FFUF (Fuzz Faster U Fool): A Fast, Flexible Web Fuzzing Tool
Introduction: FFUF (Fuzz Faster U Fool) is a high-performance web fuzzing tool written in Go. It’s designed to discover hidden web content – such as files, directories, subdomains, parameters, and virtual hosts – by brute-forcing with wordlists. Its Go implementation makes it cross-platform and extremely fast (multi-threaded). In practical use, ffuf is prized for its flexibility: it can fuzz URLs, parameters, headers, and more. For example, it “allows you to brute-force parameters, directories, subdomains, and more” thanks to its speed and options. Security professionals consider tools like ffuf (alongside DirBuster, Gobuster, etc.) to be staples of the pentester’s toolkit for uncovering hidden endpoints.
Installation: FFUF can be installed in several ways: on Debian-based systems (like Kali) it’s available via the package manager, e.g. sudo apt-get install ffuf
. On macOS you can use Homebrew: brew install ffuf
. If you have Go ≥1.16 installed, you can run go install github.com/ffuf/ffuf/v2@latest
. Alternatively, clone the repository and build manually:
git clone https://github.com/ffuf/ffuf
cd ffuf
go get && go build
This requires Go 1.16+. After installation, running ffuf -h
or ffuf --version
should confirm it’s working.
Core Features
Directory/File Fuzzing: The basic use of ffuf is to brute-force directories or files on a web server by placing the special FUZZ
keyword in the URL. For example:
ffuf -w wordlist.txt -u https://target.com/FUZZ
This will try every word from wordlist.txt
in place of FUZZ
, checking which URLs return valid responses. By default ffuf reports responses that look interesting (e.g. status codes in the 200-399 range). You can adjust which responses match using filtering (see below). Typical wordlists come from SecLists or similar collections.
Virtual Host Discovery: Besides paths, ffuf can fuzz HTTP Host headers to discover hidden virtual hosts on the same IP. To do this, target the base URL and use -H "Host: FUZZ"
:
ffuf -w vhost-wordlist.txt -u https://target.com/ -H "Host: FUZZ"
Each entry in vhost-wordlist.txt
is tried as a hostname. Often you will also filter out the default host response by size or content. For example, if the normal site responds with 4242 bytes, you can add -fs 4242
to ignore those, showing only differing responses. An example from ffuf’s docs is:
ffuf -w vhosts.txt -u https://target.com -H "Host: FUZZ" -fs 4242
This flags any hostnames that produce a different-sized response.
Subdomain Fuzzing: To find public subdomains via DNS, ffuf simply fuzzes the hostname portion. For example, to brute-force subdomains of example.org
using a list subs.txt
:
ffuf -w subs.txt -u http://FUZZ.example.org/
This makes DNS lookups for each guessed subdomain. Any that exist will show up as successful hits. As one write-up notes, “With FFUF we simply add the FUZZ parameter to the URL where the subdomain would be”. In practice, include FUZZ
in the host and optionally use -H "Host: FUZZ"
if needed.
GET/POST Parameter Fuzzing: FFUF can fuzz query parameter names or values. To fuzz parameter names, insert FUZZ
before the =
. For instance:
ffuf -w param-names.txt -u https://target.com/script.php?FUZZ=test
This tries words from param-names.txt
as parameter keys. If an unknown parameter returns a 4242-byte page, you can filter it out with -fs 4242
to show only non-default responses.
To fuzz values of a known parameter, swap FUZZ
into the value:
ffuf -w values.txt -u https://target.com/script.php?user=admin&pass=FUZZ
For example, testing common passwords or tokens. You can filter out expected status codes (e.g. -fc 401
) to focus on success cases.
For POST data fuzzing, use -X POST
and -d
to send form data, with FUZZ
in the value. Example from ffuf’s docs:
ffuf -w passwords.txt -X POST -d "username=admin&password=FUZZ" -u https://target.com/login.php -fc 401
This replaces FUZZ
with each password guess, ignoring (filtering out) the 401 unauthorized responses. FFUF handles JSON or multipart forms similarly (just include -H "Content-Type: application/json"
or other headers).
Recursive Fuzzing: FFUF can automatically recurse into discovered directories. Use -recursion
to enable it and -recursion-depth <n>
to limit depth. For example:
ffuf -w wordlist.txt -u https://target.com/FUZZ -recursion -recursion-depth 2
This will, for any path found, append FUZZ
again at the end up to 2 levels. You can also use -maxtime-job
to limit time per recursive branch. (Note: without recursion, FUZZ must be at the end of the URL.)
Filter Options: FFUF has rich filters to ignore common “noise” responses. Key flags include:
-fc <codes>
: filter out (exclude) specific HTTP status codes or ranges (e.g.-fc 404
to drop “not found” results).-fs <size>
: exclude responses of a given size (in bytes), or ranges (e.g.-fs 42
or-fs 1-100,500-1024
), useful if the default error page has a consistent length.-fw <words>
and-fl <lines>
: filter by number of words or lines in the response.-ft <time>
: filter by time to first byte (for timing-based analysis). These let you, for instance, ignore all 404s or any responses matching the known “not found” content. You can combine filters with logical AND/OR using-fmode
and similarly use match options (-mc
,-mr
, etc.) to only keep certain results.
Concurrency and Rate Limiting: FFUF is highly concurrent by default. Use -t <threads>
(or --threads
) to set the number of worker threads (default 40). For example, -t 100
for 100 parallel requests. To avoid overwhelming a target or bypass rate limits, FFUF also supports a rate cap with -rate <rps>
. For instance, -rate 50
limits ffuf to ~50 requests per second. (Alternatively, -p <delay>
adds a fixed or random delay between requests.) Balancing threads and rate can improve reliability – too many threads without throttling may trigger WAF blocks or network issues.
Output Formats: Results can be written to files in various formats using -o <file>
and -of <format>
. Supported formats include JSON, HTML, Markdown, CSV, etc. (default is JSON). For example, -o results.json -of json
saves JSON output, and -of csv
produces CSV. This allows easy parsing of results or reporting.
Advanced Techniques
Authentication Fuzzing: FFUF can brute-force authentication. For HTTP Basic Auth, you can include credentials directly in the URL (e.g.
http://user:PASS@target.com/
) or add anAuthorization: Basic
header with-H
. Moreover, ffuf’s multi-wordlist mode supports clusterbomb testing of user/password lists simultaneously (see below). While ffuf doesn’t have a dedicated “auth mode”, creative use of headers or URL credentials lets you fuzz login pages or services.Custom Header Fuzzing: Like directory names, you can fuzz headers. For example:
ffuf -w wordlist.txt -u https://target.com/ -H "X-Api-Key: FUZZ"
This will replace
FUZZ
in theX-Api-Key
header with each word. Multiple-H
flags are allowed for different headers (ffuf will combine them). This is useful for finding hidden API keys or bypass tokens in headers.Fuzzing Multiple Parameters (Multi-Wordlist): FFUF’s
-mode
option (defaultclusterbomb
) lets you fuzz several keywords in parallel. For example, given two wordlists (users.txt
,pass.txt
), you can assign them different FUZZ keywords in one command:ffuf -u http://example.com/?user=FUZZUSER&pass=FUZZPASS \ -w users.txt:FUZZUSER,pass.txt:FUZZPASS -mode clusterbomb
This tries every combination of user and password (clusterbomb mode). If you pair them by index instead (one-to-one), use
-mode pitchfork
. For example, in a raw HTTP request file (exported from Burp), you can similarly use named placeholders and-request
. FFUF’s examples show using-request
with-w userlist:FUZZUSR,passwordlist:FUZZPW
to fuzz a saved login request.Burp Suite Integration: FFUF can integrate with Burp in two ways. First, export a raw HTTP request from Burp (as a text file), insert
FUZZ
where you want to fuzz (e.g. in a POST body or URL), and run:ffuf -request /path/to/request.txt -w wordlist.txt
FFUF will replay that request for each payload. This allows fuzzing within the context of a captured request. Second, you can use Burp as a proxy. Run a proxy listener in Burp (e.g. on 127.0.0.1:8080), then point ffuf to it:
ffuf -u http://127.0.0.1:8080/FUZZ -w wordlist.txt
Now ffuf’s requests go through Burp (and you’ll see them in Burp’s proxy). Both methods let you leverage Burp’s analysis features while fuzzing.
Timing-Based Fuzzing: You can detect time-based behaviors by measuring response delays. FFUF has a time-to-first-byte filter (
-ft
). For example, use-ft >100
to show only requests where the server took over 100 ms to respond. In practice, combine this with payloads that may induce delays (e.g. SQL injection time delays) and filter for unusually slow responses. Also, the-timeout
option can kill very slow requests.
Practical Examples
Here are some concrete ffuf usages illustrating the above features:
Basic directory scan:
ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt -u https://target.com/FUZZ
This tests common directories under
https://target.com/
. Any valid hits are shown.VHost scan:
ffuf -w vhosts.txt -u https://10.0.0.1/ -H "Host: FUZZ.target.com" -fs 500
Finds virtual hosts for
target.com
on that IP, filtering out 500-byte default pages.Subdomain enumeration:
ffuf -w subdomains.txt -u http://FUZZ.example.org/
Tests subdomains of
example.org
. Matches appear if DNS resolution succeeds.GET parameter fuzz (name):
ffuf -w parameters.txt -u https://target.com/search.php?FUZZ=query -fs 1024
Tries parameter names from
parameters.txt
. Ignores 1024-byte default responses.GET parameter fuzz (value):
ffuf -w passlist.txt -u https://target.com/login.php?user=admin&pass=FUZZ -fc 401
Brute-forces the
pass
value. Filters out 401 errors, so non-401 responses (e.g. 200) stand out.POST fuzz:
ffuf -w payloads.txt -X POST -d "comment=FUZZ" -u https://target.com/submit -mc 200
Sends each payload as the
comment
field. Only 200 OK responses are kept.Recursive scan:
ffuf -w smalllist.txt -u https://target.com/FUZZ -recursion -recursion-depth 3 -timeout 5
Fuzzes directories recursively up to 3 levels, with each request timing out after 5s.
Filtering and output:
ffuf -w list.txt -u https://target.com/FUZZ -fc 404,302 -fl 0-10 \ -o results.json -of json
Excludes 404/302 codes, ignores short responses (0–10 lines), and writes results in JSON format.
Multiple parameters (clusterbomb):
ffuf -u "https://api.target.com/?user=FUZZUSR&api_key=FUZZKEY" \ -w users.txt:FUZZUSR,keys.txt:FUZZKEY -mode clusterbomb
Tries all combinations of users and API keys.
Rate-limited scan:
ffuf -w biglist.txt -u https://target.com/FUZZ -t 200 -rate 50
Uses 200 threads but throttles to ~50 req/s, to be gentler on the server.
Fuzzing headers:
ffuf -w headers.txt -u https://target.com/ -H "X-Forwarded-For: FUZZ"
Tries to inject values into the
X-Forwarded-For
header, which can bypass IP restrictions.
Comparison with Other Tools
FFUF is often compared to Gobuster, DirBuster, Feroxbuster, and Dirsearch. In practice:
Gobuster: Also written in Go, Gobuster is widely used for directory/DNS fuzzing. Like ffuf it’s very fast, especially with many threads, and supports DNS and vhost modes. Gobuster’s interface is simpler (one position for FUZZ). Performance-wise, ffuf and Gobuster are roughly equivalent in speed when given the same concurrency. FFUF’s edge is flexibility: it can fuzz more than just paths (headers, POST data, etc.) and has richer filtering/output.
DirBuster: A Java GUI tool (from OWASP) with large built-in lists. DirBuster is older and typically slower (single-threaded or fewer threads). It’s less convenient for scripting. FFUF is far more efficient for large lists and can run in any shell.
Dirb/Dirsearch: Dirb (C) and Dirsearch (Python) are also older CLI scanners. They lack ffuf’s advanced filtering and multi-parameter modes. For basic scanning tasks, they produce similar results but tend to be slower or less featureful.
Feroxbuster: A Rust-based tool often cited alongside ffuf. In community comparisons, all three (ffuf, Gobuster, Feroxbuster) perform similarly under similar settings. Some users prefer Feroxbuster’s built-in recursion and robots.txt parsing, but ffuf can achieve similar recursion manually.
In summary, ffuf’s strength is its versatility: beyond directories, it can fuzz query params, POST bodies, headers, and import raw requests. Its speed is on par with other top tools, but it can be easier to integrate into complex workflows (e.g. with Burp).
Common Pitfalls & Troubleshooting
False Positives/Negatives: If you get too many hits or no hits, adjust filters. For example, if the site returns HTTP 200 (OK) for “not found” pages, you’ll need to filter by size or a keyword instead of status. Try toggling
-fc
and-fs
until results make sense. Also remember ffuf does not follow redirects by default; use-r
if you expect redirects to valid content.Encoding/Quoting: On the shell, make sure to quote or escape special chars in URLs or POST data. E.g.
&
in-d "a=1&b=FUZZ"
often needs to be quoted or escaped so the shell doesn’t split it.Concurrency Issues: Too high
-t
(threads) or no-rate
throttle can overwhelm small targets or hit WAFs. If ffuf seems to hang or flood, reduce threads or add-rate
. Conversely, if it’s very slow, increase threads.Wordlist Mistakes: Ensure your wordlist matches the context. For virtual host fuzzing, use hostnames (e.g. “admin”, “dev”) not directory names. Use the
-w file:KEYWORD
syntax correctly when fuzzing multiple places. For example,-w users.txt:FUZZUSR, pass.txt:FUZZPW
requires using those keywords (FUZZUSR
,FUZZPW
) in the URL or request.Installation/Proxy Errors: If using
-request
and getting no output, check the format of the request file (see ffuf docs). If running ffuf through a proxy, ensure you use-x
or-proxy
. If you see certificate errors, use-ignore-certificate
.
If ffuf is giving many errors, try sending its traffic through Burp or a proxy to inspect; some targets ban rapid fuzzing. Reducing -t
or adding delays often helps recover from connection errors.
Use Cases and Scenarios
FFUF shines in many real-world security tasks:
Bug Bounty & Pentests: Quickly enumerating hidden endpoints is a staple in bug hunting. FFUF is ideal for crawling a new target: you can enumerate
/admin/
, backup files, forgotten pages, API endpoints, etc., in minutes. Its ability to fuzz parameters also helps find hidden API routes or bypass filters (for example, fuzzingFUZZ
into a GraphQL endpoint or hidden GET params). In many bounty write-ups, finding an unlinked page via wordlist fuzzing with ffuf has led to high-severity findings.Subdomain Takeover Hunting: Security researchers often use ffuf to brute-force subdomains (
FUZZ.example.com
) and detect dangling records or takeovers. Its speed allows testing thousands of names quickly to spot misconfigured or inactive subdomains.WAF/Firewall Testing: Because ffuf can vary payloads and throttle itself, it can test WAF rules by sending lots of requests and observing which ones get blocked. Timing-based filters (
-ft
) can even help detect throttling.Automation: FFUF can be scripted (e.g. in a CI pipeline or as part of an automated scan) because it has non-interactive output (JSON) and can read wordlists from stdin. Pentesters often chain ffuf with other tools (e.g. pipe directories into ffuf, or use its output for further processing). Its interactive mode (pause with ENTER) is also handy during an interactive pentest when you want to examine results on the fly.
Teaching and CTFs: In educational scenarios (like labs or CTFs), ffuf is the go-to tool for any directory or parameter discovery challenge. The official ffuf “playground” (ffuf.me or ffufme Docker) even exists for practice.
Summary and Recommendations
FFUF is a powerful, flexible fuzzing toolkit that excels at content discovery. It’s fast (Go-based, multithreaded), but more importantly it’s versatile – supporting directories, hosts, parameters, headers, and more. To use it effectively: always pick or build good wordlists (project-specific lists often find more than generic ones). Start with broad scans (default threads, generic wordlists), then narrow results with filters (-fs
, -fc
, etc.). Integrate ffuf with proxies or other tools when needed (using -request
or -x
). For large scans, adjust -t
and -rate
to avoid detection or crashing targets.
Finally, keep an eye on output formats: JSON or CSV exports make it easy to review or share findings. With practice, ffuf becomes an indispensable part of any web security assessment — from quick reconnaissance to deep parameter fuzzing.