When applications receive inputs they do not expect, they generally fail,
hopefully with an error message of some kind—indicating that the
programmer anticipated that type of bad input. But sometimes, programs
crash when they receive bad input, which can lead a researcher—or
exploitable vulnerability. Testing applications by feeding them bad data
is known as "fuzzing", and there are numerous toolkits and frameworks
available to help with such a task. One of those is Fusil, a Python library which can
be used to write fuzzing programs.
The basic idea behind Fusil is that it will start the targeted program in a
limited environment, create bad input to feed to it, and watch for various
events that would indicate a program crash. Fusil monitors the process
exit code, stdout and stderr for patterns that might indicate a crash, as
well as keeping track cpu usage and run time to look for infinite loops and
the like. It runs the process as a separate user ("fusil") to try to avoid
any adverse effects to the user's environment from any crashes that result.
Fusil's most recent version is 1.2, released in early February, which comes
with more than a dozen fuzzing programs for standard applications and
libraries. There are fuzzers for firefox, clamav, python, and mplayer for
example, along with ones for libraries like gettext and for
printf() in libc. There is also a rather impressive list of crashes
found by Fusil, including several that became CVE entries.
Getting started using Fusil is fairly straightforward when following the usage
guide, though the author ran into a number of problems when trying to
run as a non-root user. Running the fusil-python fuzzer did
produce a crash ("unexpected exception during garbage collection"), which
needs to be looked into further.
When it crashes an application, Fusil creates a script that will reproduce
the error along with various files to help diagnose the problem. The
output and a core file from the application are stored with the
replay.py script. The data file and a log of the session are
stored there as well. One can re-run the failing process inside gdb or
valgrind by passing the appropriate option (i.e. --gdb or
--valgrind) to replay.py.
There is also a document on how
to write fuzzers using Fusil. It starts with the traditional "hello
world" program using echo—not much fuzzing going on
there—and moves into a more real-world echo fuzzer. Fusil
provides various ways to randomize the data that gets handed to the
application. Then there are
mechanisms available to inject bad data via the command line, environment
variables, data files, or the network.
Overall, Fusil looks like an interesting tool. It has already been used to
find crashes in various applications and libraries, and it has the
capability to be extended to many more. If you are in need of a framework
to fuzz test your application, Fusil is worth a look. If more projects
made use of tools like Fusil, we would probably see fewer exploitable
vulnerabilities caused by unexpected input.
to post comments)