Files
AFLplusplus/docs/README.network_fuzzing
van Hauser 7e061b87ff doc update
2019-07-16 18:20:58 +02:00

109 lines
5.9 KiB
Plaintext

Fuzzing network services
----------------------------
Both client and server (daemon) programs that communicate using an
IP network (IPv4 or IPv6) can be fuzzed using the command line
$ ./afl-fuzz -i testcase_dir -o findings_dir [-D delay_before_write] \
[-t timeout_delay] [-K] -N network_specification /path/to/program \
[...params...]
where the network_specification has a form similar to a URL:
[tcp|udp]://hostspec:port
Afl-fuzz has two network fuzzing modes, where it acts as a client to a
network server that expects input via a socket (no -K option), and where it
acts as a server to a network client that sends data to afl-fuzz before
receiving input (using the -K option). In the first case, afl-fuzz sends data
to the port specified by the URL. In the second case, afl-fuzz receives data
on that port and sends a (fuzzed) response to the port the target (client) used
to send its data.
Note that when afl-fuzz acts as a server (the -K option), there is no control
over how the target client manages its use of sockets - and in particular, a
client that uses ephemeral sockets (the usual case) will rapidly consume the
network stack's pool of available sockets. Some operating systems are able to
reclaim used ephemeral sockets to keep the pool from being exhausted; others
may experience difficulties.
While the -D and -t command line arguments are optional, they are almost
always necessary when fuzzing a program using network protocols, as
described below.
Case is irrelevant in the network specification. For programs that
use a stream (connection-based) protocol, use TCP, and for programs
that use a datagram (connectionless) protocol, use UDP. The hostspec
must be one of ::1 (forcing IPv6 networking), 127.0.0.1 (forcing IPv4
networking), and localhost (which is typically configured as IPv4 but
may suppport IPv6 on some systems). Only loopback networking (local
to the host) is supported. The port must be either a port number in
the range 1..65535 or a service name known to the system being used.
You can test programs that use privileged ports, but you then have to
provide afl-fuzz with those additional privileges (e.g., root). It is
usually better to reconfigure the program being tested so that it will
use a non-privileged port during fuzzing.
Programs that implement network services, also called daemons, are
typically transaction-based: They wait for a request and send a
response, and some expect a sequence of request/response transactions.
Afl-fuzz implements fuzzing only for the first write to the target
program and ignores all responses from the target. Most network
services expect to run as background processes and process requests
from many processes -- they do not normally exit. A timeout delay is
required in order to terminate these processes, and the default
timeout delay used in afl-fuzz is usually too long. The user needs to
experimentally determine a timeout delay (in milliseconds) that
produces a sufficiently low percentage of hangs (exits forced by
expiration of the delay) while allowing the input to the target from
afl-fuzz to be completely processed. (Note that afl-fuzz will usually
count these hangs as a single unique hang.) Since a network service
does not normally exit, the initial timing performed by afl-fuzz will
fail unless a '+' character is appended to the timeout_delay
parameter, indicating that afl-fuzz is to ignore these timeouts.
Network services programs also require some time to perform start-up
processing, create and bind a socket to an address and port, and begin
listening for traffic on that socket. Connection requests (TCP) and
sends (UDP) generated by afl-fuzz will fail if made before the network
service is ready. Afl-fuzz implements a delay and retry procedure to
avoid this problem, where the delay is specified by the
delay_before_write parameter (in milliseconds). The first connection
attempt (for TCP) or write (for UDP) is not made until after this
delay, and the delay also specifies the wait time before each
subsequent attempt. Afl-fuzz will attempt to connect or send to the
same each target process a maximum of three times.
The delay_before_write parameter, in particular, and to a lesser
extent the timeout_delay parameter limit the maximum achievable rate
of target program executions and therefore need to be small. A rule of
thumb is the timeout_delay value should be slightly longer than three
times the delay_before_write value, and the delay_before_write value
should be as small as possible while consistent with an acceptable
fraction of target process executions that time out (for example,
around 0.1%).
Network client program have similar characteristics that require the use of
the delay parameter, but they write to their expected server (afl-fuzz in this
case) before reading from their network socket. This makes coordination between
afl-fuzz and (client) target somewhat more challenging. While the delay and
timeout parameters can usually be adjusted to obtain execution rates similar
to those for server programs, when afl-fuzz exits (due to a ^C interrupt) it
may hang. In this case, use (on UNIX or Linux) the ps command to find the
process id (PID) of the afl-fuzz process, and use the kill command to terminate
it (typically, "kill -9 PID"). This will also terminate (or scavenge) the
network client program's process, which may be in a zombie state that can not
otherwise be removed (without rebooting the system).
A note concerning network fuzzing on multi-core systems:
It is not possible to run two processes under a single operating
system kernel that bind to (listen to) the same port on the same
address. Thus, either a special wrapper (such as could be implemented
using LD_PRELOAD) can be used to remap each target's port to a
different value, or only one target process can be executed per kernel
(not per core). Parallel fuzzing of network services can be done using
several independent hosts (a cluster), or by reconfiguring the code
running on each core to use a different port.