white clouds under blue sky during daytime
Sun May 21

Fuzzing the Right Way: Maximizing Results with ffuf

Penetration testing, encompassing XSS vulnerability testing, SQL Injection vulnerability testing, and bypassing authorization forms, is a complex task that is challenging to carry out manually. Manually trying every potential payload for each vulnerability is impractical, time-consuming, and inefficient. Therefore, automating the process is highly recommended.

For instance, when testing for SQL injection, it becomes necessary to evaluate website inputs using numerous payloads specifically designed for SQL injection. This list can be extensive, potentially spanning hundreds or even thousands of lines. This is where fuzzing plays an important role in simplifying the process.

What is fuzzing?

Fuzzing is an automated software testing technique used in programming, where invalid and unexpected data is provided as inputs. For example, when dealing with SQL injection, we can grab some random data from the internet and give it a try. By employing fuzzing techniques, penetration researchers can identify anomalies and respond accordingly

Use case

Before proceeding, note that doing this on the actual website we mention is illegal. We are just doing it to make learning easier for you to learn. We won’t take any responsibility for your actions.

For better comprehension about fuzzing, let’s take a very simple example. Say that we are doing some CTF (Capture the Flag) event. Let’s say we would like to do some domain listing on the website.

https://example.com/

Suppose this domain has been recently generated, thus you can’t find any information about it over the internet. You can’t find anything with a tool like DNS enumeration or any reconnaissance processes like OSINT won’t get you anywhere. Possibly, the best way to find “something” is by using the fuzzing technique.

Wordlist

To do it, we will need the list or set data that hopefully will match our intentions. This is what we know as wordlist. In any fuzzing tool, the data is required, and if you are using Kali Linux, there are some wordlists that are ready to use, which you can find in the /usr/share/wordlists. Alternatively, you can find it online. If you need a good set of wordlists, I recommend the Seclists from this Github repository. Grab it with the following command.

$ git clone https://github.com/danielmiessler/SecLists.git

Fuzzing with ffuf

When it comes to fuzzing, one of my favorite tools is ffuf. However, feel free to use any tool that suits your needs. Personally, I prefer ffuf because it’s lightweight and super fast compared to other options like BurpSuite, which is also an essential tool for penetration testers.

Simple fuzzing

Back to our case, there are, for the very least, two things to run the ffuf, a set of wordlist and setting up a keyword “FUZZ” in the request. If we want to find any interesting path like sitemap.xml, robots.txt, or any accessible page you can do the following.

$ ffuf -w /path/to/wordlist.txt -u ‘https://www.example.com/FUZZ’

Make sure you choose the right set of wordlists based on your specific purpose. Obviously, using the “password.txt” wordlist would not be suitable in this case. If you have the Seclists collection we mentioned earlier, the “dirsearch.txt” wordlist would be a more fitting choice.

Fuzzing with multiple wordlists

Quite often, you will find the case where you need more than one wordlist to work simultaneously. Specific case and common use case for this is fuzzing over the login form. Despite the fact that some websites are migrating to use more modern authentication procedures like OAuth 2.0, the login form is still common and being implemented on lots of websites. This is when the fuzzing technique could come in handy.

Login form requires users to supply their username and password information. If we “translate” it to fuzzing technique, we need at least two wordlists: the username wordlist and password wordlist.

From previous fuzzing, suppose that we found a login form in the following path.

https://www.example.com/login

After testing the login form, we found that our inputs are added as a query parameter like this.

https://www.example.com/login?username=test&password=test2

Therefore, we can try to fuzz the input using two different wordlists.

We need to specify the suitable keyword for each part. From the previous scenario, you can set your own custom with the following command.

$ ffuf -w /path/to/username.txt:USERNAME -w /path/to/password.txt:PASSWORD -u ‘https://www.example.com/login?username=USERNAME&password=PASSWORD’

Fuzzing mode

When working with multiple wordlists, ffuf has some modes available for you. For explanation purposes, we will simplify the wordlists with only three words for each. The username wordlist consists of abc, def, ghi and the password wordlist also consists of rst, uvw, xyz. You can set the mode you want with --mode option.

$ ffuf --mode <pitchfork/clusterbomb> -w /path/to/username.txt:USERNAME -w /path/to/password.txt:PASSWORD -u ‘https://www.example.com/login?username=USERNAME&password=PASSWORD’ ’

Clusterbomb mode

This is the default mode when working with multiple wordlists. In the fuzzing process, the first word in the first wordlist is compared to all the words in the second wordlist, followed by testing the second word in the first wordlist against all the words in the second wordlist. This pattern continues for all combinations. It’s important to note that there is no limit to the number of wordlists, meaning the process can continue indefinitely. However, it’s worth mentioning that the overall testing duration will increase exponentially with each additional wordlist.

The username and password combination would look like this.

CombinationUsernamePassword
1abcrst
2abcuvw
3abcxyz
4defrst
5defuvw
6defxyz
7ghirst
8ghiuvw
9ghixyz

Pitchfork mode

This mode uses a much more simple approach to match between multiple wordlists. The first word from username will match the first word from password, the second word from username will also match the second word from password and so on.

The username and password combination will go like this.

CombinationUsernamePassword
1abcrst
2defuvw
3ghixyz

Request configuration

In some cases, the username and password won’t be shown in the query string. Instead, it will be sent to the server within the request body. Since we can’t use the same request we did before, the most easy way to fuzz is by using the raw HTTP request saved in a file. This method is not limited to fuzzing the data included in the request body, but it can also fuzz data within the request header.

Headers

You have the option to specify various header key-value pairs by using the command line argument -H ‘Name: Value’. Additionally, you can include any of the keywords into either the header key or value, or both.

$ ffuf -w users.txt -u ‘https://www.example.com/’ -H ‘X-User: FUZZ’

Body

To include a request body, you can use the -d option followed by the request body. It is also important to note that ffuf won’t set any header values based on the request body content. Hence, defining a proper Content-Type header is mandatory when working with HTML or JSON data.

$ ffuf -w username.txt:USERNAME -w password.txt:PASSWORD -u 'https://www.example.com/api/v1/login' -X POST -H 'Content-Type: application/json' -d "username=USERNAME&password=PASSWORD”

Matching and Filtering

While receiving a response, ffuf will first check whether the response matches the matchers defined by the user and discard the response defined by the filters. There are several matchers types that might be helpful for you.

Response code (-mc and -fc)

This is a very common matcher and filter to suit your needs. By design, ffuf uses multiple matching response codes, such as 200,204,301,302,307,401,403,405,500. A special value “all” is available to cover these response codes. Assuming that we want to match all the values, but filter out the 401, 403, 405 and 500 response code, we can use the following command.

$ ffuf -w wordlist.txt -u ‘htttps://www.example.com/FUZZ’ -mc all -fc 400-403, 500

Response size (-ms and -fs)

Another common practice to filter the output is by utilizing the Content- Length in the response header. This is a powerful filtering which can be useful in combination with -mc to narrow down the result. Assume that we want to match only the response with status code 200 with the Content-Length of 67.

$ ffuf -w wordlist.txt -u ‘https://www.example.com/FUZZ’ -mc 200 -fs 67

Number of words(-mw and -fw)

ffuf makes it possible to do matching or filtering based on the number of words in response. Still based on the Content-Length, the purpose is to eliminate false positives, particularly when the service’s response includes a Content-Length that varies based on user input. Assume that we want to match all response codes but filter out responses with word count of 18.

$ ffuf -w wordlist.txt -u 'https://www.example.com/FUZZ' -mc all -fw 18

Number of lines(-ml and -fl)

Alternatively, you have an option to count by the number of lines instead of words. However, it is advised to prioritize using the word count matching over this, as it’s more specific as compared to line matching.

Time based(-mt and -ft)

Matching and filtering based on the response time is another choice you can choose when utilizing ffuf. Some timing-based attacks like time-based SQL injection may benefit from this option to determine whether a payload is working or not. Two special characters, greater than (>) and less than (<) are available to match a more specific timeframe. Note that the value is in milliseconds.

$ ffuf -w sqli-payloads.txt -u 'https://www.example.com/api/v1/user’ -H 'Content-Type: application/json' -d '{"id":"FUZZ"}' -mt >5000

Conclusion

ffuf is an extensively used tool in the field of web application security, as it helps uncover potential vulnerabilities and weaknesses in web applications by systematically testing different inputs and analyzing the resulting responses. Although, we don’t mention some of the additional features it has, there are still a whole lot more options and features you can explore to better suit your needs.