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``` 101static protobuf_mutator::libfuzzer::PostProcessorRegistration<MyMessageType> reg = { 102 [](MyMessageType* message, unsigned int seed) { 103 TweakMyMessage(message, seed); 104 }}; 105 106DEFINE_PROTO_FUZZER(const MyMessageType& input) { 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 113Important: Callbacks should be deterministic and avoid modifying good messages. 114Callbacks are called for both: mutator generated and user provided inputs, like 115corpus or bug reproducer. So if callback performs unnecessary transformation it 116may corrupt the reproducer so it stops triggering the bug. 117 118Note: You can add callback for any nested message and you can add multiple callbacks for 119the same message type. 120``` 121static PostProcessorRegistration<MyMessageType> reg1 = { 122 [](MyMessageType* message, unsigned int seed) { 123 TweakMyMessage(message, seed); 124 }}; 125static PostProcessorRegistration<MyMessageType> reg2 = { 126 [](MyMessageType* message, unsigned int seed) { 127 DifferentTweakMyMessage(message, seed); 128 }}; 129static PostProcessorRegistration<MyMessageType::Nested> reg_nested = { 130 [](MyMessageType::Nested* message, unsigned int seed) { 131 TweakMyNestedMessage(message, seed); 132 }}; 133 134DEFINE_PROTO_FUZZER(const MyMessageType& input) { 135 // Code which needs to be fuzzed. 136 ConsumeMyMessageType(input); 137} 138``` 139## UTF-8 strings 140"proto2" and "proto3" handle invalid UTF-8 strings differently. In both cases 141string should be UTF-8, however only "proto3" enforces that. So if fuzzer is 142applied to "proto2" type libprotobuf-mutator will generate any strings including 143invalid UTF-8. If it's a "proto3" message type, only valid UTF-8 will be used. 144 145## Extensions 146Currently the library does not mutate 147[extensions](https://developers.google.com/protocol-buffers/docs/proto#extensions). 148This can be a problem if extension contains required fields so the library will not 149be able to change the message into valid initialized state. 150You can use [post processing hooks](#mutation-post-processing-experimental) to 151cleanup/initialize the message as workaround. 152 153## Users of the library 154* [Chromium](https://cs.chromium.org/search/?q=DEFINE_.*._PROTO_FUZZER%5C\() 155* [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) 156* [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) 157 158## Bugs found with help of the library 159 160### Chromium 161* [AppCache exploit](http://www.powerofcommunity.net/poc2018/ned.pdf) ([Actual still restricted bug](https://bugs.chromium.org/p/chromium/issues/detail?id=888926)) 162* [Stack Buffer Overflow in QuicClientPromisedInfo](https://bugs.chromium.org/p/chromium/issues/detail?id=777728) 163* [null dereference in sqlite3ExprCompare](https://bugs.chromium.org/p/chromium/issues/detail?id=911251) 164### Envoy 165* [strftime overflow](https://github.com/envoyproxy/envoy/pull/4321) 166* [Heap-use-after-free in Envoy::Upstream::SubsetLoadBalancer::updateFallbackSubset](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8028) 167* [Heap-use-after-free in Envoy::Secret::SecretManagerImpl](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11231) 168* [Heap-buffer-overflow in Envoy::Http::HeaderString](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10038) 169 170## Related materials 171* [Attacking Chrome IPC: Reliably finding bugs to escape the Chrome sandbox](https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc) 172* [Structure-aware fuzzing for Clang and LLVM with libprotobuf-mutator](https://www.youtube.com/watch?v=U60hC16HEDY) 173* [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md) 174