Files in the top-level directory in any check-in
- cli-cases
- cull2
- dbfuzz
- json-cases
- minimized_culled
- opt-cases
- rowvalue
- session-cases
- upsert-cases
- all-db.db
- all-sql.db
- culling.md
- db-fuzz-ck.txt
- db-fuzz-init.txt
- enhanced-sql.dict
- get-files.sh
- optfuzz-db01.c
- optfuzz.c
- README.md
- rebuild-cli.sh
- rebuild-json.sh
- rebuild-main.sh
- rebuild-opt.sh
- rebuild-session.sh
- rerun-cli.sh
- rerun-db.sh
- rerun-sql.sh
- rerun-upsert.sh
- run-upsert.sh
- session-cmin.sqlar
- sessionfuzz.c
- shell.c
- sqlite3.c
- sqlite3.h
Fuzzing SQLite Using AFL
This repository contains seed files and instructions for fuzzing using the American Fuzzy Lop (AFL) fuzzer.
Prerequisites
- The SQLite source tree available from https://www.sqlite.org/src
- The latest version of AFL available from http://lcamtuf.coredump.cx/afl
- The content of this repository either as a tarball, or preferably as a Fossil clone.
How To Run The Fuzzer
Untar the AFL download into a directory which we will here call ~/afl
cd into ~/afl and type "make"
Create a subdirectory ~/afl/sqlite
cd into ~/afl/sqlite and open this repository: fossil open ~/repos/afl-sqlite.fossil
Open the SQLite source repository in a directory which we will here call ~/sqlite.
cd to ~/sqlite and build the amalgamation: ./configure; make sqlite3.c
cd back to ~/afl/sqlite and copy source files into the ~/afl/sqlite directory: cp ~/sqlite/sqlite3.[ch] .; cp ~/sqlite/tool/fuzzershell.c .
Build the instrumented fuzzershell: ../afl-gcc -O3 -o fuzzershell -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_LOAD_EXTENSION=0 -DSQLITE_NO_SYNC -DSQLITE_DEBUG -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_OMIT_RANDOMNESS -I. fuzzershell.c sqlite3.c -ldl
- Easier alternative: sh get-files.sh; sh rebuild-main.sh
- Set -DSQLITE_DEBUG to enable assert() statements.
- Set -DSQLITE_OMIT_RANDOMNESS to cause SQLite's PRNG to be seeded the same way on every run, so that the AFL fuzzer does not see variance between runs using the same input.
- The -DSQLITE_NO_SYNC is probably not needed since fuzzershell never writes to disk. But it does not hurt.
- The -DSQLITE_THREADSAFE=0 and -DSQLITE_ENABLE_LOAD_EXTENSION=0 options preclude the need for linking with -ldl and -lpthreads
Make an output directory: rm -rf out; mkdir out
Disable the AFL warning about CPU frequency: export set AFL_SKIP_CPUFREQ=1
Run the fuzzer: ../afl-fuzz -i cull2 -o out -T sql -x ../testcases/_extras/sql.dict -- ./fuzzershell
- The original test vector set designed by Michal Zalewski is in the "minimized_culled" directory. This can be substituted in place of "cull2" if desired.
- Used the "json-cases" directory instead of "cull2"/"minimized_culled" and omit the -x option if testing the json1.c extension
If the fuzzer stops for any reason (for example to update "fuzzershell.c" to a new version) then it can be restated by changing the "-i cull2" argument to just "-i-". Example:
- ../afl-fuzz -i- -o out -T sql -x ../testcases/_extras/sql.dict -- ./fuzzershell
- Omit the -x option when testing json1.c
- Easier alternative: sh rerun-sql.sh
Database File Fuzzing
The procedure above fuzzes SQL input. To fuzz the database file format, change steps (11) and (12) to be the following:
Run the fuzzer: ../afl-fuzz -i dbfuzz -o out -f testdb -T db -- ./fuzzershell --database testdb db-fuzz-ck.txt
Use the -i- trick to restart the fuzzer: ../afl-fuzz -i- -o out -f testdb -T db -- ./fuzzershell --database testdb db-fuzz-ck.txt
Easier alternative: sh rerun-db.sh
The seed database file in the dbfuzz directory are created using the db-fuzz-init.txt SQL script.
Other links
Acknowledgements
- Michal Zalewski wrote AFL and supplied the "minimized_culled" seed files.