Attacking Web Applications with Ffuf

This module covers the fundamental enumeration skills of web fuzzing and directory brute forcing using the Ffuf tool.

Introduction

  • The term fuzzing refers to a testing technique that sends various types of user input to a certain interface to study how it would react.

  • We usually utilize pre-defined wordlists of commonly used terms for each type of test for web fuzzing to see if the webserver would accept them.

  • This is done because web servers do not usually provide a directory of all available links and domains (unless terribly configured), and so we would have to check for various links and see which ones return pages.

Wordlists

  • To determine which pages exist, we should have a wordlist containing commonly used words for web directories and pages.

  • Though this will not reveal all pages under a specific website, as some pages are randomly named or use unique names, in general, this returns the majority of pages.

  • We will not have to reinvent the wheel by manually creating these wordlists, as great efforts have been made to search the web and determine the most commonly used words for each type of fuzzing.

  • Some of the most commonly used wordlists can be found under the GitHub SecLists repository, which categorizes wordlists under various types of fuzzing.

  • In Kali Linux, the SecLists can be found in /usr/share/seclists/

  • Taking a look at these wordlists we will notice that it contains copyright comments at the beginning, which can be considered as part of the wordlist and clutter the results.

  • Directory/Page: SecLists/Discovery/Web-Content/directory-list-2.3-small.txt

  • Extensions Wordlist: SecLists/Discovery/Web-Content/web-extensions.txt

  • Domain Wordlist: SecLists/Discovery/DNS/subdomains-top1million-5000.txt

  • Parameters Wordlist: SecLists/Discovery/Web-Content/burp-parameter-names.txt

DNS Records

  • Some websites are not public websites that can be accessed by anyone but local websites within the network.

  • Browsers only understand how to go to IPs, and if we provide them with a URL, they try to map the URL to an IP by looking into the local /etc/hosts file and the public DNS Domain Name System.

  • If the URL is not in either, it would not know how to connect to it.

  • So, to connect to an internal website (i.e. academy.htb), we would have to add it to our /etc/hosts file (sudo sh -c 'echo "Server IP Address> <Domain Name>" >> /etc/hosts'

Basic Fuzzing

  • The main two options are -w for wordlists and -u for the URL.

  • We can assign a wordlist to a keyword to refer to it where we want to fuzz. For example, we can pick our wordlist and assign the keyword FUZZ to it by adding :FUZZ after it. This can be useful when we want to use two wordlists and have a unique keyword for each (By default, the keyword is FUZZ).

    • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ

  • Fuzzing speed may vary depending on your internet speed and ping, but it should still be extremely fast.

  • We can even make it go faster if we are in a hurry by increasing the number of threads to 200, for example, with -t 200, but this is not recommended, especially when used on a remote site, as it may disrupt it, and cause a Denial of Service, or bring down your internet connection in severe cases.

Directory Fuzzing

  • If we want to be fuzzing for web directories, we can place the FUZZ keyword where the directory would be within our URL. (http://<Server IP Address>:<Port Number>/FUZZ)

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://<Server IP Address>:<Port Number>/FUZZ

Extension Fuzzing

  • Before we start fuzzing the pages, we must find out what types of pages the website uses, like .html, .aspx, .php, or something else.

  • One common way to identify that is by finding the server type through the HTTP response headers and guessing the extension. For example, if the server is apache, then it may be .php, or if it was IIS, then it could be .asp or .aspx, and so on.

  • Before we start fuzzing, we must specify which file that extension would be at the end of! We can always use two wordlists and have a unique keyword for each, and then do FUZZ_1.FUZZ_2 to fuzz for both. However, there is one file we can always find in most websites, which is index.*, so we will use it as our file and fuzz extensions on it.

The wordlist might or might not contain a dot (.), It's important to know before fuzzing to determine if we need to add the dot (.) ourselves or not.

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/web-extensions.txt:FUZZ -u http://<Server IP Address>:<Port Number>/blog/indexFUZZ

  • After we know what extension the website uses, we are going to start fuzzing the pages of the website using this extension.

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://<Server IP Address>:<Port Number>/blog/FUZZ.php

Recursive Fuzzing

  • When we scan recursively, it automatically starts another scan under any newly identified directories that may have on their pages until it has fuzzed the main website and all of its subdirectories.

  • Some websites may have a big tree of sub-directories, like /login/user/content/uploads/...etc, and this will expand the scanning tree and may take a very long time to scan them all. This is why it is always advised to specify a depth to our recursive scan, such that it will not scan directories that are deeper than that depth.

  • In ffuf, we can enable recursive scanning with the -recursion flag, and we can specify the depth with the -recursion-depth flag.

  • When using recursion in ffuf, we can specify our extension with -e <.File Extension>

  • Finally, we will also add the flag -v to output the full URLs. Otherwise, it may be difficult to tell which file lies under which directory.

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://SERVER_IP:PORT/FUZZ -recursion -recursion-depth 1 -e .php -v

Domain Fuzzing

Subdomains Fuzzing

  • A sub-domain is any website underlying another domain. For example, https://photos.google.com is the photos sub-domain of google.com.

  • Remember that if a domain isn't identifiable by the DNS then we also need to add its subdomains to the /etc/hosts/ file for them to be identifiable in this case we use the -vhost scanning option.

  • In the SecLists repo, there is a specific section for sub-domain wordlists, consisting of common words usually used for sub-domains. We can find it in /opt/useful/SecLists/Discovery/DNS/

  • Example: ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u https://FUZZ.inlanefreight.com/

  • Example: ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://FUZZ.academy.htb/

Vhost Fuzzing

  • When it came to fuzzing sub-domains that do not have a public DNS record or sub-domains under websites that are not public, we could not use the same method used for normal subdomains scanning. We have use Vhost fuzzing.

Vhosts vs. Sub-domains

  • The key difference between VHosts and sub-domains is that a VHost is basically a 'sub-domain' served on the same server and has the same IP, such that a single IP could be serving two or more different websites.

  • VHosts may or may not have public DNS records.

  • This is where we utilize VHosts Fuzzing on an IP we already have. We will run a scan and test for scans on the same IP, and then we will be able to identify both public and non-public sub-domains and VHosts.

  • To scan for VHosts, without manually adding the entire wordlist to our /etc/hosts, we will be fuzzing HTTP headers, specifically the Host: header. To do that, we can use the -H flag to specify a header and will use the FUZZ keyword within it.

  • Example: ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://academy.htb:PORT/ -H 'Host: FUZZ.academy.htb'

  • Note that all words in the wordlist are returning 200 OK! This is expected, as we are simply changing the header while visiting http://academy.htb:PORT/. So, we know that we will always get 200 OK. However, if the VHost does exist and we send a correct one in the header, we should get a different response size, as in that case, we would be getting the page from that VHosts, which is likely to show a different page. This is where we might need to filter our results.

Filtering Results

  • The results are automatically filtered by default by their HTTP code, which filters out code 404 NOT FOUND, and keeps the rest.

  • Ffuf provides the option to match or filter out a specific HTTP code, response size, or amount of words.

  • Filtering Options:

    • -fc Filter HTTP status codes from response. Comma separated list of codes and ranges

    • -fl Filter by amount of lines in response. Comma separated list of line counts and ranges

    • -fr Filter regexp -fs Filter HTTP response size. Comma separated list of sizes and ranges

    • -fw Filter by amount of words in response. Comma separated list of word counts and ranges

  • Let's take the VHost example where all the results are 200 OK but the difference should be noticed in the response size in this case we can use: ffuf -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://academy.htb:PORT/ -H 'Host: FUZZ.academy.htb' -fs 900

Parameter Fuzzing

  • Fuzzing parameters may expose unpublished parameters that are publicly accessible. Such parameters tend to be less tested and less secured.

GET Request Fuzzing

  • In GET requests, the parameter is usually added to the end of the URL. For example, http://admin.academy.htb:PORT/admin/admin.php?param1=key

  • So, all we have to do is replace param1 in the example above with FUZZ and rerun our scan.

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:PORT/admin/admin.php?FUZZ=key

POST Request Fuzzing

  • The main difference between POST requests and GET requests is that POST requests are not passed with the URL and cannot simply be appended after a ? symbol.

  • POST requests are passed in the data field within the HTTP request.

  • To fuzz the data field with ffuf, we can use the -d flag. We also have to add -X POST to send POST requests.

  • We also have to consider the content-type. For example, in PHP, "POST" data "content-type" can only accept "application/x-www-form-urlencoded". So, we can set that in "ffuf" with "-H 'Content-Type: application/x-www-form-urlencoded'"

  • Example: ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:PORT/admin/admin.php -X POST -d 'FUZZ=key' -H 'Content-Type: application/x-www-form-urlencoded'

Value Fuzzing

  • After fuzzing a working parameter, we now have to fuzz the correct value.

  • When it comes to fuzzing parameter values, we may not always find a pre-made wordlist that would work for us, as each parameter would expect a certain type of value.

  • For some parameters, like usernames, we can find a pre-made wordlist for potential usernames, or we may create our own based on users that may potentially be using the website. In other cases, like custom parameters, we may have to develop our own wordlist.

  • Depending on whether it's a GET or POST parameter, the command will change.

  • Example: ffuf -w ids.txt:FUZZ -u http://admin.academy.htb:PORT/admin/admin.php -X POST -d 'id=FUZZ' -H 'Content-Type: application/x-www-form-urlencoded'

Last updated