https://github.com/cispa-syssec/wasmfuzz
WebAssembly as a Fuzzing Compilation Target @ FUZZING'24
Science Score: 39.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
✓DOI references
Found 3 DOI reference(s) in README -
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (14.0%) to scientific vocabulary
Repository
WebAssembly as a Fuzzing Compilation Target @ FUZZING'24
Basic Info
- Host: GitHub
- Owner: CISPA-SysSec
- License: apache-2.0
- Language: Rust
- Default Branch: main
- Homepage: https://doi.org/10.1145/3678722.3685531
- Size: 1.59 MB
Statistics
- Stars: 10
- Watchers: 3
- Forks: 0
- Open Issues: 0
- Releases: 1
Metadata Files
README.md
wasmfuzz: WebAssembly as a Fuzzing Compilation Target
A reasonablely good fuzzer for libfuzzer-style WebAssembly harnesses
and a suite of C/C++/Rust projects for WASM fuzzer evals.
[](./LICENSE-APACHE) [](./assets/isstaws24fuzzingmain-p5-p-30a9e696b6-80430-final.pdf) [](https://doi.org/10.1145/3678722.3685531)
wasmfuzz Fuzzer
Our WebAssembly fuzzer prototype builds on LibAFL and a custom WASM JIT. We insert instrumentation during the fuzzing campaign, and thus can run different combinations of feedback kinds on-demand.
wasmfuzz implements fast reset and runs harnesses that are designed for libfuzzer's persistent mode APIs.
Compatible modules export LLVMFuzzerTestOneInput and malloc in order to be able to allocate space for the input data and run each fuzz case. Our implementation resets the module's state after each execution.
Based on a preliminary experiment comparing wasmfuzz and cargo-fuzz (libfuzzer), fuzzing efficacy should be on-par with native fuzzers.
Installation
wasmfuzz currently requires Linux hosts for its snapshot-restore mechanism.
To build form source you need a somewhat recent stable or nightly Rust toolchain.
- From source:
cargo install --locked --force --git https://github.com/CISPA-SysSec/wasmfuzz - From a git checkout:
cargo install --locked --force --path . - Pre-built binaries: https://github.com/CISPA-SysSec/wasmfuzz/releases/download/initial-commit/wasmfuzz-x86_64-unknown-linux-gnu.2.31
Pre-built binaries are dynamically linked against an old glibc version (2.31) and should be compatible with most Linux environments.
Usage Examples
Run a simple fuzzing campaign:
wasmfuzz fuzz --timeout=1h --cores 8 --dir corpus/ the-module.wasm
Create a line coverage report:
wasmfuzz cov-html --corpus corpus/ --output report/ the-module.wasm
Other options are available via wasmfuzz --help and wasmfuzz fuzz --help.
Implementation Details
- Custom WebAssembly JIT with the Cranelift code generator as its backend.
- Input mutation is handled by LibAFL.
- Fully deterministic execution with fast-ish snapshot restore via CoW memory mappings.
- Pluggable instrumentation passes that can be configured on-the-fly.
- Simple ensemble fuzzing strategy that periodically swaps out instrumentation options.
- Coverage visualization via DWARF line debug information and DWARFv5 Embedded Source Code. We adapt Coverage.py's HTML template for our reports.
Instrumentation Passes
- Function-level, basic-block-level, edge-level code coverage:
src/instrumentation/code_coverage.rs - Arithmetic comparison distance coverage:
src/instrumentation/cmpcov.rs - Function all parameters and return values:
src/instrumentation/call_params.rs - Path coverage:
src/instrumentation/path_hash.rs - Function / loop hitcounts:
src/instrumentation/perffuzz.rs - Execution trace instruction limits:
src/instrumentation/instruction_limit.rs - Memory access values, pointer ranges:
src/instrumentation/mem.rs - Shortest input that reaches each function / basic block:
src/instrumentation/input_size.rs
Note: We have not evaluated the effectiveness of these passes yet.
Current Limitations
- Exits if a crash is found
- No core pinning
- Does not support LibAFL-style network scaling (we use simple ad-hoc in-process message passing and structure sharing, no
llmp) - No support for the WebAssembly 2.0 Component Model.
Harness Suite (./harness-suite/)
Building these requires a Docker/Podman and Python installation. Use make -C harness-suite to build all projects.
Standard
libfuzzer-compatible harness API (LLVMFuzzerTestOneInput).Mix of C/C++ and Rust targets. C/C++ projects require porting while Rust targets have drop-in support.
Currently builds 18 C/C++ and 29 Rust projects. This includes 6 out of the 19 fuzzbench targets at the moment.
Optimized builds with full debug info: Harness modules also contain their source code so we can emit coverage reports without any additional files.
We target the Lime1 series of WebAssembly, which is WebAssembly 1.0 in combination with a few standardized post-1.0 features like the bulk-memory-opt extension.
WASM Variants of Other Fuzzers (./wasm-fuzzers/)
We retrofit support for WebAssembly to native fuzzers via a KISS recompilation strategy:
wasm2c translates WASM modules to plain C files, which we then run through standard source-level fuzzing setups.
Currently, we include the following WebAssembly fuzzers in our evaluation scripts:
- wasmfuzz
- WAFL (We include a "harness stub" for compatibility)
- FuzzM (with "harness stub")
- libfuzzer via wasm2c
- AFL++ via wasm2c
- libafl_libfuzzer via wasm2c
Limitations
Symbols get renamed during the wasm2c process for native fuzzers. Due to this, hardcoded support for input-to-state mutations might be impacted due to symbol names and/or non-standard unrolled translated implementations. We have not confirmed the impact of this specific issue though.
Notes on Upstreaming
rustcsupport for-Zembed-sourcefor embedded sources in harness binaries: [Upstream PR]Alternate JIT memory allocator for Cranelift: [Upstream PR]
symboliconly supports DWARF embedded sources at exactly v12.10.0-v12.11.1: [Upstream PR]
Fuzzer Integration
We're using a patched version of WAFL that side-steps a crash when using WASM modules that have symbols: [Upstream PR]
We have applied several patches to FuzzM in order to be able to run our WASM modules:
- Wasmtime: Avoid assertion failure in
raw-cpuidcrate: fuzzm-wasmtime-0.20-fix-cpuid.patch - Wasabi: Support the Lime1 extensions by @doehyunbaek [Upstream PR]
- Wasabi: Fix parser error with overlong
call_indirectencoding [Upstream PR] - FuzzM: Adjust for Wasabi changes [Upstream PR]
- Wasmtime: Avoid assertion failure in
Owner
- Name: CISPA-SysSec
- Login: CISPA-SysSec
- Kind: organization
- Location: Germany
- Repositories: 1
- Profile: https://github.com/CISPA-SysSec
Research Group Holz @ CISPA
GitHub Events
Total
- Watch event: 4
- Delete event: 1
- Push event: 37
- Pull request event: 2
- Create event: 3
Last Year
- Watch event: 4
- Delete event: 1
- Push event: 37
- Pull request event: 2
- Create event: 3
Dependencies
- Swatinem/rust-cache v2 composite
- actions/checkout v4 composite
- dtolnay/rust-toolchain stable composite
- actions/checkout v4 composite
- actions/upload-artifact v4 composite
- baptiste0928/cargo-install v3 composite
- dtolnay/rust-toolchain stable composite
- goto-bus-stop/setup-zig v2 composite
- 301 dependencies
- scratch latest build
- ubuntu 24.04 build
- ubuntu 24.04 build