Web Content Discovery
Content discovery finds endpoints the app doesn't link to: admin panels, backups, APIs, debug paths, and unlinked apps. Run it after tech fingerprinting so you know which extensions and wordlists match the stack. Discovery output feeds into parameter crawling and exposed git directory checks.
ffuf Baseline
ffuf is the default choice. Fast, flexible filtering, and handles custom 404s cleanly:
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file path used for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Variable placeholders for the target host IP and port. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these specific HTTP status codes. |
301/302 to a new path is real content. 401/403 is still interesting — it's a valid endpoint behind auth. If everything returns a hit, you're seeing a custom 404 and need size filtering.
Handle Custom 404s with Size Filtering
Measure the error response size, then exclude it:
4242
Explain command
| -s | Silent mode; suppresses progress meter and error messages. |
| -k | Allow insecure TLS connections, skipping certificate verification. |
| http://$TARGET_IP:$PORT/thisshouldnotexist | Target URL with variable host/port to a non-existent path. |
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file path used for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword as the injection point. |
| $TARGET_IP:$PORT | Variable placeholders for the target host IP and port. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these HTTP status codes. |
| -fs 4242 | Filter out responses with a body size of 4242 bytes. |
Replace 4242 with the actual size. For apps returning varying sizes on 404, filter by word count with -fw instead.
Stack-Matched Extensions
Match extensions to what fingerprinting revealed. Wrong extensions waste significant time on large wordlists:
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file used for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Variable placeholders for the target host IP and port. |
| -e .php,.php5,.phtml,.html,.txt,.bak,.old,.zip | File extensions to append to each wordlist entry. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these HTTP status codes. |
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file to use for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword as the injection point. |
| $TARGET_IP:$PORT | Variable placeholders for target host IP and port. |
| -e .asp,.aspx,.ashx,.asmx,.config,.txt,.bak | Append these extensions to each wordlist entry during fuzzing. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these HTTP status codes. |
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file to use for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ as the injection point placeholder. |
| $TARGET_IP:$PORT | Variable placeholders for the target host IP and port. |
| -e .jsp,.jspx,.do,.action,.txt,.xml | Append these extensions to each wordlist entry during fuzzing. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these specific HTTP status codes. |
Recursive Discovery
ffuf handles recursion but feroxbuster is faster and more reliable for deep trees:
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file to use for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Placeholder for target host IP address and port number. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these HTTP status codes. |
| -recursion | Enable recursive fuzzing on discovered directories. |
| -recursion-depth 2 | Limit recursive fuzzing to a maximum depth of 2 levels. |
Explain command
| -u http://$TARGET_IP:$PORT/ | Target URL to perform directory/file brute-forcing against. |
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file used for brute-forcing paths and filenames. |
| -x php,html,txt,js,json | File extensions to append to each wordlist entry during fuzzing. |
| -t 30 | Number of concurrent threads to use for scanning. |
| -k | Disable TLS certificate validation for HTTPS targets. |
Explain command
| -u | Target URL to begin directory/file brute-forcing against. |
| http://$TARGET_IP:$PORT/ | Base URL with variable host and port placeholders. |
| -w | Wordlist file path to use for brute-forcing. |
| /usr/share/seclists/Discovery/Web-Content/common.txt | Common web content wordlist from SecLists collection. |
| -x | File extensions to append to each wordlist entry during fuzzing. |
| php,html,txt,js,json | Extensions to test: PHP, HTML, plain text, JavaScript, and JSON. |
| -C | HTTP status codes to filter out (exclude) from results. |
| 404,302 | Suppresses responses with Not Found and Redirect status codes. |
| -o | Output file path to save scan results. |
| ferox_results.txt | File where discovered results will be written. |
Authenticated Discovery
Run a second pass authenticated to find endpoints only visible after login:
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file to use for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Placeholder for the target host IP and port number. |
| -H "Cookie: session=REPLACE_ME" | Adds a custom Cookie header with a session token to each request. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these specific HTTP status codes. |
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Specifies the wordlist file to use for fuzzing. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword as the injection point. |
| $TARGET_IP:$PORT | Placeholder for the target host IP and port number. |
| -u $USER:$PASSWORD | Specifies credentials (likely misused flag; intended for -u in some tools). |
| $USER:$PASSWORD | Placeholder for authentication username and password credentials. |
| -mc 200,204,301,302,307,401,403 | Match HTTP response codes to include in results. |
Larger Wordlists for Deeper Coverage
When common.txt misses things, upgrade the wordlist. raft and directory-list are heavier but surface more results:
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt | Wordlist file used for fuzzing directory names. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Variable placeholders for the target host IP and port. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these specific HTTP status codes. |
Explain command
| -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt | Wordlist file to use for fuzzing input. |
| -u http://$TARGET_IP:$PORT/FUZZ | Target URL with FUZZ keyword marking the injection point. |
| $TARGET_IP:$PORT | Placeholder for the target host IP and port number. |
| -mc 200,204,301,302,307,401,403 | Match only responses with these HTTP status codes. |
| -t 100 | Number of concurrent threads to use for requests. |
Gobuster and dirsearch as Alternatives
Warning
dirb and wfuzz still work but are slower and noisier than ffuf and feroxbuster. Use them as fallback only.
Explain command
| dir | Use directory/file brute-forcing mode. |
| -u | Target URL to enumerate. |
| http://$TARGET_IP:$PORT/ | Base URL with variable host and port placeholders. |
| -w | Wordlist file path to use for brute-forcing. |
| /usr/share/seclists/Discovery/Web-Content/common.txt | Common web content wordlist from SecLists. |
| -x | File extensions to append to each wordlist entry. |
| php,html,txt,js,json | Extensions to try: php, html, txt, js, and json. |
| --random-agent | Use a random User-Agent string per request. |
| -t | Number of concurrent threads to use. |
| 50 | Thread count value — 50 parallel requests. |
| -o | Write output results to a specified file. |
| gobuster.txt | Output file where results will be saved. |
Explain command
| -u http://$TARGET_IP:$PORT/ | Target URL to perform directory brute-forcing against. |
| -w /usr/share/seclists/Discovery/Web-Content/common.txt | Wordlist file used for directory and file enumeration. |
| -e php,html,txt,js,json | File extensions to append to each wordlist entry during scan. |
| -i 200,204,301,302,307,401,403 | Only include responses matching these HTTP status codes. |
| -t 50 | Number of concurrent threads to use during the scan. |
| -o dirsearch.txt | Write scan output/results to the specified file. |
References
-
Matchers, filters, recursion, and output formats
-
feroxbustergithub.com/epi052/feroxbuster (opens in new tab)
Recursive forced browsing and filtering options
-
dir mode usage and flags
-
Web content wordlists including raft, common, and directory-list
Was this helpful?
Your feedback helps improve this page.