The case of identifying the vulnerabilities was rather interesting. I wanted to fuzz another program and wrote a quick harness to test if my setup works. This test harness used GNU Readline to read input from stdin and passed the data along to the function under test. I left the fuzzer running while I started to improve the harness (which would also mean getting rid of GNU Readline as it is relatively slow for the use-case at hand). However, AFL showed the first crashes and upon inspection, the vulnerabilities where not in the code I actually wanted to fuzz but in my systems GNU Readline.
This lead to a shift of my fuzzing target as I now wanted to investigate GNU Readline further. If you are interested in how AFL or its successor AFL++ is used, you should check out the AFL++ homepage tutorials section. AFL++ offers a variety of different instrumentation techniques. If you are unsure which one to use, you can follow the advice of this flow-chart (https://github.com/AFLplusplus/AFLplusplus#a-selecting-the-best-afl-compiler-for-instrumenting-the-target).
I reported the bugs I found while fuzzing and the developers have fixed them. Thanks for that!
I want to finish this blog post with a need little trick I learned that might come in handy if you are fuzzing and need to use specific libraries. Often these libraries are either loaded with LD_PRELOAD or LD_LIBRARY_PATH. However, if you have a typo in the path, the system might still load the system’s library without you noticing. In this case, you can simply check with ldd if the library has been loaded.
Let us consider the case that we want to load libcrypto.so.1.1 from another location. In the first case, the wrong path with LD_LIBRARY_PATH has been set, and we can see that the library under /usr/lib has been loaded.
$ LD_LIBRARY_PATH=”`pwd`/foo” ldd sha1
libssl.so.1.1 => /usr/lib/libssl.so.1.1 (0x00007fa5b24c5000)
libcrypto.so.1.1 => /usr/lib/libcrypto.so.1.1 (0x00007fa5b21e8000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fa5b201f000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fa5b1ffd000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fa5b1ff7000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa5b258d000)
In this second case, we have set the correct path in LD_LIBRARY_PATH and see that the library has been loaded from /tmp/test.
$ LD_LIBRARY_PATH=”`pwd`” ldd sha1
libssl.so.1.1 => /usr/lib/libssl.so.1.1 (0x00007f83ec4d5000)
libcrypto.so.1.1 => /tmp/test/libcrypto.so.1.1 (0x00007f83ec204000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f83ec03b000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f83ec019000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f83ec013000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f83ec59d000)