frewsxcv / afl.rs
- вторник, 21 июня 2016 г. в 03:13:06
C
Fuzzing Rust code with american-fuzzy-lop
Fuzzing Rust code with american fuzzy lop (AFL)
Screen recording of AFL running on Rust code. The code under test is examples/hello.rs
in this repository.
Fuzz testing is a software testing technique used to find security and stability issues by providing pseudo-random data as input to the software. American fuzzy lop is a popular, effective, and modern fuzz testing tool. This library, afl.rs, allows one to run AFL on code written in the Rust programming language.
rustc
's. The easy solution (if you can wait on a slow build) is to build rustc
from source and put it in your PATH
. Then afl.rs's build script will find llvm-config
automatically. Otherwise, the environment variable LLVM_CONFIG
should hold the path to llvm-config
when you build afl.rs.Because of these relatively strict requirements, there is a Vagrantfile provided that assists in bootstraping an afl.rs compatible environment. View the README in the vagrant/
directory for more information.
NOTE: It is known that requiring one to compile Rust greatly increases the barrier to use afl.rs. It will soon be the case this requirement will be lifted and the setup instructions will be greatly simplified. Stay tuned!
First, add this project as a Cargo dependency:
[dependencies]
afl = "0.1"
afl-plugin = "0.1"
Then you can add afl instrumentation to one or more crates:
#![feature(plugin)]
#![plugin(afl_plugin)]
You will also need a test executable that exercises the instrumented functions,
in a deterministic way based on input from stdin. This executable should link
the afl
run-time library:
extern crate afl;
This will produce a binary that you can pass to afl-fuzz
in the usual manner.
C++ code will be compiled by default with g++
, though one can specify a different C++ compiler by setting the CXX
environment variable to point to a different compiler binary.
To look for logic errors in safe Rust code, use the no-landing-pads
rustc flag
upon compilation of the AFL entrypoint. This causes the fuzzer to treat any
Rust panic as a crash. Examples of usage:
rustc -Z no-landing-pads
cargo rustc -- -Z no-landing-pads
If your program has a slow set-up phase that does not depend on the input data,
you can set AFL_DEFER_FORKSRV=1
for a substantial speed-up, provided that you
insert a call to afl::init()
after the set-up and before any
dependence on input. There are various other caveats, described in the section
"Bonus feature: deferred instrumentation" in llvm_mode/README.llvm
distributed with afl. See also examples/deferred-init.rs
in
this repository.
afl instrumentation adds some run-time overhead, so it's a good candidate for conditional compilation, perhaps through a Cargo feature:
# You may need to add `optional = true` to the above dependencies.
[features]
afl = ["afl-plugin", "afl"]
// Active only with `cargo [...] --feature afl`
#![cfg_attr(feature = "afl", feature(plugin))]
#![cfg_attr(feature = "afl", plugin(afl_plugin))]
See the afl documentation for other configuration variables. Some of these are
set at compile time in config.h
. For the most part they only affect
afl-fuzz
itself, and will work fine with this library. However, if you change
SHM_ENV_VAR
, MAP_SIZE
, or FORKSRV_FD
, you should update this library's
src/config.h
to match.
These bugs aren't nearly as serious as the memory-safety issues afl has
discovered in C and C++ projects.
That's because Rust is memory-safe by default, but also because not many people
have tried afl.rs yet! Over time we will update this section with the most
interesting bugs, whether they're logic errors or memory-safety problems
arising from unsafe
code. Pull requests are welcome!