← Back to writing
Tools & Cheatsheets

ffuf Fuzzing Guide

Jun 03, 2024
4 min read
lawbyte

ffuf (Fuzz Faster U Fool) is the fastest web fuzzer available. This guide covers every use case from basic directory brute-forcing to advanced parameter discovery and virtual host enumeration, with filter tuning to eliminate noise.

Installation

# Go install
go install github.com/ffuf/ffuf/v2@latest

# Binary release
wget https://github.com/ffuf/ffuf/releases/latest/download/ffuf_linux_amd64.tar.gz
tar -xzf ffuf_linux_amd64.tar.gz && mv ffuf /usr/local/bin/

Basic Flags

-u         # URL with FUZZ keyword
-w # wordlist path (use path:KEYWORDNAME for multiple)
-c # colorize output
-v # verbose (show full URL)
-t # threads (default 40)
-rate # max requests/second
-timeout # per-request timeout in seconds
-recursion # recursive fuzzing
-o # output file
-of # output format (json, csv, ecsv, md, html)

Directory & File Discovery

# Basic directory fuzzing
ffuf -u https://target.com/FUZZ -w /usr/share/seclists/Discovery/Web-Content/common.txt -c

# With extensions
ffuf -u https://target.com/FUZZ -w wordlist.txt -e .php,.txt,.html,.bak,.old -c

# Larger wordlist for thorough coverage
ffuf -u https://target.com/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt \
-e .php,.asp,.aspx,.jsp,.html,.txt \
-c -t 50

# Recursive — auto-recurse into found directories
ffuf -u https://target.com/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-recursion -recursion-depth 3 \
-c

# Case insensitive fuzzing (useful for Windows targets)
ffuf -u https://target.com/FUZZ -w wordlist.txt -c -ic

Response Filtering

Filtering is the most important skill in ffuf. Without it you drown in false positives.

# Filter by status code (default shows 200,204,301,302,307,401,403,405,500)
-mc 200,302 # match ONLY these codes
-fc 404 # filter OUT 404
-fc 404,403 # filter multiple

# Filter by response size
-fs 1234 # filter out responses of exactly 1234 bytes
-ms 200-1000 # match responses between 200-1000 bytes

# Filter by word count
-fw 10 # filter responses with 10 words
-mw 50-500 # match responses with 50-500 words

# Filter by line count
-fl 50 # filter responses with 50 lines
-ml 1-100 # match 1-100 lines

# Filter by regex
-fr "Not Found" # filter responses containing "Not Found"
-mr "admin" # match responses containing "admin"

Calibration workflow

  1. Run a few quick requests to see what the default response looks like for non-existent paths.
  2. Note the size or word count of the 404 page.
  3. Add -fs or -fw to filter that out.
# Step 1 — check baseline response
curl -s https://target.com/definitely-not-exists | wc -c # byte count
# → 3472 bytes

# Step 2 — fuzz with that filtered
ffuf -u https://target.com/FUZZ -w wordlist.txt -fs 3472 -c

# Auto-calibration (experimental)
ffuf -u https://target.com/FUZZ -w wordlist.txt -ac -c

Parameter Discovery

GET parameter fuzzing

# Known endpoint, unknown parameter names
ffuf -u "https://target.com/api/user?FUZZ=test" \
-w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
-fs <baseline_size> -c

# Parameter name + value fuzzing
ffuf -u "https://target.com/page?param=FUZZ" \
-w /usr/share/seclists/Fuzzing/special-chars.txt \
-c

POST parameter fuzzing

# POST body fuzzing (JSON)
ffuf -u https://target.com/api/login \
-X POST \
-H "Content-Type: application/json" \
-d '{"FUZZ":"test"}' \
-w parameter_names.txt \
-fs <baseline> -c

# POST body value fuzzing
ffuf -u https://target.com/api/login \
-X POST \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"FUZZ"}' \
-w /usr/share/wordlists/rockyou.txt \
-fs <baseline> -c

Subdomain Enumeration

# Basic subdomain fuzzing
ffuf -u https://FUZZ.target.com \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-c

# With Host header (when target uses vhosts)
ffuf -u https://target.com \
-H "Host: FUZZ.target.com" \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-fc 302,404 -c

Virtual Host / vHost Fuzzing

When multiple virtual hosts share an IP, fuzz the Host header:

ffuf -u http://10.10.10.100 \
-H "Host: FUZZ.target.com" \
-w /usr/share/seclists/Discovery/DNS/namelist.txt \
-fs <default_response_size> \
-c

Multiple Wordlist / Multiple FUZZ Keywords

# Two wordlists — FUZZ and W2 keywords
ffuf -u https://target.com/FUZZ/W2 \
-w wordlist1.txt:FUZZ \
-w wordlist2.txt:W2 \
-c

# Username + password brute force
ffuf -u https://target.com/login \
-X POST \
-d "username=FUZZ&password=W2" \
-H "Content-Type: application/x-www-form-urlencoded" \
-w users.txt:FUZZ \
-w passwords.txt:W2 \
-fc 401 -c

# Cluster bomb mode (all combinations)
# Above is cluster bomb by default with multiple wordlists

Header Fuzzing

# Fuzz a specific header
ffuf -u https://target.com/admin \
-H "X-Forwarded-For: FUZZ" \
-w /usr/share/seclists/Fuzzing/IPv4-useful-ranges.txt \
-mc 200 -c

# Fuzz header name
ffuf -u https://target.com/ \
-H "FUZZ: 127.0.0.1" \
-w /usr/share/seclists/Fuzzing/http-request-headers/http-request-headers-large.txt \
-mr "Welcome" -c

# Fuzz cookie value
ffuf -u https://target.com/dashboard \
-b "session=FUZZ" \
-w session_tokens.txt \
-fc 302 -c

# Fuzz cookie name
ffuf -u https://target.com/ \
-b "FUZZ=admin" \
-w cookie_names.txt \
-mr "admin panel" -c

Authenticated Fuzzing

# With session cookie
ffuf -u https://target.com/api/FUZZ \
-H "Cookie: PHPSESSID=your_session_here" \
-w api_endpoints.txt \
-c

# With Bearer token
ffuf -u https://api.target.com/v1/FUZZ \
-H "Authorization: Bearer eyJhb..." \
-w api_endpoints.txt \
-mc 200,201,204 -c

Output and Reporting

# JSON output for parsing
ffuf -u https://target.com/FUZZ -w wordlist.txt -o results.json -of json

# HTML report
ffuf -u https://target.com/FUZZ -w wordlist.txt -o report.html -of html

# CSV for spreadsheet import
ffuf -u https://target.com/FUZZ -w wordlist.txt -o results.csv -of csv

# Parse JSON output
cat results.json | python3 -c "import json,sys; [print(r['url']) for r in json.load(sys.stdin)['results']]"

# General web content
Discovery/Web-Content/common.txt # ~4k words
Discovery/Web-Content/raft-large-words.txt # ~119k words
Discovery/Web-Content/raft-large-directories.txt

# API endpoints
Discovery/Web-Content/api/api-endpoints.txt
Discovery/Web-Content/api/objects.txt

# Parameters
Discovery/Web-Content/burp-parameter-names.txt
Fuzzing/LFI/LFI-Jhaddix.txt

# Subdomains
Discovery/DNS/subdomains-top1million-5000.txt
Discovery/DNS/subdomains-top1million-110000.txt

# Passwords
Passwords/rockyou.txt
Passwords/Common-Credentials/10-million-password-list-top-10000.txt

One-Liner CTF Workflow

# Quick full scan on CTF box
ffuf -u http://10.10.10.1/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-e .php,.txt,.html,.bak \
-c -ac \
-o scan_results.json -of json

# Follow up on found dirs
ffuf -u http://10.10.10.1/found-dir/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-c -ac

Discussion

Leave a comment · All fields required · No spam

No comments yet. Be the first.