Web Application Fuzzing: Techniques, Tools, and Methodology
Fuzzing is the practice of sending unexpected, malformed, or boundary-case inputs to an application and observing what breaks. In web security testing, fuzzing spans two distinct activities: content discovery (finding hidden endpoints and files) and input fuzzing (probing parameters for injection and logic flaws). Both are essential phases of a thorough web application penetration test.
This guide covers the practical application of web fuzzing: tool selection, wordlist strategy, response interpretation, and the specific fuzzing techniques that find real vulnerabilities in modern web applications.
Content Discovery: Finding Hidden Attack Surface
Modern web applications expose far more than their navigation menus suggest. Admin panels, API endpoints, backup files, old scripts, and development artifacts often exist at discoverable paths that no page links to directly. Directory and file fuzzing maps this hidden surface.
ffuf: The Default Choice for Content Discovery
ffuf (Fuzz Faster U Fool) is the standard tool for web content discovery — fast, flexible, and well-integrated with wordlist sources. Basic directory enumeration:
# Basic directory fuzzing
ffuf -w /usr/share/wordlists/dirb/common.txt \
-u https://target.example.com/FUZZ \
-mc 200,301,302,401,403
# With a better wordlist (SecLists)
ffuf -w /opt/SecLists/Discovery/Web-Content/raft-large-words.txt \
-u https://target.example.com/FUZZ \
-mc 200,301,302,401,403 \
-o output.json -of json
# Recursive fuzzing (follow directories)
ffuf -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories.txt \
-u https://target.example.com/FUZZ \
-recursion -recursion-depth 3 \
-mc 200,301,302,401,403
# File extension fuzzing
ffuf -w /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt \
-u https://target.example.com/FUZZ.php \
-mc 200,301,302,401,403
# Multiple extensions in one pass
ffuf -w /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt \
-u https://target.example.com/FUZZ \
-e .php,.asp,.aspx,.jsp,.html,.txt,.bak,.sql,.conf,.env \
-mc 200,301,302,401,403
Response Filtering
Raw ffuf output contains significant noise. Effective filtering separates findings from background:
# Filter by response size (exclude the most common size, which is likely the 404 page)
ffuf -w wordlist.txt -u https://target.example.com/FUZZ \
-fs 1234 # filter size
# Filter by word count
ffuf -w wordlist.txt -u https://target.example.com/FUZZ \
-fw 14 # filter word count of 404 response
# Filter by status code and minimum size
ffuf -w wordlist.txt -u https://target.example.com/FUZZ \
-mc 200 -ms 100 # match 200 status, minimum 100 bytes
# Multiple match conditions
ffuf -w wordlist.txt -u https://target.example.com/FUZZ \
-mc 200,301,302 -ml 5 # filter if response has fewer than 5 lines
feroxbuster: Recursive Discovery at Scale
feroxbuster is optimized for recursive directory enumeration — automatically descending into discovered directories without manual configuration:
# Automatic recursive enumeration
feroxbuster -u https://target.example.com \
-w /opt/SecLists/Discovery/Web-Content/raft-large-directories.txt \
--depth 4 \
--status-codes 200,301,302,401,403
# With extension searching
feroxbuster -u https://target.example.com \
-w /opt/SecLists/Discovery/Web-Content/raft-large-words.txt \
--extensions php,asp,aspx,txt,bak,env,conf \
--depth 3
# Quiet output, filter common noise sizes
feroxbuster -u https://target.example.com \
-w wordlist.txt \
--filter-size 5765 \
--quiet
Wordlist Strategy
The wordlist determines what you find. Generic wordlists miss technology-specific paths; overly large wordlists waste time on irrelevant patterns. Match the wordlist to the target:
| Target Technology | Recommended Wordlists |
|---|---|
| PHP application | raft-large-words.txt + PHP-specific from SecLists |
| WordPress | CMS/WordPress/wp-directories.fuzz.txt |
| ASP.NET / IIS | raft-large-words.txt with .aspx,.asmx,.svc extensions |
| Java / Spring | raft-large-words.txt + Spring-Boot.fuzz.txt |
| Node.js / Express | raft-large-words.txt + .json,.js extensions |
| API endpoints | api/objects.txt, api/actions.txt from SecLists |
| Backup and config files | Backups/backup-words.txt, Miscellaneous/ |
SecLists (github.com/danielmiessler/SecLists) is the standard repository for security testing wordlists. Install it on Kali with apt install seclists or clone the repository to /opt/SecLists.
Virtual Host Fuzzing
Web servers can host multiple applications on the same IP address, distinguished by the Host header. Fuzzing the Host header discovers virtual hosts that don't appear in DNS:
# VHost discovery — enumerate host headers on a known IP
ffuf -w /opt/SecLists/Discovery/DNS/namelist.txt \
-H "Host: FUZZ.example.com" \
-u https://10.0.0.1 \
-mc 200,301,302 \
-fs 0 # filter empty responses
# When target is behind CDN, use direct IP with SNI override
ffuf -w subdomains.txt \
-H "Host: FUZZ" \
-u https://192.0.2.1 \
-mc 200,301,302 \
-fs 4096 # filter the default response size
Parameter Fuzzing
Known endpoints become more interesting when you find undocumented parameters. Hidden GET parameters can expose debug modes, alternative code paths, and unprotected functionality:
# GET parameter discovery
ffuf -w /opt/SecLists/Discovery/Web-Content/burp-parameter-names.txt \
-u "https://target.example.com/page?FUZZ=test" \
-mc 200 \
-fs 1234 # baseline response size without parameter
# POST parameter fuzzing
ffuf -w /opt/SecLists/Discovery/Web-Content/burp-parameter-names.txt \
-u https://target.example.com/api/endpoint \
-X POST \
-d "FUZZ=test" \
-H "Content-Type: application/x-www-form-urlencoded" \
-mc 200
# JSON parameter fuzzing
ffuf -w /opt/SecLists/Discovery/Web-Content/burp-parameter-names.txt \
-u https://target.example.com/api/endpoint \
-X POST \
-d '{"FUZZ":"test"}' \
-H "Content-Type: application/json" \
-mc 200
Hidden parameters worth hunting:
debug=true,test=1,dev=1— debug modes that expose verbose error output or bypass validationadmin=true,role=admin,is_admin=1— privilege escalation through mass assignmentcallback=,redirect=,url=— open redirect or SSRF entry pointsformat=json,output=xml— alternate response format endpoints with different security controlslang=,locale=,template=— path traversal or template injection vectors
Input Fuzzing for Injection Vulnerabilities
Once parameters are mapped, fuzz their values to detect injection vulnerabilities. The approach differs by vulnerability class:
SQL Injection Fuzzing
# SQL injection payloads in SecLists
ffuf -w /opt/SecLists/Fuzzing/SQLi/Generic-SQLi.txt \
-u "https://target.example.com/items?id=FUZZ" \
-mc 200,500 \
-of json -o sqli_results.json
# Time-based blind SQL injection detection
# Look for responses that take significantly longer than baseline
ffuf -w /opt/SecLists/Fuzzing/SQLi/Generic-BlindSQLi.fuzz.txt \
-u "https://target.example.com/items?id=FUZZ" \
-timeout 10 \
-t 1 # single thread to measure timing accurately
XSS Fuzzing
# Reflected XSS detection
ffuf -w /opt/SecLists/Fuzzing/XSS/XSS-Jhaddix.txt \
-u "https://target.example.com/search?q=FUZZ" \
-mc 200
# Check if payload is reflected in response body
ffuf -w xss_payloads.txt \
-u "https://target.example.com/search?q=FUZZ" \
-mr "FUZZ" # match if payload appears in response
Path Traversal Fuzzing
# Path traversal payloads
ffuf -w /opt/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt \
-u "https://target.example.com/file?path=FUZZ" \
-mc 200 \
-ms 100 # filter tiny responses
# Detect known Linux system files in response
ffuf -w /opt/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt \
-u "https://target.example.com/template?name=FUZZ" \
-mr "root:x:0:0" # match if /etc/passwd appears
SSTI Fuzzing
# Server-side template injection detection
ffuf -w /opt/SecLists/Fuzzing/template-injection-1.txt \
-u "https://target.example.com/page?name=FUZZ" \
-mc 200 \
-mr "49" # 7*7 template evaluation result
# Common SSTI probes: {{7*7}}, ${7*7}, #{7*7}, <%= 7*7 %>
# If response contains "49", template injection confirmed
API Endpoint Fuzzing
REST APIs present a distinct fuzzing surface. Common API-specific fuzzing targets:
API Versioning Discovery
# Find valid API versions
ffuf -w /opt/SecLists/Discovery/Web-Content/api/api-versioning.fuzz.txt \
-u https://api.example.com/FUZZ/users \
-mc 200,201,400,401,403
# Common versions: v1, v2, v3, v1.0, v2.1, api/v1, api/v2
# Old API versions often lack security controls added to current versions
API Endpoint Discovery
# REST API endpoint discovery
ffuf -w /opt/SecLists/Discovery/Web-Content/api/actions.txt \
-u https://api.example.com/api/FUZZ \
-mc 200,201,400,401,403
# Object type discovery
ffuf -w /opt/SecLists/Discovery/Web-Content/api/objects.txt \
-u https://api.example.com/api/v1/FUZZ \
-mc 200,201,400,401,403
# ID enumeration on discovered endpoints
ffuf -w /opt/SecLists/Fuzzing/Integers/Integers-1000.txt \
-u https://api.example.com/api/v1/users/FUZZ \
-mc 200,201
HTTP Method Fuzzing
Endpoints that only respond to GET may also respond to PUT, DELETE, or PATCH — exposing state-changing operations without authentication:
# HTTP method fuzzing on discovered endpoints
for method in GET POST PUT PATCH DELETE OPTIONS HEAD; do
response=$(curl -s -o /dev/null -w "%{http_code}" \
-X $method https://api.example.com/api/v1/users/1)
echo "$method: $response"
done
# Or with ffuf
ffuf -w methods.txt \
-u https://api.example.com/api/v1/users/1 \
-X FUZZ \
-mc 200,201,204,400,401,403
Burp Suite Intruder for Precision Fuzzing
Burp Suite Intruder is the best tool when you need precise control over fuzzing with session tokens, complex request bodies, and multi-parameter correlation:
Cluster Bomb Attack
Tests all combinations of multiple parameter positions — useful for credential spraying or multi-parameter injection testing where both parameters must be set correctly:
POST /api/login HTTP/1.1
Host: target.example.com
{
"username": §admin§,
"password": §password123§
}
# Cluster Bomb iterates: username[0]+password[0], username[0]+password[1], etc.
# Set 1: usernames wordlist
# Set 2: passwords wordlist
Pitchfork Attack
Iterates positions in parallel — useful for IDOR testing where you want to test user 1 with token 1, user 2 with token 2:
GET /api/users/§1§/profile HTTP/1.1
Authorization: Bearer §token_for_user_1§
# Pitchfork: position 1 and position 2 advance together
# List 1: user IDs (1, 2, 3, ...)
# List 2: corresponding valid tokens
# Tests: are user 2's data protected when accessed with user 1's token?
Rate Limiting and WAF Evasion During Fuzzing
Aggressive fuzzing triggers rate limits and WAF blocking. Techniques for maintaining access during testing:
# Reduce threads and add delays
ffuf -w wordlist.txt \
-u https://target.example.com/FUZZ \
-t 5 \ # 5 threads instead of default 40
-p 0.5 # 0.5 second delay between requests
# Randomize user agent
ffuf -w wordlist.txt \
-u https://target.example.com/FUZZ \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
# Rotate through multiple headers to avoid fingerprinting
# Use Burp's upstream proxy to route through Tor or rotating proxies
ffuf -w wordlist.txt \
-u https://target.example.com/FUZZ \
-x http://127.0.0.1:8080 # route through Burp proxy
Note: During authorized penetration tests, coordinate WAF and rate limit exceptions with the client rather than attempting evasion. Evasion techniques are relevant for red team engagements simulating real attackers; standard web app tests benefit more from removing the friction so testing can be comprehensive.
Fuzzing Results Analysis
Raw fuzzing output contains thousands of requests. Systematic triage extracts the findings:
Response Code Triage
- 200 OK — endpoint exists and is accessible; investigate response content
- 301/302 Redirect — follow redirect to understand the actual resource
- 401 Unauthorized — endpoint exists but requires authentication; note for auth testing
- 403 Forbidden — endpoint exists; test for authentication bypass, IP-based access controls, or method override
- 405 Method Not Allowed — endpoint exists on this path but not with this method; switch methods
- 500 Internal Server Error — error triggered by the input; investigate for injection or error disclosure
Response Size Analysis
Anomalous response sizes often indicate findings:
- Response significantly larger than baseline for the same URL path — may indicate content injection or verbose error
- Response size 0 for a 200 — may indicate empty response where content was expected; application logic flaw
- Consistent response size for all inputs — parameter reflected without sanitization; potential XSS or injection
Integrating Fuzzing into Security Testing Workflow
Fuzzing is most effective as a structured phase within the broader testing methodology:
- Recon first — passive reconnaissance (CT logs, DNS, Wayback Machine) reveals historical paths to include in wordlists and seed URL lists for crawlers
- Crawl the application — automated crawling with Burp Suite or Katana maps linked content before fuzzing fills in the gaps
- Technology-targeted wordlists — fingerprint the stack before choosing wordlists; a PHP wordlist on a Node.js application wastes significant time
- Content discovery fuzzing — run directory and file fuzzing against all discovered hostnames and virtual hosts
- Parameter fuzzing — on all discovered endpoints, fuzz for hidden parameters
- Input fuzzing — apply injection payload wordlists to each parameter, prioritizing user-controlled inputs that appear in responses
- Manual verification — every potential finding from fuzzing requires manual verification; automated fuzzing produces significant false positives that require human triage
Wordlist Maintenance and Custom Lists
Generic wordlists are a starting point. The most effective security teams maintain application-specific wordlists built from:
- JavaScript source analysis — extract internal paths, API endpoints, and parameter names from the application's own code
- Previous engagement findings — paths and parameters that produced findings in similar applications
- Framework-specific patterns — Spring Boot Actuator endpoints, Rails admin routes, Django admin paths
- Historical content — Wayback Machine URLs joined with current discovery wordlists
# Extract URLs from JS bundles to seed wordlists
curl -s https://target.example.com/static/app.bundle.js | \
grep -oP '"/api/[^"]+|/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+' | \
sort -u > custom_paths.txt
# Extract parameter names from JavaScript
curl -s https://target.example.com/static/app.bundle.js | \
grep -oP '"[a-zA-Z_][a-zA-Z0-9_-]+":\s*"' | \
sed 's/"//g; s/:.*//g' | \
sort -u > custom_params.txt
Ironimo runs fuzzing and content discovery automatically as part of every scan — using Kali Linux tools including ffuf and feroxbuster with curated wordlists tuned for the target's technology stack. Rather than spending hours configuring and running fuzzing manually, get the full discovery pass as a service on a schedule you define.
Join the waitlist to run your first automated scan.
Start free scan