1# libprotobuf-mutator 2 3[](https://travis-ci.org/google/libprotobuf-mutator) 4[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libprotobuf-mutator) 5 6## Overview 7libprotobuf-mutator is a library to randomly mutate 8[protobuffers](https://github.com/google/protobuf). <BR> 9It could be used together with guided fuzzing engines, such as [libFuzzer](http://libfuzzer.info). 10 11## Quick start on Debian/Ubuntu 12 13Install prerequisites: 14 15``` 16sudo apt-get update 17sudo apt-get install protobuf-compiler libprotobuf-dev binutils cmake \ 18 ninja-build liblzma-dev libz-dev pkg-config autoconf libtool 19``` 20 21Compile and test everything: 22 23``` 24mkdir build 25cd build 26cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug 27ninja check 28``` 29 30Clang is only needed for libFuzzer integration. <BR> 31By default, the system-installed version of 32[protobuf](https://github.com/google/protobuf) is used. However, on some 33systems, the system version is too old. You can pass 34`LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON` to cmake to automatically download and 35build a working version of protobuf. 36 37Installation: 38 39``` 40ninja 41sudo ninja install 42``` 43 44This installs the headers, pkg-config, and static library. 45By default the headers are put in `/usr/local/include/libprotobuf-mutator`. 46 47## Usage 48 49To use libprotobuf-mutator simply include 50[mutator.h](/src/mutator.h) and 51[mutator.cc](/src/mutator.cc) into your build files. 52 53The `ProtobufMutator` class implements mutations of the protobuf 54tree structure and mutations of individual fields. 55The field mutation logic is very basic -- 56for better results you should override the `ProtobufMutator::Mutate*` 57methods with more sophisticated logic, e.g. 58using [libFuzzer](http://libfuzzer.info)'s mutators. 59 60To apply one mutation to a protobuf object do the following: 61 62``` 63class MyProtobufMutator : public protobuf_mutator::Mutator { 64 public: 65 // Optionally redefine the Mutate* methods to perform more sophisticated mutations. 66} 67void Mutate(MyMessage* message) { 68 MyProtobufMutator mutator; 69 mutator.Seed(my_random_seed); 70 mutator.Mutate(message, 200); 71} 72``` 73 74See also the `ProtobufMutatorMessagesTest.UsageExample` test from 75[mutator_test.cc](/src/mutator_test.cc). 76 77## Integrating with libFuzzer 78LibFuzzerProtobufMutator can help to integrate with libFuzzer. For example 79 80``` 81#include "src/libfuzzer/libfuzzer_macro.h" 82 83DEFINE_PROTO_FUZZER(const MyMessageType& input) { 84 // Code which needs to be fuzzed. 85 ConsumeMyMessageType(input); 86} 87``` 88 89Please see [libfuzzer_example.cc](/examples/libfuzzer/libfuzzer_example.cc) as an example. 90 91### Mutation post-processing (experimental) 92Sometimes it's necessary to keep particular values in some fields without which the proto 93is going to be rejected by fuzzed code. E.g. code may expect consistency between some fields 94or it may use some fields as checksums. Such constraints are going to be significant bottleneck 95for fuzzer even if it's capable of inserting acceptable values with time. 96 97PostProcessorRegistration can be used to avoid such issue and guide your fuzzer towards interesting 98code. It registers callback which will be called for each message of particular type after each mutation. 99 100``` 101DEFINE_PROTO_FUZZER(const MyMessageType& input) { 102 static PostProcessorRegistration reg = { 103 [](MyMessageType* message, unsigned int seed) { 104 TweakMyMessage(message, seed); 105 }}; 106 107 // Code which needs to be fuzzed. 108 ConsumeMyMessageType(input); 109} 110``` 111Optional: Use seed if callback uses random numbers. It may help later with debugging. 112 113Note: You can add callback for any nested message and you can add multiple callbacks for 114the same message type. 115``` 116DEFINE_PROTO_FUZZER(const MyMessageType& input) { 117 static PostProcessorRegistration reg1 = { 118 [](MyMessageType* message, unsigned int seed) { 119 TweakMyMessage(message, seed); 120 }}; 121 static PostProcessorRegistration reg2 = { 122 [](MyMessageType* message, unsigned int seed) { 123 DifferentTweakMyMessage(message, seed); 124 }}; 125 static PostProcessorRegistration reg_nested = { 126 [](MyMessageType::Nested* message, unsigned int seed) { 127 TweakMyNestedMessage(message, seed); 128 }}; 129 130 // Code which needs to be fuzzed. 131 ConsumeMyMessageType(input); 132} 133``` 134## UTF-8 strings 135"proto2" and "proto3" handle invalid UTF-8 strings differently. In both cases 136string should be UTF-8, however only "proto3" enforces that. So if fuzzer is 137applied to "proto2" type libprotobuf-mutator will generate any strings including 138invalid UTF-8. If it's a "proto3" message type, only valid UTF-8 will be used. 139 140## Users of the library 141* [Chromium](https://cs.chromium.org/search/?q=DEFINE_.*._PROTO_FUZZER%5C\() 142* [Envoy](https://github.com/envoyproxy/envoy/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code) 143* [LLVM](https://github.com/llvm-mirror/clang/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code) 144 145## Bugs found with help of the library 146 147### Chromium 148* [AppCache exploit](http://www.powerofcommunity.net/poc2018/ned.pdf) ([Actual still restricted bug](https://bugs.chromium.org/p/chromium/issues/detail?id=888926)) 149* [Stack Buffer Overflow in QuicClientPromisedInfo](https://bugs.chromium.org/p/chromium/issues/detail?id=777728) 150* [null dereference in sqlite3ExprCompare](https://bugs.chromium.org/p/chromium/issues/detail?id=911251) 151### Envoy 152* [strftime overflow](https://github.com/envoyproxy/envoy/pull/4321) 153* [Heap-use-after-free in Envoy::Upstream::SubsetLoadBalancer::updateFallbackSubset](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8028) 154* [Heap-use-after-free in Envoy::Secret::SecretManagerImpl](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11231) 155* [Heap-buffer-overflow in Envoy::Http::HeaderString](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10038) 156 157## Related materials 158* [Attacking Chrome IPC: Reliably finding bugs to escape the Chrome sandbox](https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc) 159* [Structure-aware fuzzing for Clang and LLVM with libprotobuf-mutator](https://www.youtube.com/watch?v=U60hC16HEDY) 160* [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md) 161