Helloo There, As a bug bounty hunter with the practical experience in penetration testing and bug bounties, I've spent countless hours probing web applications for vulnerabilities. One tool that's on my toolkit is ffuf — a lightning-fast web fuzzer written in Go. It's not just quick; it's flexible enough to uncover those elusive hidden endpoints that developers often overlook. In this article, I'll walk you through how I used ffuf during a bug bounty program for a government website.

Governments like the Department of Defense (DoD) and Health and Human Services (HHS) run public bug bounty programs through platforms such as HackerOne and Bugcrowd, where researchers like me get explicit permission to test their systems. In this case, I was participating in the Vulnerability Disclosure Program (VDP), which encourages reporting issues in non-critical assets. The goal? To map out hidden endpoints that could expose sensitive data or functionality if left unchecked.

Let's Gooo.

What Are Hidden Endpoints and Why Do They Matter?

Before we get to the fuzzing, a quick information: Hidden endpoints are URLs or API paths on a web server that aren't linked from the main site or documented in public APIs. Think admin panels (/admin), backup files (/backup.zip), or internal APIs (/api/internal/users). They're "hidden" because they're not meant for public access, but they're often discoverable through brute-force guessing or fuzzing.

In government websites, these can be particularly risky. Such sites handle everything from citizen data to national security info. A leaked endpoint might reveal personally identifiable information (PII) or allow unauthorized access. For example, in 2023, a misconfigured endpoint on a federal health portal exposed user records — incidents like that underscore why mapping them is crucial for security teams.

Fuzzing tools like ffuf automate the process by trying thousands of potential paths from a wordlist, checking server responses to identify what's real. Unlike slower tools like DirBuster, ffuf leverages Go's concurrency for speed, making it ideal for large-scale scans without overwhelming the target (or your patience).

Setting the Scene: Permissions and Preparation

Ethics first: Never fuzz a site without permission. In my case, the DoD's VDP provided clear rules of engagement — no exploiting vulnerabilities, just reporting them. I scoped my testing to a public-facing subdomain of a government portal (let's call it portal.gov for anonymity).

Preparation was straightforward:

  • Environment: I used Kali Linux, but any Linux distro works. ffuf is installable via apt install ffuf or by compiling from source with Go.
  • Wordlists: These are the heart of fuzzing. I started with SecLists (github.com/danielmiessler/SecLists), specifically raft-medium-directories.txt (about 20,000 entries) for directories and common.txt from dirb for basics. For APIs, I used a custom list with terms like "api", "v1", "internal".
  • Other Tools: Burp Suite for proxying requests if needed, but ffuf standalone sufficed here.
  • Rate Limiting Mindset: Government sites often have web application firewalls (WAFs) or rate limits. I set a delay (-p 0.5) to mimic human traffic and avoid bans.

With setup done, it was time to fire up ffuf.

The Fuzzing Process: Step by Step

ffuf's syntax is simple: Define a target URL with the FUZZ keyword where you want to insert wordlist entries, provide a wordlist (-w), and filter noise.

Step 1: Basic Directory Fuzzing

I began with a broad scan to map top-level directories. The command:

text

ffuf -u https://portal.gov/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-directories.txt -fc 404,403 -t 50 -p 0.2-0.5
  • -u: The URL with FUZZ as the placeholder.
  • -w: Path to the wordlist.
  • -fc: Filter out 404 (Not Found) and 403 (Forbidden) responses to focus on hits like 200 (OK) or 301 (Redirect).
  • -t 50: 50 threads for speed without overload.
  • -p 0.2–0.5: Random delay between 0.2–0.5 seconds per request.

This ran for about 10 minutes, processing 20,000 entries. ffuf outputs progress in real-time, showing response codes, sizes, and words/lines for easy spotting of anomalies.

Hits included:

  • /about (200 OK, expected public page).
  • /docs (301 Redirect to documentation — useful but not hidden).
  • /api (200 OK, an undocumented endpoint).

That /api was gold; it wasn't linked anywhere on the site.

Step 2: Recursive Fuzzing for Deeper Paths

One hit led to more. ffuf supports recursion (-recursion) to automatically fuzz subdirectories. I adjusted:

ffuf -u https://portal.gov/api/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-small-directories.txt -recursion -recursion-depth 2 -fc 404,403,429 -mc all -fs 0
  • -recursion: Enables scanning subpaths (e.g., if /api/v1 is found, it fuzzes /api/v1/FUZZ).
  • -recursion-depth 2: Limits to two levels deep to avoid endless loops.
  • -mc all: Match all status codes for broader insights.
  • -fs 0: Filter out zero-byte responses (empty pages).

This uncovered /api/v1/internal (200 OK, ~5KB response) and /api/v1/users (401 Unauthorized — suggesting authentication needed, but its existence was reportable).

Step 3: Parameter and VHost Fuzzing

Endpoints often hide in query parameters or virtual hosts. For parameters:

ffuf -u https://portal.gov/api?param=FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common-api-endpoints-mazen160.txt -X GET -fc 404

This fuzzed values like "id", "key", "secret". One hit: ?debug=true returned verbose error messages — a classic info leak.

For virtual hosts (if the site used them):

ffuf -u https://portal.gov -H "Host: FUZZ.portal.gov" -w /path/to/subdomains.txt -fs <default_size>

Here, -fs filtered by response size to ignore the default page. No major finds, but it's a standard check.

Analyzing Results

ffuf logs to stdout or a file (-o output.json). I piped to grep for quick review:

ffuf ... | grep -E "200|301|302"

Valid hits got manual verification in a browser or curl. For example, /api/internal showed JSON metadata — nothing sensitive, but undocumented.

What I Discovered (and Reported)

In total, I mapped 15 hidden endpoints. Highlights:

  • /admin-old: A deprecated admin panel (redirected to login, but exposed version info for potential exploits).
  • /api/v2/backup: Returned a 200 with a file list — major risk if accessible.
  • /internal/logs: 403, but the path hinted at log storage.

These weren't vulnerabilities per se, but exposed attack surface. I reported via the VDP portal with screenshots, commands, and impact analysis (e.g., "This endpoint could be brute-forced for data exfil"). The agency acknowledged within days and patched by hiding or securing them.

Challenges I Faced and How I Overcame Them

No scan is smooth. The site had a WAF triggering 429 (Too Many Requests) after 1,000 requests. Solution: Lower threads (-t 20) and increase delay (-p 1).

False positives were another: Many 200s were just custom error pages. I added -fw <word_count> to filter by response words, excluding generic "Not Found" pages.

Large wordlists can take hours; I used -maxtime 3600 to cap at 1 hour, resuming later.

Lessons Learned: Best Practices for Ethical Fuzzing

From this and dozens of similar hunts:

  • Start Small: Use short wordlists first to test filters.
  • Customize Filters: Match on size (-ms), lines (-ml), or regex (-mr) for precision.
  • Stay Legal: Always check program scopes. Platforms like Intigriti or YesWeHack list government bounties.
  • Combine Tools: ffuf pairs well with nuclei for vuln scanning post-discovery.
  • Document Everything: Screenshots and logs build credible reports.

Fuzzing isn't magic — it's systematic guessing backed by good lists and configs.

CONCLUSION

Using ffuf on that government site reinforced how even "secure" apps hide gems under the surface. It took me about 4 hours total, yielding actionable intel that strengthened the portal. If you're dipping into pentesting, grab ffuf, join a bug bounty (start with HackTheBox or TryHackMe for practice), and fuzz ethically.

Remember, the goal is defense, not disruption. Have you tried ffuf on a bounty? Share in the comments !