Skip to content

CONCEPT Cited by 1 source

Path enumeration attack

Definition

A path enumeration attack is the reconnaissance technique of systematically requesting URLs against a target to discover hidden, private, or unlinked resources — by observing which responses are 200 OK / redirects (resource exists) versus 404 Not Found (resource does not exist).

The attack class includes:

  • Directory enumeration: guessing /admin, /backup, /.git/config, /wp-admin/, /phpmyadmin/, etc.
  • File enumeration: guessing filename patterns like backup.sql, config.old, dump.tar.gz, .env.bak.
  • ID enumeration: walking sequential IDs like /users/1, /users/2, /users/3 to discover private user profiles.
  • Dictionary attack: running a wordlist (e.g. SecLists, DirBuster, gobuster wordlists) against the target.

The attack exploits the fact that a server's response to "does this path exist?" is often observable — different response codes, response times, or content lengths reveal membership in the set of real paths without needing to authenticate or exploit any vulnerability.

Why membership checks matter

Every public server must answer "does this path exist?" on every request to return a 404 or serve content. An attacker with a wordlist of likely paths can drain this signal.

The defensive properties the server wants:

  • Low information leakage: 404 for non-existent paths should look identical (response code, body, timing) to 404 for forbidden paths.
  • No timing side-channel: 200 and 404 paths should take similar wall-clock time. Otherwise attackers can distinguish cache-hit real paths from reject-fast fake paths.
  • Rate limits: cap request rate per source to slow enumeration.
  • Bot management: detect enumeration by pattern (many 404s from one source, wordlist-shaped paths) and challenge / block.
  • Canary paths: include known-bait paths that trigger alerts if hit.

Canonical Vercel framing

Vercel's 2026-04-21 routing post names the attack class as a second-order motivator for the routing service's hot-path membership check:

"Before serving a request, the routing service consults this JSON file and checks if the path exists. If it doesn't, we immediately return a 404. This early check ensures we only fetch documents from storage when we're sure they exist. [...] This prevents unnecessary requests to storage and protects against enumeration attacks, where attackers try to discover hidden files by guessing URLs."

(Source: sources/2026-04-21-vercel-how-we-made-global-routing-faster-with-bloom-filters.)

The primary motivator is don't hit storage unnecessarily (performance). The secondary motivator is don't let storage leak membership via response timing or error shape (security). A Bloom-filter membership check on the hot path delivers both: fast negative on non-existent paths + uniform response shape to the attacker.

Structural defences

1. Membership check before storage fetch

The Vercel move. Check a compact in-memory filter before reaching to the authoritative (slower, potentially membership-leaking) store. Uniform response shape regardless of whether the filter was consulted or skipped — same 404 for non-existent paths whether they're filtered or fetched- then-404'd.

2. Authenticated membership

Hidden resources should be behind authentication, not just obscurity. A path's secrecy is "security through obscurity" and an attacker with enough patience always finds it.

3. Non-sequential identifiers

Use NanoIDs, UUIDs, ULIDs for resource IDs instead of sequential integers. Makes ID enumeration statistically impossible even if endpoint is unauthenticated. Complementary to concepts/nanoid-identifier.

4. Rate limiting and bot detection

A human user does not request 10,000 unique paths per minute. Bot-management products (Cloudflare Bot Management, Vercel BotID, Kasada) flag enumeration signatures.

5. robots.txt is not a defence

robots.txt tells compliant crawlers what not to crawl. Attackers use it as a reconnaissance hint — paths listed in robots.txt are the ones worth enumerating.

6. Consistent timing

If /real-path serves from a cache in 10 ms and /fake-path 404s in 2 ms, the attacker can distinguish them by timing alone. Membership-check-then-storage-fetch has the same timing for both cases (filter check dominates) — which is one reason Vercel's Bloom-filter substitution also helps security.

7. 404-as-403 opacity

Some systems return 404 uniformly for both "doesn't exist" and "exists but you can't see it" to prevent inferring membership via authorisation signals. Cost: legitimate users get an unhelpful 404 instead of a useful 403.

  • Directory traversal (../, ..\\) — different class; exploits path-parsing bugs to read files outside the web root. Mitigation is parsing hygiene, not membership checks.
  • Forced browsing — requesting URLs the application doesn't link but hasn't protected (same root cause as enumeration, different name).
  • Subdomain enumeration — DNS-level path enumeration. Same reconnaissance shape; different layer.

Seen in

Last updated · 476 distilled / 1,218 read