====== 0x07b. Stateful Fuzzing ======
===== Slides =====
The slides ca be found over {{:session:sess-08.pdf|here}}
===== Tutorials =====
==== Stateful Fuzzing ====
When doing stateful fuzzing, our protocol message requests aren't independent any more from one another and must be sent in a specific order so as to carry out the fuzzing process. This type of ordering leads to a natural representation of the state machine as a graph with message requests being represented as nodes and sequencing between messages as edges.
The fuzzer, in this case, will walk all the paths in the graph, incrementally sending the correct messages to reach a certain node. The fuzzing process is complete when all paths have been explored.
==== Sulley Recap & Review ====
{{ :session:sulley-architecture.png?direct&800 |}}
Let's recap a bit what we've learned about the Sulley Fuzzing Framework. A general overview of its architecture is given in the figure above.
Some of the components and their use:
* Data Generation/Request Library - defines request encoding and fuzzable fields
* Session Management - sequences individual requests into a state machine that can be walked
* Agents - monitor the process that's being fuzzed as well as the network
* Targets - the actual places we're sending the fuzzing data (eg. network sockets), we can have multiple targets in the same fuzz scenario
* Utilities - usually post-mortem analysis tools for the test results (crashes)
* Driver - python script that glues everything together:
* Requests
* Session
* Targets
* Agents
In our previous lab we've been mainly focused on the data generation step and stateless fuzzing and left Sulley session management and the other components for this one.
==== Sulley Sessions ====
The major benefit of Sulley is the fact that is allows "deep" fuzzing within a protocol. This is accomplished by linking requests together in a graph (or session in Sulley parlance) as shown in the following figure depicting such a graph for SMTP.
{{ :session:smtp-graph.png?direct&150 |}}
The code used for creating the graph and requests is presented below :
from sulley import *
s_initialize("helo")
s_static("helo")
s_initialize("ehlo")
s_static("ehlo")
s_initialize("mail from")
s_static("mail from")
s_initialize("rcpt to")
s_static("rcpt to")
s_initialize("data")
s_static("data")
sess = sessions.session()
sess.connect(s_get("helo"))
sess.connect(s_get("ehlo"))
sess.connect(s_get("helo"), s_get("mail from"))
sess.connect(s_get("ehlo"), s_get("mail from"))
sess.connect(s_get("mail from"), s_get("rcpt to"))
sess.connect(s_get("rcpt to"), s_get("data"))
fh = open("session_test.udg", "w+")
fh.write(sess.render_graph_udraw())
fh.close()
The graph can be dumped to an UDG file for rendering in [[http://www.informatik.uni-bremen.de/uDrawGraph/en/download/download.html | uDraw]] as shown near the end of the code snippet.
When fuzzing, Sulley walks the graph structure starting with the root node and fuzzing each component along the way. In this example it will begin with the **'helo'** request. Once complete, Sulley will begin fuzzing the **'mail from'** request. It does so by prefixing each test case with a valid 'helo' request. Next, Sulley moves on to fuzzing the **'rcpt to'** request. Again, this is accomplished by prefixing each test case with a valid 'helo' and 'mail from' request.
The process continues through **'data'** and then restarts down the **'ehlo'** path.
When instantiating a session, the following optional keywords arguments may be specified:
* session_filename: (string, default=None) Filename to serialize persistent data to. Specifying a filename allows you to stop and resume the fuzzer.
* skip: (integer, default=0) Number of test cases to skip.
* sleep_time: (float, default=1.0) Time to sleep in between transmission of test cases.
* log_level: (integer, default=2) Set the log level, higher number == more log messages.
* proto: (string, default="tcp") Communication protocol.
* timeout: (float, default=5.0) Seconds to wait for a send() / recv() to return prior to timing out.
* restart_interval: (integer, default=0) Restart the target after n test cases, disable by setting to 0
* crash_threshold: (integer, default=3) Maximum number of crashes allowed before a node is exhausted
Another advanced feature that Sulley introduces is the ability to register callbacks on every edge defined within the protocol graph structure. This allows us to register a function to call between node transmissions to implement functionality such as challenge response systems.
The callback method must follow this prototype and is passed as the thrid argument to session.connect:
def callback(node, edge, last_recv, sock)
Where:
* **'node'** is the node about to be sent
* **'edge'** is the last edge along the current fuzz path to **'node'**
* **'last_recv'** contains the data returned from the last socket transmission
* **'sock'** is the live socket.
A callback is also useful in situations where, for example, the size of the next pack is specified in the first packet. As another example, if you need to fill in the dynamic IP address of the target register a callback that snags the IP from sock.getpeername().
Edge callbacks can also be registered through the optional keyword argument 'callback' to the session.connect()
method.
An example of the places where callbacks may be registered is given in the following figure.
{{ :session:sulley-callbacks.png?direct&700 |}}
==== Sulley Debugging Tips ====
=== Sulley Process Monitor ===
In previous session on stateless fuzzing, we had problems with Sulley not restarting the process properly after it crashed.
In order to fix that, the **start_target** function defined in **process_monitor_unix.py** must return **True** since the check is done against the value in sulley/session.py and if it's false (which is the default) it considers the restart procedure failed.
Also, the **stop_target** function must return **True** as well. By default it returns None which corresponds to False when used in an if statement.
==== Parallel Fuzzing ====
Sulley is designed (but not fully implemented yet) to support parallel fuzzing by adding more targets. When more than one target is present, the fuzz tests are divided between all targets and are run in parallel. For each target, you will need a separate process monitor and network monitor to be instantiated. These can either be on the same machine (different ports) or on different machines.
===== Tasks =====
==== DNS Server Fuzzing ====
During the previous Stateless Fuzzing session we've fuzzed only text based protocols but Sulley can also be used for binary ones so this time we can have a go at DNS. You may start your fuzzing from the **examples/mdns.py** fuzzer found in Sulley.
Your practice target will be the following DNS server written by someone who wanted to practice his networking skills. Let's see how many crashes you can find in it.
git clone https://github.com/francois/dnsd
You need to figure out how to compile it first ;)
Now, for the real thing. Your target will be the following open source DNS server:
git clone https://github.com/samboy/MaraDNS
MaraDNS is a tough nut to crack so, don't be disappointed if you won't find any crashes. The main challenge for this exercise is to orchestrate and automate the fuzzing for this real application.
==== FTP Server Fuzzing ====
Please sync the following Github repository which contains a simple FTP Server written in C, compile it, look over how it's configured and attempt to develop a stateful Sulley FTP fuzzer for it. A reference for the FTP state machine can be found in [[http://tools.ietf.org/html/rfc959|RFC959]] int the **6. STATE DIAGRAMS** section.
git clone https://github.com/xu-wang11/FtpServer.git
If you want a head start on the FTP fuzzer, you may find some code and logic for it over [[https://code.google.com/p/ftpfuzz/source/browse/sulley/ftp.py | here ]]
Now, after you had enough playing with the toy target, let's try and go for something real:
git clone https://github.com/jedisct1/pure-ftpd
==== Fuzz your own application ====
This is a free-form exercise. You can select any application you want to fuzz and go build a fuzzer for it.
Eg. applications:
* network services:
* E-mail
* DNS
* DHCP
* Active Directory
* FTP
* HTTP
* SNMP
* SSH
* SSL/TLS/DTLS
* P2P services
* VoIP solutions
* etc...
* File-based apps:
* Bittorrent clients
* PDF/DOC/PPT/XLS/etc..
* PNG/JPG/BMP/PS/etc...
* Web browsers
* E-books
* etc...
===== Resources =====
* [[http://www.informatik.uni-bremen.de/uDrawGraph/en/download/download.html | uDraw]]
* [[https://github.com/OpenRCE/sulley|Sulley Github Repository]]
* [[http://www.fuzzing.org/wp-content/SulleyManual.pdf| Sulley User Manual]]
* [[http://www.fuzzing.org/| Fuzzing.org]]
* [[http://sulley.readthedocs.org/en/latest/genindex.html| Sulley API Docs]]
* [[http://dragos.comaneci.ro/FuzzingBruteForceVulnerabilityDiscovery2007.pdf | Fuzzing - Brute Force Vulnerability Discovery]]