├── Dockerfile ├── README.md ├── brotli ├── decode_fuzzer.html ├── decode_fuzzer.js └── decode_fuzzer.wasm ├── checkout_build_install_llvm.sh ├── compile_libfuzzer.sh ├── compile_sqlite.sh ├── crash ├── crash.cc ├── crash.html ├── crash.js └── crash.wasm ├── generate_links.py ├── index.html ├── lzma ├── 7z_fuzzer.dict ├── 7z_fuzzer.html ├── 7z_fuzzer.js ├── 7z_fuzzer.wasm ├── filters_fuzzer.html ├── filters_fuzzer.js ├── filters_fuzzer.wasm ├── lzma2dec_fuzzer.html ├── lzma2dec_fuzzer.js ├── lzma2dec_fuzzer.wasm ├── lzma2enc_fuzzer.html ├── lzma2enc_fuzzer.js ├── lzma2enc_fuzzer.wasm ├── lzmadec_fuzzer.html ├── lzmadec_fuzzer.js ├── lzmadec_fuzzer.wasm ├── lzmaenc_fuzzer.html ├── lzmaenc_fuzzer.js ├── lzmaenc_fuzzer.wasm ├── ppmdenc_fuzzer.html ├── ppmdenc_fuzzer.js ├── ppmdenc_fuzzer.wasm ├── xzdec_fuzzer.dict ├── xzdec_fuzzer.html ├── xzdec_fuzzer.js ├── xzdec_fuzzer.wasm ├── xzenc_fuzzer.html ├── xzenc_fuzzer.js └── xzenc_fuzzer.wasm ├── meetup-Fuzzing-Native-Applications-in-Browsers-With-WASM.pdf ├── out └── dummy-file-for-git ├── shell-for-console.html ├── sqlite-fast ├── sqlite.html ├── sqlite.js └── sqlite.wasm ├── sqlite ├── sqlite.html ├── sqlite.js └── sqlite.wasm ├── sqlite3-ossfuzz.c ├── sqlite3.c ├── sqlite3.h └── template.html /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update && \ 4 | apt-get upgrade -y && \ 5 | apt-get install -y libc6-dev binutils libgcc-5-dev && \ 6 | apt-get autoremove -y 7 | 8 | ENV SRC /src 9 | ENV OUT /out 10 | ENV WORK /work 11 | RUN mkdir $SRC $OUT $WORK 12 | 13 | COPY checkout_build_install_llvm.sh /root/ 14 | RUN /root/checkout_build_install_llvm.sh 15 | 16 | RUN git clone https://github.com/emscripten-core/emsdk.git /src/emsdk 17 | WORKDIR /src/emsdk 18 | RUN apt-get install -y python 19 | RUN ./emsdk install latest 20 | RUN ./emsdk activate latest 21 | RUN printf "LLVM_ROOT = '/work/build/bin'\nBINARYEN_ROOT = '/src/emsdk/upstream'\nEMSCRIPTEN_ROOT = '/src/emsdk/upstream/emscripten'\nNODE_JS = '/src/emsdk/node/12.9.1_64bit/bin/node'\nTEMP_DIR = '/tmp'\nCOMPILER_ENGINE = NODE_JS\nJS_ENGINES = [NODE_JS]" > /src/.emscripten-llvm-override 22 | 23 | # Activate the emsdk and don't let it overwrite the .emscripten file we need to 24 | # point to our LLVM build. 25 | RUN echo "/src/emsdk/emsdk activate && source /src/emsdk/emsdk_env.sh &> /dev/null && cp /src/.emscripten-llvm-override /root/.emscripten" >> /root/.bashrc 26 | # RUN echo "PATH=$PATH:/src/emsdk:/src/emsdk/upstream/emscripten:/src/emsdk/node/12.9.1_64bit/bin" >> /root/.bashrc 27 | 28 | WORKDIR /src/llvm-project/compiler-rt/lib/fuzzer 29 | COPY compile_libfuzzer.sh /src 30 | RUN /src/compile_libfuzzer.sh 31 | 32 | COPY sqlite3.c /src 33 | COPY sqlite3-ossfuzz.c /src 34 | COPY sqlite3.h /src 35 | COPY compile_sqlite.sh /src 36 | COPY shell-for-console.html /src/shell-for-console.html 37 | 38 | WORKDIR /src 39 | 40 | ENTRYPOINT /bin/bash -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demos From My Talk on Fuzzing Native Code in Web Browsers using WASM. 2 | 3 | This repo contains demos and examples from the talk ([Talk slides](meetup-Fuzzing-Native-Applications-in-Browsers-With-WASM.pdf)) I gave on fuzzing C/C++ programs in-browser with libFuzzer using [WebAssembly](https://webassembly.org/). 4 | 5 | It contains [demos of in-browser fuzzing](https://jonathanmetzman.github.io/wasm-fuzzing-demo/index.html) 6 | as well as some tools to help users build libFuzzer targets for WASM themselves. 7 | 8 | Note that this is not at all about fuzzing the WASM runtime. It is about fuzzing programs (e.g. SQLite, lzma) running in the WASM VM. Because this is running in the WebAssembly runtime, the demos are actually runnning in your web browser, not on a remote server. 9 | 10 | # Fuzzing in WASM 11 | 12 | I have made a docker image to make building fuzz targets easier since the version of clang currently (12/14/2019) shipped by emscripten 13 | crashes when libFuzzer's coverage instrumentation is used. The docker image builds clang, downloads/installs emscripten 14 | and then builds libFuzzer (targeting WASM). 15 | From the image you can build whatever program you want by using the compiler flag `-fsanitize-coverage=inline-8bit-counters` and then linking against libFuzzer. See the docs on [emscripten.org](https://emscripten.org/) for more info on building projects to run in the WASM VM. 16 | Follow the steps in the section to build the SQLite fuzzer. This should be a good starting point for building other projects yourself. 17 | 18 | 19 | # Building the [SQLite example](https://jonathanmetzman.github.io/wasm-fuzzing-demo/sqlite/sqlite.html) 20 | 21 | Run the following commands from the root of this repository. 22 | 23 | 1. `docker build -f Dockerfile -t gcr.io/libfuzzer-wasm .` 24 | 25 | 2. `docker run -v $PWD/out:/out -it gcr.io/libfuzzer-wasm` 26 | 27 | 3. `bash /src/compile_sqlite.sh # Run this inside of the docker image` 28 | 29 | 4. `exit` 30 | 31 | 5. Start web server to view the output. 32 | `cd out && python -m SimpleHTTPServer` 33 | 34 | 6. Open dev tools console in your browser and then go to localhost:8000/sqlite.html 35 | 36 | # FAQ 37 | ## Why does the fuzzer I built write output only to the console and not the webpage (as the demos do)? 38 | Writing to the webpage (as I cover in the talk) requries making an invasive change to libFuzzer that also hurts performance 39 | significantly (~10-20X, though I may have implemented it badly). Therefore I didn't include this when I added basic support for emscripten to libFuzzer. 40 | -------------------------------------------------------------------------------- /brotli/decode_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/brotli/decode_fuzzer.wasm -------------------------------------------------------------------------------- /checkout_build_install_llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | # Copyright 2016 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | ################################################################################ 17 | 18 | LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python2.7 g++-multilib" 19 | apt-get install -y $LLVM_DEP_PACKAGES 20 | 21 | # Checkout 22 | CHECKOUT_RETRIES=10 23 | function clone_with_retries { 24 | REPOSITORY=$1 25 | LOCAL_PATH=$2 26 | CHECKOUT_RETURN_CODE=1 27 | 28 | # Disable exit on error since we might encounter some failures while retrying. 29 | set +e 30 | for i in $(seq 1 $CHECKOUT_RETRIES); do 31 | rm -rf $LOCAL_PATH 32 | git clone $REPOSITORY $LOCAL_PATH 33 | CHECKOUT_RETURN_CODE=$? 34 | if [ $CHECKOUT_RETURN_CODE -eq 0 ]; then 35 | break 36 | fi 37 | done 38 | 39 | # Re-enable exit on error. If checkout failed, script will exit. 40 | set -e 41 | return $CHECKOUT_RETURN_CODE 42 | } 43 | 44 | # Use chromium's clang revision 45 | mkdir $SRC/chromium_tools 46 | cd $SRC/chromium_tools 47 | git clone https://chromium.googlesource.com/chromium/src/tools/clang 48 | cd clang 49 | 50 | LLVM_SRC=$SRC/llvm-project 51 | clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC 52 | 53 | mkdir -p $WORK/build 54 | cd $WORK/build 55 | 56 | TARGET_TO_BUILD="host;WebAssembly" 57 | 58 | PROJECTS_TO_BUILD="compiler-rt;clang;lld" 59 | cmake -G "Ninja" \ 60 | -DLIBCXX_ENABLE_SHARED=OFF -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON -DLIBCXXABI_ENABLE_SHARED=OFF \ 61 | -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ 62 | -DLLVM_ENABLE_PROJECTS=$PROJECTS_TO_BUILD \ 63 | $LLVM_SRC/llvm 64 | ninja install 65 | 66 | # rm -rf $LLVM_SRC 67 | # rm -rf $SRC/chromium_tools 68 | # apt-get remove --purge -y $LLVM_DEP_PACKAGES 69 | # apt-get autoremove -y 70 | -------------------------------------------------------------------------------- /compile_libfuzzer.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | source /src/emsdk/emsdk_env.sh 4 | cd /src/llvm-project/compiler-rt/lib/fuzzer 5 | CXX=emcc bash build.sh 6 | 7 | -------------------------------------------------------------------------------- /compile_sqlite.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | emcc --shell-file /src/shell-for-console.html -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ALLOW_MEMORY_GROWTH=1 -fsanitize-coverage=inline-8bit-counters /src/sqlite3.c /src/sqlite3-ossfuzz.c /src/llvm-project/compiler-rt/lib/fuzzer/libFuzzer.a -o $OUT/sqlite.html 4 | -------------------------------------------------------------------------------- /crash/crash.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 6 | if (size > 0 && data[0] == 'H') 7 | if (size > 1 && data[1] == 'I') 8 | if (size > 2 && data[2] == '!') { 9 | uint8_t* p = (uint8_t*) malloc(10); 10 | free(p); 11 | return p[0]; 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /crash/crash.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/crash/crash.wasm -------------------------------------------------------------------------------- /generate_links.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | def find_html(directory): 5 | for filename in os.listdir(directory): 6 | path = os.path.join(directory, filename) 7 | if path.endswith('.html'): 8 | yield path 9 | 10 | 11 | def get_links(paths): 12 | links = [] 13 | for path in paths: 14 | name, _ = os.path.splitext(path) 15 | links.append(f'{name}
') 16 | return links 17 | 18 | def main(): 19 | directory = sys.argv[1] 20 | paths = find_html(directory) 21 | print('\n'.join(get_links(paths))) 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 |

sqlite

11 | sqlite
12 |

Crash (with ASAN stacktrace)

13 | crash
14 |

brotli

15 | brotli/decode_fuzzer
16 |

lzma

17 | lzma/lzmadec_fuzzer
18 | lzma/xzenc_fuzzer
19 | lzma/filters_fuzzer
20 | lzma/lzma2dec_fuzzer
21 | lzma/lzma2enc_fuzzer
22 | lzma/lzmaenc_fuzzer
23 | lzma/7z_fuzzer
24 | lzma/ppmdenc_fuzzer
25 | lzma/xzdec_fuzzer
26 |

sqlite-fast (need to open dev tools)

27 | sqlite
28 |

Project Git Repo

29 | Project Git Repo
30 | -------------------------------------------------------------------------------- /lzma/7z_fuzzer.dict: -------------------------------------------------------------------------------- 1 | # The 7z header signature. 2 | "7z\xbc\xaf\x27\x1c" 3 | 4 | # See sdk/C/7zDec.c for the codec ids. 5 | # Codec id for "Copy" 6 | "\x00" 7 | # Codec id for "Delta" 8 | "\x03" 9 | # Codec id for "LZMA2" 10 | "\x21" 11 | # Codec id for "LZMA" 12 | "\x03\x01\x01" 13 | # Codec id for "BCJ" 14 | "\x03\x03\x01\x03" 15 | # Codec id for "BCJ2" 16 | "\x03\x03\x01\x1B" 17 | # Codec id for "PPC" 18 | "\x03\x03\x02\x05" 19 | # Codec id for "IA64" 20 | "\x03\x03\x04\x01" 21 | # Codec id for "ARM" 22 | "\x03\x03\x05\x01" 23 | # Codec id for "ARMT" 24 | "\x03\x03\x07\x01" 25 | # Codec id for "SPARC" 26 | "\x03\x03\x08\x05" 27 | # Codec id for "PPMD" 28 | "\x03\x04\x01" 29 | -------------------------------------------------------------------------------- /lzma/7z_fuzzer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | Emscripten-Generated Code 15 | 111 | 112 | 113 | 114 | image/svg+xml 1204 | 1205 | 1206 |
1207 |
Downloading...
1208 | 1209 | 1210 | Resize canvas 1211 | Lock/hide mouse pointer     1212 | 1214 | 1215 | 1216 | 1217 |
1218 | 1219 |
1220 | 1221 | 1222 |
1223 | 1224 |
1225 | 1226 | 1227 | 1304 | 1305 | More Demos
1306 | README.md 1307 | 1308 | 1309 | 1310 | 1311 | -------------------------------------------------------------------------------- /lzma/7z_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/7z_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/filters_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/filters_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/lzma2dec_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/lzma2dec_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/lzma2enc_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/lzma2enc_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/lzmadec_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/lzmadec_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/lzmaenc_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/lzmaenc_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/ppmdenc_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/ppmdenc_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/xzdec_fuzzer.dict: -------------------------------------------------------------------------------- 1 | # XZ_SIG 2 | "\xfd7zXZ\x00" 3 | -------------------------------------------------------------------------------- /lzma/xzdec_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/xzdec_fuzzer.wasm -------------------------------------------------------------------------------- /lzma/xzenc_fuzzer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/lzma/xzenc_fuzzer.wasm -------------------------------------------------------------------------------- /meetup-Fuzzing-Native-Applications-in-Browsers-With-WASM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/meetup-Fuzzing-Native-Applications-in-Browsers-With-WASM.pdf -------------------------------------------------------------------------------- /out/dummy-file-for-git: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shell-for-console.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LibFuzzer in WASM (Open Console Before Visting Page) 7 |

LibFuzzer in WASM (Open Console Before Visting Page)

8 | 62 | 63 | 64 |
65 |
emscripten
66 |
Downloading...
67 |
68 | 69 |
70 |
71 | 72 |
73 | 74 |
75 | 76 | 172 | {{{ SCRIPT }}} 173 | 174 | 175 | -------------------------------------------------------------------------------- /sqlite-fast/sqlite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | Emscripten-Generated Code 15 | 69 | 70 | 71 |

Open dev tools console before visiting this page to view libFuzzer's output

72 |
73 |
emscripten
74 |
Downloading...
75 |
76 | 77 |
78 |
79 | 80 |
81 | 82 |
83 |
84 | 178 | 179 | More Demos
180 | README.md 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /sqlite-fast/sqlite.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/sqlite-fast/sqlite.wasm -------------------------------------------------------------------------------- /sqlite/sqlite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | Emscripten-Generated Code 15 | 69 | 70 | 71 |
72 |
emscripten
73 |
Downloading...
74 |
75 | 76 |
77 |
78 | 79 |
80 | 81 |
82 |

83 | 179 | 180 | More Demos
181 | README.md 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /sqlite/sqlite.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanmetzman/wasm-fuzzing-demo/6e92cf17ca2d7400e7a483d4b60eae48832f03e5/sqlite/sqlite.wasm -------------------------------------------------------------------------------- /sqlite3-ossfuzz.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 Google Inc. All Rights Reserved. 2 | ** Licensed under the Apache License, Version 2.0 (the "License"); 3 | ** 4 | ** Derived from the public domain SQLite (https://sqlite.org) sources. 5 | */ 6 | /* 7 | ** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service. 8 | ** (https://github.com/google/oss-fuzz) 9 | */ 10 | #include 11 | #include 12 | #include "sqlite3.h" 13 | 14 | /* 15 | ** Progress handler callback 16 | */ 17 | static int progress_handler(void *pReturn) { 18 | return *(int*)pReturn; 19 | } 20 | 21 | /* 22 | ** Callback for sqlite3_exec(). 23 | */ 24 | static int exec_handler(void *pCnt, int argc, char **argv, char **namev){ 25 | int i; 26 | for(i=0; i>= 1; 65 | progressArg = uSelector & 1; uSelector >>= 1; 66 | 67 | /* Bit 2 of the selector enables foreign key constraints */ 68 | sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc); 69 | uSelector >>= 1; 70 | 71 | /* Remaining bits of the selector determine a limit on the number of 72 | ** output rows */ 73 | execCnt = uSelector + 1; 74 | 75 | /* Run the SQL. The sqlite_exec() interface expects a zero-terminated 76 | ** string, so make a copy. */ 77 | zSql = sqlite3_mprintf("%.*s", (int)size, data); 78 | sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg); 79 | 80 | /* Cleanup and return */ 81 | sqlite3_free(zErrMsg); 82 | sqlite3_free(zSql); 83 | sqlite3_close(db); 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Emscripten-Generated Code 7 | 61 | 62 | 63 |
64 |
emscripten
65 |
Downloading...
66 |
67 | 68 |
69 |
70 | 71 |
72 | 73 |
74 | 75 | 173 | {{{ SCRIPT }}} 174 | 175 | 176 | --------------------------------------------------------------------------------