Fuzzing javascript nodejs/npm WebAssembly parsing library with jsfuzz

I asked recently on twitter what should be my next blogpost subject and voters choose this one, so here it is.

In this short blogpost, I will first introduce jsfuzz, a coverage-guided javascript fuzzer for nodejs/npm packages. Then, I’ll discuss about the wasm binary parsing library I decided to target. Finally, I’ll explain how to create a jsfuzz target script and show the OOM/DoS crash I found.

Just a quick reminder before we start, if you are interested about WebAssembly security (both reversing and fuzzing), I decided to convert my 4-day live training into recorded courses.

More details about my courses here.

1. Javascript fuzzer: Jsfuzz

Jsfuzz is a coverage-guided fuzzer for javascript node.js packages developped by Fuzzit. The typical bugs found by jsfuzz are unhandled exceptions, logic bugs, Denial-of-Service (DoS) caused by hangs and excessive memory usage (OOM).

Jsfuzz is both user-friendly and efficient, especially when fuzzing parsing libraries. You will only need to implement the following function to start fuzzing your target. All the fuzzing/mutation logic, coverage collection and crash detection will be handle by jsfuzz.

jsfuzz wasm npm nodejs package fuzzing
Minimal custom jsfuzz target script

2. Target: @webassemblyjs/wasm-parser

webassemblyjs is a set of 22 dedicated packages for WebAssembly module manipulation. Most of them are really popular npm package with more than 6 millions weekly downloads each, like those ones:

I decided to target @webassemblyjs/wasm-parser because the API is really simple and also because I think jsfuzz mutation algorithm will be more efficient on binary file.
wasm api webassembly api fuzzing npm
wasm-parser npm package simple API
wasm npm parser popular package fuzzing

3. Setup the fuzzing javascript target script

The process to setup a fuzz target script with jsfuzz is extremely simple. The first step is to create a corpus of valid WebAssembly module like the ones on Mozilla github repository: MDN webassembly-examples.

Then, run the fuzzer with the following command:

jsfuzz fuzz-wasm-parser.js corpus-wasm

You should immediately trigger some valid error/exception and you will need to customized the fuzz target to catch and ignored them like in the following code (available here).

wasm fuzzer jsfuzz webassembly parser
wasm-parser complete fuzz target

4. Result: OOM/DoS of javascript nodejs triggered

Once most common exceptions are handled using try/catch, jsfuzz will start to generate fuzzing status logs and eventually crash like the following picture.

This bug is triggered really quickly (less than a minute) by the fuzzer with my wasm module corpus.

I quickly minimized the crashing buffer, create a reproducer JS file and directly open an issue on webassemblyjs github repository.

wasm npm parser crash reproducer webassembly fuzzing
Reproducer for DoS/OOM bugs found

In October 2019, Fuzzit team found another bug in this library but not in the same npm package: @webassemblyjs/wast-parser: Crash/TypeError.

jsfuzz crash nodejs npm package wasm webassembly
jsfuzz crash after less than a minute

5. Conclusion

I strongly invite every JavaScript/nodejs developer to give a try to Jsfuzz. It will help you when fuzzing npm package, finding bugs, create edge-cases inputs and easily get code coverage visibility. Kudos again to Fuzzit for sharing this fuzzer publicly.

Final reminder, If you want to learn/discover more about WebAssembly security (both reversing and fuzzing), I decided to convert my 4-day live training into recorded courses.

More details about my courses here.

If you want to contact me for consulting, please DM me on Twitter/LinkedIn or use the following contact form.

Patrick Ventuzelo / @Pat_Ventuzelo

FREE Courses & Training

Enter your email and we'll send you a bundle of awesome resources. 100% free - 100% awesome.

Any questions about our services and trainings ?

Get in touch today with any questions that you might have.