Fuzzing is a black-box software testing technique and consists of finding implementation flaws and bugs by using malformed/semi-malformed payloads via automation. Fuzzing an application is not a matter of simply exploiting a specific point of an application, but also acquiring knowledge and potential crashes that could be explored in-depth through the implementation of crafted payloads in order to take advantage of bad practices of coding. In addition, fuzzing helps you explore an application’s deploys, infrastructures, protocols, entry points and so on.
Understanding a fuzzing scenario
The user-password authentication mechanism is still commonly used in most applications today. In brief, the application receives two user inputs — the username and password string — which are then received and verified to allow the creation of a session allowing later access to other authenticated features.
Let’s take an FTP application as an example. If the size of the username string is equal to eight bytes, the max size of a string can be: infosec1 (eight characters) or username, as you can see below.
Figure 1: Buffer overflow vulnerability
When an automation program (the fuzzer) sends arbitrary payloads during the authentication process, several username payloads can be generated with different sizes and character sets, or even templates. If the username parameter is greater than eight bytes, the application will crash, and that will create a buffer overflow condition. From here, a remote code execution vulnerability could be explored via the execution of a crafted payload.
Fuzzing is an aging mechanism developed at the University of Wisconsin – Madison in 1989 by Professor Barton Miller and his students. Fuzzing is a means of detecting potential implementation weaknesses that can be used to take advantage of any target. To do this, a specific fuzzer must be used, where semi-random data is injected into a program/stack to detect bugs or crashes. This process is composed of several steps that can be enumerated as follows.
Figure 2: Fuzzing workflow diagram
Initially, the target system must be identified to select the specific fuzzer, the target input, and the right character-set inputs in order to generate the final payloads to test.
After the target input identification, the payload list is generated. Several types of data can be included, such as strings, digits, characters and combinations between them within different input sizes. Next, the payloads are executed by starting the fuzzer in the right conditions.
A crucial part of this process is monitoring the system behaviors and log defects. Here is where we analyze — via an offline format — the results of the test. The potential flaw, bug or crash is detected in this phase.
Finally, the specially crafted payload can be created according to the results obtained from the fuzzing process to take advantage of the target system, resulting in the creation of the final exploit.
Fuzzing is beneficial to find new crashes and bugs in applications, protocols and so on. It can be grouped into different types.
Every input can be fuzzed (inputs, URLs parameters, forms, cookies and so on) with different character sets and payloads but the same goal: crash the system to take advantage of the implementation weakness. The FTP scenario described above is considered an application fuzzing scenario, as the test was performed based on the input parameter: username.
A protocol fuzzer sends forged packets to the tested application, or eventually acts as a proxy, modifying requests on the fly and replaying them (e.g., Burp Suite tool — proxy feature).
File format fuzzing
A file format fuzzer can generate multiple malformed samples and opens them sequentially. After that, the program crashes and the debug information is kept for further investigation.
This kind of fuzzer is less common but still tends to appear these days. For example, MS04-028 (KB833987), Microsoft’s JPEG GDI+ vulnerability, is one example of this type of fuzzing scenario.
Fuzzing char-set input
Among the most important parts of fuzzing a system are the generated payloads, consisting of the target inputs. The payloads must be generated via a random or semi-random approach or by using known pieces of information (existent data accepted by the system).
Two types of approaches can be used to carry out this task, namely:
Each subsequent iteration’s data is created independently of any previous input. This approach is based on a model of the input format.
Changes of the existing data are done according to certain patterns. Traditional fuzzing uses fuzzers that operate by channeling malformed and corrupted data to an entry point. On the other hand, modern fuzzers continue to improve their functionalities by generating high-structured types of data to reach deeper layers of the entry point under test.
There are several tools for different fuzzing scenarios.
SPIKE: SPIKE is a protocol fuzzer creation kit. It provides an API that allows a user to create their own fuzzers for network-based protocols using the C++ programming language.
American fuzzy lop: American fuzzy lop is a free fuzzer that uses genetic algorithms to efficiently increase code coverage of the test cases. It has been used in the detection of significant software bugs in dozens of major free software projects, including X.Org Server, PHP, OpenSSL, pngcrush, bash, Firefox, BIND, Qt and SQLite.
Figure 3: American fuzzy lop fuzzing screen
Radamsa: Radamsa works by reading sample files of valid data and generating different outputs from them. The main selling points of Radamsa are: it has already found a slew of bugs in programs that actually matter; it is easily scriptable; and easy to get up and running.
Figure 4: Radamsa fuzzer features
Boofuzz: Boofuzz is a Python fuzzing framework. Boofuzz is capable of fuzzing a target and automatically restarting a process in case of a failure. Boofuzz is a fork of and the successor to the venerable Sulley fuzzing framework. Besides numerous bug fixes, boofuzz aims for extensibility.
Figure 5: Boofuzz dashboard control
BFuzz: BFuzz is an input-based fuzzer tool which takes HTML as an input, opens up a supported web browser with a new instance and passes multiple test cases generated by domato, which is present in the recurve folder of BFuzz. BFuzz is automation that performs the same task repeatedly; it doesn’t mangle any test cases.
Powerfuzzer: Powerfuzzer is a highly automated and fully customizable web fuzzer based on many other open-source fuzzers available and information gathered from numerous security resources and websites. It was designed to be user-friendly, modern and effective.
Figure 6: Powerfuzzer main window
Fuzzing: Pros and cons
As other testing techniques, this is not perfect and should be used as part of a robust testing strategy. A list of the pros and cons of fuzzing is presented below.
- Simple to design and perform automated tests
- Find bugs or crashes not easily visible via other testing techniques
- Bugs found are sometimes severe and include defects that could be exploitable in the wild, including unhandled exceptions, crashes, memory faults/leaks and so on
- Usually very inexpensive to implement
- Generally finds very simple faults
- Often takes an extremely long time to run
- Crashes can often be difficult to analyze, especially when using black-box fuzzing
- Mutation templates for applications with complex inputs can often be time-consuming to produce
Fuzzing is a testing approach that can produce good results when used to identify bugs and crashes under any entry point. Nonetheless, finding bugs is a time-consuming task, and this can require a large time investment to correctly set up a suitable fuzzing platform or tool that is integrated with the software testing suite.
While this is seen as the main drawback to this testing paradigm, fuzzing can still help find critical vulnerabilities and prevent them from being discovered by malicious agents in the future.