ffuf — Complete Reference

What is ffuf?

Fast F web Fuzzer — Go-based CLI that injects wordlist entries wherever FUZZ appears in URL, headers, or body. Primary Gobuster alternative when you need filter by size/words/lines, Host header vhosts, parameter fuzzing, or multi-wordlist attacks.

OSCP use: Wildcard 200 responses (-fs), vhost discovery (-H "Host: FUZZ"), hidden GET/POST params, extension brute (-e), recursion on found dirs.


Install (Kali)

sudo apt update && sudo apt install -y ffuf
# or: go install github.com/ffuf/ffuf/v2@latest

Verify: ffuf -V

Full install index → Installation - Kali Setup


📌 Template

ffuf -w /usr/share/wordlists/dirb/big.txt -u http://TARGET/FUZZ \
  -e .php,.txt,.html,.bak -c -v -o ffuf_big.txt

📌 Kali Wordlists — Quick Index

AttackPath
Dir — quick/usr/share/wordlists/dirb/common.txt
Dir — medium/usr/share/wordlists/dirb/big.txt
Dir — thorough/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
Dir — SecLists/usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
Vhost / subdomain/usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
GET/POST params/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
Passwords/usr/share/wordlists/rockyou.txt
API/usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt
Backups / .db/usr/share/seclists/Discovery/Web-Content/Common-DB-Backups.txt
ls /usr/share/wordlists/dirb/ /usr/share/seclists/Discovery/Web-Content/ /usr/share/seclists/Discovery/DNS/
sudo apt install seclists wordlists

Basic Syntax

ffuf -w WORDLIST -u http://TARGET/FUZZ

FUZZ = injection point. Custom keyword: -w /path/list:KEYWORD then use KEYWORD in URL.


📌 1) HTTP Options

FlagDescription
-u URLTarget URL — must contain FUZZ (or custom keyword)
-X METHODHTTP method (GET, POST, PUT, DELETE, etc.)
-H "Name: Value"Header (repeatable). e.g. -H "Host: FUZZ.domain.com"
-b "COOKIES"Cookie string NAME=VAL; NAME2=VAL2
-d DATAPOST body — use FUZZ in data
-rFollow redirects
-rawDo not encode URI
-http2Use HTTP/2
-ignore-bodyDon’t fetch response body (faster)
-timeout SECRequest timeout (default 10)
-x PROXYProxy: http://127.0.0.1:8080 or socks5://127.0.0.1:9050
-replay-proxy URLReplay matches through another proxy
-sni NAMETLS SNI (no FUZZ support)
-cc FILEClient certificate
-ck FILEClient key
-recursionRecurse into found dirs — URL must end in FUZZ
-recursion-depth NMax recursion depth (default 0)
-recursion-strategydefault (redirect) or greedy (all matches)

📌 2) Matcher Options (-m*)

Only show responses matching criteria:

FlagDescription
-mc CODESMatch status codes — default 200-299,301,302,307,401,403,405,500 · use all
-ms SIZEMatch response size (bytes)
-mw COUNTMatch word count
-ml COUNTMatch line count
-mr REGEXMatch regex in response body
-mt TIMEMatch time to first byte — >100 or <100 ms
-mmodeMatcher operator: and or or (default or)
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -mc 200,301,403
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -mc all -mr "admin"

📌 3) Filter Options (-f*) — Wildcard Bypass

Hide false positives (OSCP essential):

FlagDescription
-fc CODESFilter status codes — e.g. -fc 404
-fs SIZEFilter response size — e.g. -fs 1234
-fw COUNTFilter word count
-fl COUNTFilter line count
-fr REGEXFilter regex in body
-ft TIMEFilter by response time
-fmodeFilter operator: and or or (default or)

Wildcard 200 workflow:

# Baseline size from fake path
curl -s http://TARGET/nonexistent999 | wc -c
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -fs 1234
 
# Or auto-calibrate
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -ac
Auto-calibrateDescription
-acAuto-calibrate filtering
-acc STRINGCustom calibration string (implies -ac)
-achPer-host autocalibration
-ack KEYWORDAutocalibration keyword (default FUZZ)
-acs STRATEGYCustom autocalibration strategy

📌 4) Input / Wordlist Options

FlagDescription
-w FILEWordlist — path:KEYWORD for custom keyword
-e EXTExtensions comma-separated — .php,.txt,.html
-DDirSearch wordlist mode (with -e)
-enc 'FUZZ:urlencode'Encode keyword — b64encode, etc.
-icIgnore wordlist comments
-mode MODEMulti-wordlist mode: clusterbomb, pitchfork, sniper
-request FILERaw HTTP request file (FUZZ in file)
-request-protoProtocol for raw request (default https)
-input-cmd CMDExternal command produces payloads — uses $FFUF_NUM
-input-num NNumber of inputs for -input-cmd
-input-shell SHELLShell for input command

Multi-wordlist modes

ModeBehavior
clusterbombCartesian product — all combos (default)
pitchforkParallel — word 1 + word 1, word 2 + word 2…
sniperOne payload at a time across multiple positions
# Two wordlists — PARAM and VAL
ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:PARAM \
  -w /usr/share/wordlists/dirb/common.txt:VAL \
  -u "http://TARGET/?PARAM=VAL" -mr "VAL"

📌 5) General / Performance Options

FlagDescription
-t NThreads (default 40)
-p SECDelay between requests — 0.1 or 0.1-2.0
-rate NMax requests per second
-maxtime SECMax total runtime
-maxtime-job SECMax time per recursion job
-cColor output
-vVerbose — full URL + redirect
-sSilent — results only
-jsonJSONL output
-config FILELoad config file
-VVersion
-noninteractiveDisable interactive mode
-saStop on all errors
-sfStop if >95% responses are 403
-seStop on spurious errors
-search HASHSearch ffuf history

📌 6) Output Options

FlagDescription
-o FILEOutput file
-of FORMATjson, ejson, html, md, csv, ecsv, all
-od DIRDirectory for matched results
-orDon’t create output if no results
-debug-log FILEInternal debug log

📌 7) Fuzzing Recipes (OSCP)

Directory / file discovery

Wordlists: quick → /usr/share/wordlists/dirb/common.txt · medium → dirb/big.txt · thorough → /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ
ffuf -w /usr/share/wordlists/dirb/big.txt -u http://TARGET/FUZZ \
  -e .php,.txt,.html,.bak -c -v
ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
  -u http://TARGET/FUZZ -e .php,.txt,.html,.bak -c -v
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt \
  -u https://TARGET/FUZZ -k -ac
ffuf -w /usr/share/seclists/Discovery/Web-Content/Common-DB-Backups.txt \
  -u http://TARGET/FUZZ -e .db,.sql,.bak,.zip

Vhost (Host header)

Wordlists: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt · larger → ...-20000.txt · Jhaddix → /usr/share/seclists/Discovery/DNS/dns-Jhaddix.txt

ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
  -u http://TARGET -H "Host: FUZZ.target.htb" -fs 4242
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
  -u https://TARGET -H "Host: FUZZ" -k -mc 200
ffuf -w /usr/share/seclists/Discovery/DNS/dns-Jhaddix.txt \
  -u http://10.10.10.10 -H "Host: FUZZ.htb" -ac

GET parameter name / value

Wordlists: param names → /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt · values → /usr/share/wordlists/dirb/common.txt or rockyou.txt (passwords)

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
  -u "http://TARGET/page.php?FUZZ=test" -fs 4242
ffuf -w /usr/share/wordlists/dirb/common.txt \
  -u "http://TARGET/page.php?id=FUZZ" -fc 401
 
# Authenticated admin param discovery (streamio-style)
ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
  -u 'https://streamio.htb/admin/?FUZZ=' \
  -b PHPSESSID=hcdd0gnsrol8opisb09o09b9ah --fs 1678

POST fuzzing

Wordlists: passwords → /usr/share/wordlists/rockyou.txt · usernames → /usr/share/seclists/Usernames/top-usernames-shortlist.txt

ffuf -w /usr/share/wordlists/rockyou.txt -u http://TARGET/login.php -X POST \
  -d "username=admin&password=FUZZ" -H "Content-Type: application/x-www-form-urlencoded" -fc 401
 
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/api -X POST \
  -H "Content-Type: application/json" \
  -d '{"user":"FUZZ"}' -fr "error"

Authenticated

ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -b "PHPSESSID=abc123"
ffuf -w /usr/share/wordlists/dirb/big.txt -u http://admin:pass@TARGET/FUZZ

Burp / raw request

# Save request from Burp, replace value with FUZZ
ffuf -request request.txt \
  -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt

Recursive

ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ \
  -recursion -recursion-depth 2 -fc 404

Through proxy (Burp)

ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -x http://127.0.0.1:8080

📌 8) Interactive Mode

Press ENTER during scan → adjust filters live:

fc [code]    - filter status
fs [size]    - filter size
fw [words]   - filter words
fl [lines]   - filter lines
show         - show current matches
restart      - restart job
savejson f   - save matches
help
ENTER        - resume

📌 WebSockets — discovery (HTTP only)

ffuf does not speak WebSocket frames — it fuzzes HTTP URLs, headers, and bodies. Use it to find WebSocket endpoints and upgrade paths, then test messages in Burp Suite or Curl.

Fuzz common WebSocket paths

ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt \
  -u http://TARGET/FUZZ -e .ws,.socket -fc 404 -c
 
ffuf -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
  -u http://TARGET/FUZZ -c
# look for: /ws, /websocket, /socket.io, /cable, /graphql → **[[GraphQL]]**, /api/ws

Fuzz HTTP upgrade / handshake endpoint

Some apps expose WS on a path that returns 101 Switching Protocols only with correct headers:

ffuf -w /usr/share/wordlists/dirb/common.txt \
  -u http://TARGET/FUZZ \
  -H "Connection: Upgrade" -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -mc 101,200,400,403 -c

Fuzz REST APIs that front WebSocket apps

SPAs often use HTTP login → token → first WS message. Fuzz HTTP params and JSON bodies; SQLi may live in WS messages instead:

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
  -u "http://TARGET/api?FUZZ=1" -fs 0 -c

After finding /ws or similar → Burp Suite WebSockets history → manual SQLi → SQLMap via local HTTP bridge.


📌 9) ffuf vs Gobuster

SituationTool
Simple dir brute, clean 404Gobuster
Wildcard same-size 200ffuf -fs / -ac
Vhost / Host headerffuf
Multi-param / clusterbombffuf
DNS subdomain bruteGobuster dns
Raw Burp requestffuf -request

📌 Quick Cheat Sheet

# Dir — common wordlist
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -fs 1234 -c
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ -ac
 
# Vhost
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
  -u http://TARGET -H "Host: FUZZ.htb" -fs 4242
 
# Dir + extensions + recursion
ffuf -w /usr/share/wordlists/dirb/big.txt -u http://TARGET/FUZZ \
  -e .php,.txt -recursion -recursion-depth 1
 
# Burp proxy
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://TARGET/FUZZ \
  -x http://127.0.0.1:8080 -mc 200,301,403
 
# Raw Burp request + param wordlist
ffuf -request req.txt \
  -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -fc 404