Some harness code for using afl and python-afl to fuzz-test h11.
See Alex Gaynor's tutorial, or just:
sudo apt install afl
pip install python-afl
cd fuzz
PYTHONPATH=.. py-afl-fuzz -o results -i afl-server-examples/ -- python ./afl-server.py
Note 1: You may need to add AFL_SKIP_CPUFREQ=1
if you want to play
with it on a laptop and don't want to bother messing with your cpufreq
config.
Note 2: You may see some false "hangs" due to afl's aggressive default
timeouts. I think this might be intentional, and serve to discourage
afl from wasting time exploring arbitrarily longer and longer inputs?
Or you can set the timeout explicitly with -t $MILLISECONDS
.
Note 3: Parallel fuzzing is a good thing.
Right now we just have a simple test that throws garbage at the server
receive_data
and makes sure that it's either accepted or raises
RemoteProtocolError
, never any other exceptions. (As an example of
how even this relatively simple thing can catch bugs, here's a bug in
gunicorn that was
found by this approach, and here's a bug this found in h11... though
that one's so simple that even basic fuzz-testing would have found it
without any of afl's cleverness.)
- Teach afl-server.py to watch the state machine and send responses back to get things unpaused, to allow for fuzzing of pipelined requests and unsuccessful protocol switches
- Add a client-side fuzzer too
- Add a dictionary tuned for HTTP
- add more seed examples:
Connection: close
? more complicated chunked examples? pipelining and protocol switch examples? - check that the all-at-once and byte-by-byte processing give the same event stream (modulo data splits)
- maybe should split apart fancy checks versus non-fancy checks b/c speed is important