Attacking Web Applications With Ffuf - HTB Academy
Published: December 15, 2025
Last Updated: December 17, 2025
Download Ffuf Cheatsheet here
Ffuf is used for web fuzzing/directory brute-forcing
- fuzzing for directories
- fuzzing for files and extensions
- identifying hidden vhosts
- fuzzing for PHP parameters
- fuzzing for parameter values
Basically, we send bulk requests to the webserver and check for various response codes to determine if a page exists and/or whether a parameter/value is valid.
Wordlists: SecLists
Directory Fuzzing
locate directory-list-2.3-small.txt
Taking a look at this wordlist we will notice that it contains copyright comments at the beginning, which can be considered as part of the wordlist and clutter the results. We can use the following in ffuf to get rid of these lines with the -ic flag.
-wfor wordlist-ufor url- Assign a wordlist to the keyword
FUZZto refer it to where we want to fuzz.
ffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://SERVER_IP:PORT/FUZZ
We can also increase the number of threads with -t 200
Extension Fuzzing
Common file almost always found in any website:
index.*
If the wordlist already contains a dot (.), don’t add the dot after “index” in the fuzzing command.
ffuf -w /opt/useful/seclists/Discovery/Web-Content/web-extensions.txt:FUZZ -u http://SERVER_IP:PORT/blog/indexFUZZ
Recursive Fuzzing
To start fuzzing for directories within directories, we can automatically start another scan under any newly identified directory.
-recursion to enable recursive scanning
-reursion-depth to specify recursion depth
-e to specify extension
-v to output full URLs so it’s easier to tell which file is under which directory
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
DNS Records
Browsers map URL to an IP by looking into the local /etc/hosts file and the DNS.
To connect to a private website (one that cannot be found in the public DNS) like academy.htb we add it to our /etc/hosts file.
sudo sh -c 'echo "SERVER_IP academy.htb" >> /etc/hosts'
Sub-domain Fuzzing
A sub-domain is any website underlying another domain.
eg. https://academy.hackthebox.com is the academy sub-domain of hackthebox.com
ffuf -w /opt/useful/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u https://FUZZ.inlanefreight.com/
If we run the above on academy.htb, which is a private domain, we will not get any hits back. This means that there are no public sub-domains under academy.htb because it does not have a public DNS record.
Vhost Fuzzing
Allows us to fuzz non-public sub-domains by using HTTP headers
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
-H to specify a header
ffuf -w /opt/useful/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://academy.htb:PORT/ -H 'Host: FUZZ.academy.htb'
If the Vhost exists, we should get a different response size.
Filtering Results
ffuf -h
...SNIP...
MATCHER OPTIONS:
-mc Match HTTP status codes, or "all" for everything. (default: 200,204,301,302,307,401,403)
-ml Match amount of lines in response
-mr Match regexp
-ms Match HTTP response size
-mw Match amount of words in response
FILTER 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
<...SNIP...>
If we know the response size of the incorrect results is, say, 900, we can filter it out using -fs 900.
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 - GET
GET requests are usually passed right after the URL, with a
?symbol
ffuf -w /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:PORT/admin/admin.php?FUZZ=key -fs xxx
- fuzz for subdomains
- add found subdomains to /etc/hosts
- fuzz subdomains recursively to find possible extensions
- parameter fuzzing on the results of step 3
Parameter Fuzzing - POST
POST requests are not passed with the URL and cannot simply be appended after a
?symbol
In PHP, POST data content-type can only accept application/x-www-form-urlencoded
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' -fs xxx
curl http://admin.academy.htb:PORT/admin/admin.php -X POST -d 'id=key' -H 'Content-Type: application/x-www-form-urlencoded'
Value Fuzzing
for i in $(seq 1 1000); do echo $i >> ids.txt; done
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' -fs xxx
Skills Assessment - Web Fuzzing
Commands I ran in order:
- fuzz subdomains
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -H "Host: FUZZ.academy.htb" -u http://94.237.50.128:43758/ -fs 985
→ test, archive, faculty
- add all of these to
/etc/hosts - extension fuzzing
ffuf -w /usr/share/seclists/Discovery/Web-Content/web-extensions.txt:FUZZ -u http://archive.academy.htb:43758/indexFUZZ
→ repeat for all the subdomains found
- start page fuzzing
ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://faculty.academy.htb:43758/FUZZ -recursion -recursion-depth 1 -e .php,.phps,.php7 -v -ic -mr "You don't have access"
→ repeat for all the subdomains found
- Only prints the output if the page contains “HTB”
ffuf -w /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt:FUZZ -u http://faculty.academy.htb:51841/courses/linux-security.php7 -X POST -d "username=FUZZ" -H "Content-Type: application/x-www-form-urlencoded" -fs 781 -mr "HTB"
- curl to get flag
curl http://faculty.academy.htb:51841/courses/linux-security.php7 -X POST -d 'username=harry' -H 'Content-Type: application/x-www-form-urlencoded'