ffuf: Fast Web Fuzzing for Directories, Parameters, and Vulnerabilities

ffuf: Fuzzing web applications for vulnerabilities

Of every tool in my recon toolkit, ffuf is the one I reach for most often. It’s fast, it’s flexible, and once you understand its FUZZ keyword pattern, you realize it’s not just a directory brute-forcer — it’s a general-purpose HTTP fuzzing engine that can hit virtually any part of a request: paths, parameters, headers, POST bodies, even the Host header for virtual host discovery.

What Is ffuf?

ffuf stands for “Fuzz Faster U Fool.” It’s written in Go, which is a big part of why it’s so much faster than older Perl/Python-based fuzzers like dirb — Go’s concurrency model lets it fire off hundreds of requests in parallel with low overhead.

At its core, ffuf takes a wordlist and a request template containing the placeholder FUZZ, substitutes each wordlist entry into that placeholder, sends the request, and reports back based on response size, status code, word count, or line count — letting you filter out the noise (like a wildcard “catch-all” 200 response) and zero in on real results.

How It Works Internally

ffuf’s architecture is straightforward but well engineered:

  • Input layer: reads one or more wordlists (or generates values via input commands) and manages placeholder substitution.
  • Job scheduler: a worker pool of goroutines sends requests concurrently, respecting the -t (threads) and -p (delay) settings.
  • Matcher/filter engine: every response is evaluated against matcher (-mc, -ms, -mw, -ml) and filter (-fc, -fs, -fw, -fl) rules before being shown or hidden.
  • Output layer: results can be streamed to console or exported as JSON, CSV, HTML, or markdown for reporting.

This matcher/filter separation is what makes ffuf so much smarter than naive brute-forcers — instead of just listing every response, you tell it “hide anything that returns exactly 4242 bytes” (a typical soft-404 page), and it automatically cleans up the noise.

Installation

Via Go (recommended, always gets the latest release):

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

Via apt on Kali:

sudo apt update
sudo apt install ffuf

Verify:

ffuf -V

Basic Syntax

ffuf -w <wordlist> -u <url_with_FUZZ_keyword>

Directory & File Discovery

ffuf -w /usr/share/wordlists/dirb/common.txt -u http://192.168.56.101/FUZZ

Sample output:

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://192.168.56.101/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
________________________________________________

admin                   [Status: 301, Size: 313, Words: 20, Lines: 10]
config.php              [Status: 200, Size: 0, Words: 1, Lines: 1]
uploads                 [Status: 301, Size: 315, Words: 20, Lines: 10]
robots.txt              [Status: 200, Size: 45, Words: 4, Lines: 3]
:: Progress: [4614/4614] :: Job [1/1] :: 812 req/sec :: Duration: [0:00:06] :: Errors: 0 ::

Filtering Out Noise (Wildcard Responses)

If a server returns a soft-404 (status 200 for everything), filter it out by size:

ffuf -w common.txt -u http://192.168.56.101/FUZZ -fs 4242

Or match only interesting status codes:

ffuf -w common.txt -u http://192.168.56.101/FUZZ -mc 200,301,302,403

Parameter Fuzzing

ffuf -w params.txt -u "http://192.168.56.101/search.php?FUZZ=test" -mc 200 -fs 1234

POST Body Fuzzing

ffuf -w passwords.txt -X POST -d "username=admin&password=FUZZ" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u http://192.168.56.101/login.php -fc 401

Virtual Host Discovery

ffuf -w subdomains.txt -u http://192.168.56.101/ -H "Host: FUZZ.example.lab" -fs 4242

Recursive Scanning

ffuf -w common.txt -u http://192.168.56.101/FUZZ -recursion -recursion-depth 2

Extension Fuzzing

ffuf -w common.txt -u http://192.168.56.101/FUZZ -e .php,.bak,.txt,.zip

Output for Reporting

ffuf -w common.txt -u http://192.168.56.101/FUZZ -o results.json -of json

Real-World Use Case (Authorized Lab Only)

On a lab CTF-style box, I’ve used ffuf to first discover a hidden /backup/ directory that dirb missed because I combined -recursion with an extension list, revealing a .php.bak source file. Reading that backup file exposed hardcoded database credentials, which I then used (within the same authorized scope) to move laterally into the application’s admin panel.

Workflow Integration

  • Amass/subfinder → passive subdomain enumeration, feeding a target list into ffuf’s vhost fuzzing.
  • ffuf → directory/file discovery, parameter fuzzing, vhost discovery.
  • Burp Suite → send interesting ffuf hits into Burp Repeater for manual follow-up.
  • Nuclei → once ffuf surfaces endpoints, run template-based vulnerability checks against them.

Performance Optimization

  • Increase threads with -t (default 40) if the target and your network can handle it — I typically go up to 100-150 on internal lab targets.
  • Use -rate to cap requests/sec when testing against rate-limited or fragile targets.
  • Use -mode clusterbomb or -mode pitchfork when fuzzing multiple FUZZ positions with multiple wordlists simultaneously.

Troubleshooting & Common Mistakes

  • Getting thousands of false positives — you forgot to filter the wildcard/soft-404 response size; always do a baseline request to a random nonexistent path first.
  • Too slow — check -t isn’t left at a low default, and confirm you’re not hitting an unintentional rate limit or WAF throttling.
  • SSL errors on self-signed certs — add -k to skip certificate verification in a lab context.
  • Recursive scans running forever — always set -recursion-depth to bound scope.

Best Practices

  • Always baseline the target’s 404 behavior before fuzzing.
  • Match scope and rate limits to what’s authorized — aggressive fuzzing can degrade production-like lab services.
  • Save results to JSON for later parsing/reporting rather than relying on scrollback.

FAQ

How is ffuf different from dirb or dirbuster? ffuf is significantly faster due to Go’s concurrency, and it’s far more flexible — it can fuzz any part of an HTTP request, not just the URL path, and has a much more powerful matcher/filter system.

Can ffuf fuzz JSON APIs? Yes — put FUZZ inside the -d JSON body and set the appropriate Content-Type header.

Does ffuf support proxies like Burp? Yes, via -x http://127.0.0.1:8080, which is useful for capturing every fuzzed request in Burp’s history.

Summary

ffuf has become close to the default choice for web fuzzing in modern pentesting workflows because of its speed, flexible FUZZ placeholder system, and strong matcher/filter engine that cuts through response noise quickly. Once you get comfortable with its matcher/filter flags, it becomes far more than a directory brute-forcer — it’s a general-purpose fuzzing engine for almost any part of an HTTP request.

References

Kali Linux Tools: https://www.kali.org/tools/ffuf/

Official GitHub repository: https://github.com/ffuf/ffuf

ffuf documentation wiki: https://github.com/ffuf/ffuf/wiki

Total
0
Shares

Leave a Reply

Previous Post
dirbuster: Directory brute-forcing tool

Dirb: Scanning Directories and Files on Web Servers

Next Post
cadaver: WebDAV command-line client

Cadaver: The WebDAV Command-Line Client Every Pentester Should Know

Related Posts