What fuzzing actually is
Fuzzing means sending a large, structured set of inputs at a target and watching which responses stand out from the crowd.
In web testing the inputs come from a wordlist, and a single placeholder, the keyword FUZZ, marks exactly where each word gets dropped into the request. Move that placeholder and you change the whole question you are asking. Put it in the path and you discover hidden directories and files. Put it in a parameter value and you probe for injection. Put it in the Host header and you enumerate virtual hosts the DNS never advertised.
The work is not the sending, it is the reading. A fuzzer can fire tens of thousands of requests in seconds, so the skill is telling signal from noise: a status code, a response size, or a timing that differs from the baseline is the thing you investigate. On a real engagement you run this only against systems within your authorized scope, and never against anything you have not been given written permission to test.
ZAP's fuzzer, the established workbench
ZAP is the tool most people meet first, and it is worth knowing where it stands today. It is a full dynamic analysis suite (an intercepting proxy, a spider, and an active and passive scanner), and the Fuzzer is one module inside that suite.
ZAP began in 2010 as an OWASP project created by Simon Bennetts and grew into the most widely used web application scanner. In 2023 the developers moved to the Linux Foundation's Software Security Project to secure funding, and in September 2024 the core team joined Checkmarx, where the project was rebranded ZAP by Checkmarx. It remains open source and free. So "OWASP ZAP" is technically a legacy name now, even though most people still say it.
The workbench workflow
ZAP's strength is that the fuzzer lives right next to the proxy, so capturing a real authenticated request and fuzzing one field of it is point and click.
- Proxy your traffic. Route the browser through ZAP, or use ZAP's bundled browser, and exercise the target so the request lands in the History tab.
- Open the fuzzer. Right click the request in the Sites or History tab and choose Attack, then Fuzz, to load that request into the Fuzzer dialog.
- Mark the target. Highlight the exact value you want to replace, then add a payload source: a built in list, a file, or a generated set.
- Attach processors. Optionally add Message Processors, which can read and rewrite each request, control the run, and feed results back into the interface.
- Run and triage. Start the fuzzer and read the results table, sorting by status code and response size to spot the responses that break the pattern.
Its payload engine draws on the older OWASP JBroFuzz project and ships lists from FuzzDB, with a few FuzzDB files deliberately left out because antivirus scanners flag them. The limits are exactly what push people toward a modern tool: it is a Java desktop application, the fuzzer is built for interactive use rather than scripting, and it is heavier than you want for fast, repeatable, automatable content discovery.
ffuf, the command line standard
ffuf, short for Fuzz Faster U Fool, is the current community standard for web fuzzing.
It is a fast fuzzer written in Go, shipped as a single static binary, and it is built for the terminal, which is precisely what makes it scriptable and pipeline friendly in a way ZAP's fuzzer is not. The whole model rests on one idea: put the keyword FUZZ anywhere in the URL, a header, or the body, and ffuf swaps in each line of your wordlist.
# Kali, Debian, Ubuntu (preinstalled on Kali, Parrot, BlackArch)
sudo apt install ffuf
# macOS (Homebrew)
brew install ffuf
# From source, and the same command updates it (needs Go 1.16+)
go install github.com/ffuf/ffuf/v2@latest
Three attack modes
These mirror Burp Intruder, which makes them an easy bridge for anyone who has already seen Burp.
Sniper
One wordlist, one position. The simplest case, and the default mental model for directory or parameter work.
Pitchfork
Multiple wordlists that advance in lockstep, pairing line one with line one. Good for matched user and password lists.
Clusterbomb
Every combination of every wordlist. The ffuf default, and the right choice when you want full coverage of two inputs.
Matching and filtering: how you cut the noise
This is the part that makes ffuf usable rather than overwhelming. Matchers keep responses (-mc status, -ms size, -mw words, -ml lines, -mr regex) and filters discard them (-fc, -fs, -fw, -fl). The everyday pattern is to match everything, then filter out the baseline, for example -mc all -fs 4242 to drop the standard not-found response. In practice you almost always add -ac, auto-calibration, which learns that baseline for you. Without it, results are usually too noisy to read.
Command cheat sheet
Each block is copy and run ready. The FUZZ keyword is highlighted so you can see where the injection point moves for each kind of test. Swap webapp-edge01 for your authorized target.
# Hidden directories
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-u http://webapp-edge01/FUZZ -ac -c
# Same run, but append extensions to every word
ffuf -w wordlist.txt -u http://webapp-edge01/FUZZ -e .php,.html,.txt,.bak -ac
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-u http://webapp-edge01/ -H "Host: FUZZ.target.local" -fs 4242
# Find a hidden parameter name (assume invalid names return 4242 bytes)
ffuf -w paramnames.txt -u 'http://webapp-edge01/script.php?FUZZ=test' -fs 4242
# Fuzz the value of a known parameter (assume a wrong value returns 401)
ffuf -w values.txt -u 'http://webapp-edge01/script.php?id=FUZZ' -fc 401
# POST login fuzzing (quote the & so the shell does not split it)
ffuf -w passwords.txt -X POST \
-d 'username=admin&password=FUZZ' \
-u http://webapp-edge01/login.php -fc 401
# JSON body, e.g. an IDOR probe on a numeric id (set Content-Type yourself)
ffuf -w ids.txt -X PUT \
-H 'Content-Type: application/json' \
-d '{"uid":"FUZZ"}' \
-u https://webapp-edge01/api/v1/users/1 -mc all -fc 400
# Capture a request in ZAP or DevTools, drop FUZZ into the saved file,
# and let ffuf replay it. Cleanest way to carry cookies and tokens.
ffuf --request req.txt --request-proto https -w wordlist.txt -ac -o results.json
# Send only the matched hits into ZAP for manual follow-up
ffuf -w wordlist.txt -u http://webapp-edge01/FUZZ \
-replay-proxy http://127.0.0.1:8080 -ac
# Recursion, with a per-job time cap so you do not loop forever
ffuf -w wordlist.txt -u http://webapp-edge01/FUZZ \
-recursion -recursion-depth 2 -maxtime-job 120 -ac
# Report-ready output. JSON feeds n8n or a reporting script; HTML is client friendly.
ffuf -w wordlist.txt -u http://webapp-edge01/FUZZ -of html -o report.html
The -replay-proxy flag is the pairing to remember. ffuf does the fast, high volume discovery, and forwards only the interesting responses into ZAP or Burp so the proxy history is not drowned in hundreds of thousands of misses. You discover with ffuf, then pivot to ZAP's repeater to work a finding by hand.
Build your ffuf command
Pick the kind of test, fill in the target, and the command assembles below with the FUZZ keyword placed in the right spot. Adjust the matchers, filters, and output to match the situation, then copy the result.
ZAP fuzzer versus ffuf
Neither replaces the other outright. ZAP is a complete analysis platform whose fuzzer shines for surgical, proxy adjacent work. ffuf is the fast, scriptable discovery engine. The honest answer for most assessments is both.
| Dimension | ZAP by Checkmarx (Fuzzer) | ffuf |
|---|---|---|
| Interface | Java desktop GUI, right click to fuzz | Command line, single Go binary |
| Best at | Fuzzing one field of a captured request, next to the proxy | Fast directory, parameter, and vhost discovery at scale |
| Payload model | Built in lists plus FuzzDB and JBroFuzz, message processors | Any wordlist, placed with the FUZZ keyword |
| Modes | Manual payload sets per position | Sniper, pitchfork, clusterbomb |
| Scripting and CI | Awkward, meant for interactive use | Native, with JSON, CSV, and HTML output |
| Result triage | GUI table, sort by code and size | Matchers, filters, and auto-calibration |
| Scope | Full suite: scanner, spider, reports | Fuzzing and discovery only |
Other tools worth knowing
ffuf did not appear in a vacuum, and it is not the only modern option. A quick map of the neighborhood:
wfuzz
The older Python fuzzer that ffuf drew inspiration from. Still capable, but showing its age, and largely displaced by ffuf in day to day practice.
gobuster & feroxbuster
Content discovery cousins, written in Go and Rust. feroxbuster in particular is built around fast recursive discovery.
Caido
A newer, Rust based proxy that many testers are adopting alongside or instead of Burp for a lighter, modern interface.
Burp Suite Intruder
The commercial GUI peer to ffuf. Powerful, but rate limited without a Pro license, which is exactly the friction ffuf avoids.
It is tempting to say ffuf is simply the fastest. The literature is more nuanced: at least one comparison found wfuzz competitive or faster on raw request rate and CPU efficiency. ffuf's real edge is its workflow, its single binary deployment, its active maintenance, and its ecosystem, rather than always winning on pure speed. Teach it as the modern standard, not as the universal speed champion.
Wordlists and a safe place to practice
A fuzzer is only as good as its wordlist. The standard source is SecLists, preinstalled on Kali under /usr/share/seclists. Common starting points: Discovery/Web-Content/raft-large-directories.txt for directories, Discovery/DNS/subdomains-top1million-5000.txt for subdomains and virtual hosts, and Discovery/Web-Content/burp-parameter-names.txt for parameters. Project specific lists, built from the words a target actually uses, often find more than any generic list.
Fuzzing generates a flood of traffic and can trip rate limits, exhaust resources, or trigger a WAF. Only ever run it against a system you own or have explicit written authorization to test. To practice the tool itself without touching the lab, ffuf.me is a host built specifically for it, available live or as a local Docker container.
References and further reading
- ffufgithub.com/ffuf/ffuf and the ffuf wiki
- practiceffuf.me, an intentionally fuzzable practice host
- zapZAP Fuzzer add-on documentation and the ZAP project
- owaspOWASP WSTG, Fuzzing appendix
- listsSecLists, the standard wordlist collection