An automated(+beginner friendly) setup for compiling and fuzzing Redis w/ AFL++.
More info about the process can be found here: https://0xbigshaq.github.io/2022/03/10/fuzzing-harder-part1
To build, run:
docker build -t afl-redis-setup .
To start the container with a shared volume (in order for the results to be saved in the hosting machine)
docker run --rm -v $(pwd):/root/host-share --privileged -it --workdir=/root afl-redis-setup
To run a smoke test before starting the fuzzing session, run:
AFL_PRELOAD=preeny/x86_64-linux-gnu/desock.so afl-showmap -m2048 -o/dev/null ./redis/src/redis-server ./redis.conf < <(echo "PING");
output:
[+] Hash of coverage map: 5a20352f5b1cb7e5
[+] Captured 1156 tuples (map size 38422, highest value 8, total values 2511) in '/dev/null'.
AFL_PRELOAD=preeny/x86_64-linux-gnu/desock.so afl-showmap -m2048 -o/dev/null ./redis/src/redis-server ./redis.conf < <(echo "SHUTDOWN");
output:
[+] Hash of coverage map: 653954010db919f3
[+] Captured 1170 tuples (map size 38422, highest value 8, total values 2553) in '/dev/null'.
To start fuzzing, just run ./fuzz.sh
file :^)
Note: The fuzzing speed/execs per second will not be high if you don't have a strong machine. This can be solved in two approaches: The first approach is 'Trying Harder', to apply this, just keep reading through the Distributed Fuzzing section below. The 2nd approach is 'Trying Smarter', this approach involves patching the server in a more specific way that cuts down the performance costs, such example can be found here.
To run multiple instances of AFL++, use afl-launch and specify number of cores using the -n
argument:
AFL_PRELOAD=./preeny/x86_64-linux-gnu/desock.so ~/go/bin/afl-launch -n $(nproc) -i ./input/ -o output/ -x ./dict/ -m 2048 ./redis/src/redis-server ./redis.conf
The setup in this repo is based on VolatileMinds approach from 2015, I also added some useful improvements(below)
- Upgrading to a modern version(from 3.1 to 6.2.1)
- Automating the build proccess & hot-patch of Redis and preeny
- Adding instructions for scaled/Distributed Fuzzing
- Fixing compile flags for easier crash analysis (now side-dependencies are compiled with debug information, such as the embedded lua interpreter, etc.)
- Use
AFL_PRELOAD
instead ofLD_PRELOAD
(although I didn't notice a change, some docs are suggesting to useAFL_PRELOAD
sinceLD_PRELOAD
might override the fuzzer binary and possibly make the fuzzer melt into itself) - Adding more samples for the
./input/
directory - Applying persistent fuzzing(
AFL_LOOP
) to increase the execs per second rate - Adding utils like AddressSanitizer(ASAN) UndefinedBehaviorSanitizer(UBSAN) to the final build