This project includes directions and a patch (webkit.patch) to make fuzzing WebKit easier. We use the WebKitGTK+ implementation, running on Linux as the fuzzing target. This patch and instructions will build WebKitGTK+ with ASAN and make some changes that make fuzzing easier.
The patch file was made with WebKitGTK+ version 2.34.6 and/or the WebKit Github repo as of commit 690b38f1f792a1d9c72f3fcb6f8add83090d459a. It might not work as is on other versions.
List of changes:
-
Fixes to be able to build WebKitGTK+ with ASan.
-
Changed window.alert() implementation to immediately call the garbage collector instead of displaying a message window.
-
As soon as any web process crashes, exit the main process with the same exit code.
-
Created a custom target binary (webkitfuzz).
-
Enable javascript console logging to terminal.
There are two options for building WebKitGTK+: WebKitGTK+ stable release tarball or the WebKit git repo. These instructions support both options.
-
Get the code by either downloading and extracting the WebKitGTK+ tarball version 2.34.6 or cloning the WebKit git repo as of commit 690b38f1f792a1d9c72f3fcb6f8add83090d459a.
-
Apply the changes in webkit.patch by running one of the following commands from the root of your WebKit tree:
patch -p1 < webkit.patch(tarball) orgit apply webkit.patch(git repo) -
Build WebKit by running the build script (
build_webkitfuzz.sh) from the root of the WebKit tree (webkitgtk-2.34.6/orWebKit/). This script will place the built files into thebuild/directory.During the
cmakestage, WebKit will likely yell at you to install requisite libraries. Many dependencies are turned off with theENABLEandUSEflags, but many are still required.The build process works with either
makeorninja. Our scripts usemake, but replacing withninjashould work as well.NOTE: The official WebKit build instructions recommend building with
Tools/Scripts/build-webkit. In our experience this is a less reliable process for the purposes of building a separate target binary that will call and start the WebKit processes. -
Run the fuzzer binary from the build directory (
build/) with the following command. The sample can either be a path to a file or a URL beginning withhttporhttps. If you don't set alog_path, then the crash will instead print to stdout.
ASAN_OPTIONS=detect_leaks=0,exitcode=42,log_path=asan_logs/crash ASAN_SYMBOLIZER_PATH=</path/to/llvm-symbolizer> LD_LIBRARY_PATH=lib/ ./bin/webkitfuzz </path/to/sample> <timeout in sec>
To debug the WebKit Web Process with gdb you can use gdbserver. Run webkitfuzz
with the following command. I suggest using a long timeout, like 3600s or 1 hr,
to ensure you have enough time to debug.
WEB_PROCESS_CMD_PREFIX='/usr/bin/gdbserver localhost:8080' ASAN_OPTIONS=detect_leaks=0,exitcode=42 LD_LIBRARY_PATH=lib/ ./bin/webkitfuzz http://poc.com 3600
From another terminal, you'll connect to the gdbserver as:
$ gdb bin/WebKitWebProcess
(gdb) target remote localhost:8081
If you're running on the same machine, then I suggest also running the following to save a lot of time. This will tell gdb that it doesn't have to send the symbols from the server to the client, but actually you can find them locally at this path.
(gdb) set sysroot /
If your build is succeeding, but you're not seeing the expected output during a run, check that your webkitfuzz is actually using WebKit executables and libraries that you build rather than the default ones on your machine:
- Make sure you include the environment variable:
LD_LIBRATY_PATH=lib/ - When webkitfuzz is running in another terminal run
ps -aux | grep WebKitto check that theWebKitWebProcessandWebKitNetworkProcessthat are running are from your build directory. - Check that webkitfuzz is using the webkit and javascriptcore libraries from
your build by running:
ldd bin/webkitfuzzand checking whatlibwebkit2gtk-4.0.so.37andlibjavascriptcoregtk-4.0.so.18point to.
Depending on what your fuzzing set-up and what you're trying to fuzz the following additional cmake flags can reduce build time and dependencies:
-DENABLE_VIDEO=OFF
-DENABLE_WEB_AUDIO=OFF
-DENABLE_GAMEPAD=OFF
-DENABLE_MEDIA_STREAM=OFF
Our script currently sets the -DUSE_SYSTEM_MALLOC=ON. When
-DUSE_SYSTEM_MALLOC=OFF, WebKit's bmalloc is used in of the system's malloc. bmalloc adds exploit mitigations that WebKit has implemented such as IsoHeap and GigaCage. Using the system's malloc may lead to better ASAN coverage. Change this flag based on your fuzzing needs.
If the symobilizing doesn't seem to be working, make sure that you've set ASAN_SYMBOLIZER_PATH to the version of the symbolizer that matches which clang version you're using to build WebKit. Among the first console prints when you run the build script, you'll see which compiler is running. For example:
-- The C compiler identification is Clang 13.0.1
-- The CXX compiler identification is Clang 13.0.1
In this case you'd want to make sure you link to your llvm-symoblizer-13 binary since you're using clang-13.