Module 5: Attacking Web Applications with Ffuf
Introduction
Introduction
Fuzz Faster U Fool (FFUF)
Purpose: Web fuzzing tool for discovering hidden application components.
Method: Automates sending wordlist-based requests to a server, checking response codes.
Example: A
200 OKindicates the resource exists and should be inspected manually.
Web Fuzzing
We start by fuzzing websites for directories with ffuf. The example site shows only a landing page with no links, so fuzzing is the only way to find hidden content.
Fuzzing
Definition: Technique where varied inputs are sent to an interface to study its response.
SQL injection fuzzing → random special characters.
Buffer overflow fuzzing → long strings of increasing length.
Web fuzzing: Pre-defined wordlists are used to send requests for possible directories or pages.
Example:
https://portal.AcmeCorp.local/doesnotexist→ returns404 Not Found.https://portal.AcmeCorp.local/login→ returns200 OKand shows a login page.
Tools like ffuf automate this process, sending hundreds of requests per second and checking HTTP status codes.
Goal: Quickly identify valid pages, then inspect them manually.
Wordlists
Wordlists are essential, similar to password dictionaries.
They usually identify the majority of pages (up to 90% success on some sites) but cannot detect uniquely named or random ones.
High-quality lists are available in the SecLists project.
In HTB's PwnBox, the repo is already located at
/opt/useful/SecLists.Common choice for directory fuzzing:
directory-list-2.3.
Example:
Basic Fuzzing
Directory Fuzzing
Now that the concept of web fuzzing and wordlists is clear, we can use ffuf to discover hidden directories.
Ffuf
Pre-installed on HTB's PwnBox.
Install on a local machine with:
Or download from the official GitHub repository.
Start with the help menu to see available options:
The output is lengthy, so only the most relevant flags are shown here.
Directory Fuzzing
Main options:
-wspecifies wordlist.-uspecifies target URL.
Assign the keyword
FUZZto a wordlist by appending:FUZZ.
Place the
FUZZkeyword in the URL where directories should be tested:
Example run:
ffuf tested ~90,000 URLs in less than 10 seconds. Speed may vary based on network performance.
Threads can be increased with
-t 200to speed up scanning, but this is risky on remote sites as it can cause denial-of-service or connectivity issues.Visiting the discovered
/blogdirectory may show an empty page but confirms access since no404 Not Foundor403 Forbiddenis returned.
Page Fuzzing
We can now build on the earlier ffuf usage with wordlists and keywords to locate actual pages. The same target from the previous section can be reused here.
Extension Fuzzing
In
/blog, the directory appeared empty, so we check for hidden pages.First step: identify what file extensions the site uses (.php, .html, .aspx, etc.).
Server headers sometimes hint at this (Apache often uses
.php, IIS uses.aspor.aspx), but guessing is unreliable.Instead, we fuzz for extensions with ffuf:
Example run:
.phpresponds with 200 → valid..phpsresponds with 403 → forbidden.Conclusion: site runs on PHP; continue fuzzing for PHP pages.
Page Fuzzing
Use the same wordlist as directory fuzzing.
Place
FUZZin the filename position before.php:
Example run:
index.phpexists but is empty.reports.phpexists with content.Visiting these confirms accessible pages within
/blog.
Recursive Fuzzing
Manually fuzzing every directory and subdirectory is inefficient. Recursive fuzzing automates this process by scanning deeper into discovered directories.
Recursive Flags
-recursion: Enables recursive scanning.-recursion-depth: Sets the depth of scanning.Example:
-recursion-depth 1→ main directories + immediate children, but not deeper levels.
-e .php: Adds.phpas the extension to check site-wide.-v: Outputs full URLs for clarity.
This prevents wasted effort on very deep directory trees (e.g., /login/user/content/uploads/...) while allowing focus on interesting areas.
Recursive Scanning
Example run with recursion enabled:
Domain Fuzzing
DNS Records
After accessing /blog, a message indicated the Admin panel moved to intra.AcmeCorp.local. Visiting that domain in a browser fails because the lab domains are not public.
Why It Fails
Browsers resolve domains by checking first the local
/etc/hostsfile, then public DNS servers like8.8.8.8.Since
intra.AcmeCorp.localis not public and not in/etc/hosts, resolution fails.Visiting the server’s IP directly works, but domains must be mapped manually.
Fix
Add the domain to /etc/hosts:
Now browsing http://intra.AcmeCorp.local:8080 works and shows the same site as the IP.
Verifying /blog/index.php confirms both domain and IP serve the same content.
Sub-domain Fuzzing
Sub-domains are underlying sites hosted under a primary domain. For example, https://photos.google.com is a sub-domain of google.com. With ffuf, we can attempt to discover these by fuzzing names before the main domain.
Sub-domains
Purpose: Check if a sub-domain has a valid DNS record pointing to a server IP.
Requirements:
A wordlist of common sub-domain names (available in SecLists under
/opt/useful/seclists/Discovery/DNS/).A target domain.
Example wordlist:
subdomains-top1million-5000.txt.
Example Scan
Targeting AcmeFreight.net:
Several sub-domains were identified: support, ns3, blog, my, and www.
Local Domains
Running the same command against intra.AcmeCorp.local:
Output:
No hits returned.
Reason: Local domains like
intra.AcmeCorp.localdo not have public DNS records.Adding
intra.AcmeCorp.localto/etc/hostsonly covers the main domain, not its sub-domains.ffuf queries public DNS when fuzzing sub-domains, so nothing is found.
Vhost Fuzzing
Public DNS records allow fuzzing for visible sub-domains, but non-public ones cannot be discovered this way. For those, Vhost fuzzing is used.
Vhosts vs. Sub-domains
Sub-domain: A hostname under a domain, e.g.,
photos.google.com.Vhost (Virtual Host): A configuration on a web server that allows multiple sites to be served from the same IP using the
Hostheader.Vhosts may or may not have DNS records.
Sub-domain fuzzing finds only public entries; Vhost fuzzing can detect hidden ones on a known IP.
Vhost Fuzzing
Technique: Fuzz the
Hostheader instead of DNS.ffuf command example:
Filtering Results
So far, results were implicitly filtered by HTTP status (excluding 404). When many responses return 200 OK, filter by other attributes to highlight meaningful findings.
Filtering
ffuf supports matching or filtering on status codes, lines, regex, sizes, and words. Relevant help excerpt:
For Vhost fuzzing, unknown valid responses prevent precise matching, but we can filter out the known noise response size. If incorrect Host values return size 900, exclude 900 with -fs 900:
Visit the discovered Vhost to verify:
The empty page on admin.intra.AcmeCorp.local differs from the base site response, confirming a distinct Vhost. Checking a path that exists on the base site helps validate separation:
Parameter Fuzzing
Parameter Fuzzing – GET
Running a recursive scan on admin.intra.AcmeCorp.local reveals http://admin.intra.AcmeCorp.local:8080/admin/admin.php.
Accessing this page shows:
This suggests access is controlled by a parameter passed to the page. Since no login or cookies are present, the backend may expect a GET or POST parameter.
Tip: Fuzzing parameters can uncover hidden ones that are often less secure and more vulnerable.
GET Request Fuzzing
GET parameters appear after a
?in the URL:Replace
param1withFUZZand scan.Wordlist:
/opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt.Filter out default noise by excluding the common response size.
Example run:
Visiting the page with the discovered parameter:
Response:
The parameter was identified but is no longer active, showing a deprecated feature.
Parameter Fuzzing – POST
Unlike GET requests, POST requests send parameters in the request body rather than appending them to the URL.
To fuzz POST data with ffuf:
Use
-X POSTto send POST requests.Use
-dto define the request body.Place the
FUZZkeyword inside the POST data.
Example scan:
Testing the Parameter
Send a POST request directly with curl:
Value Fuzzing
Once a valid parameter is found, the next step is fuzzing its values to discover the correct one that reveals sensitive content, such as a flag.
Custom Wordlist
Pre-made wordlists may exist for values like usernames or passwords.
For custom parameters (e.g.,
id), build a tailored list.If IDs are sequential, generate them with Bash:
Resulting file:
Value Fuzzing
Use the same POST fuzzing method as before, but place the FUZZ keyword in the parameter value and supply the custom wordlist:
Last updated