Web Cache Poisoning: A Bug Bounty Hunter's Guide
ToxSec | Understand web cache issues for bug bounty programs.
0x00 Web Cache Poisoning for Bug Hunting
Web caching is a fundamental technique used to improve website performance and reduce server load. Caches store copies of frequently accessed resources (HTML pages, images, CSS files, JavaScript files, etc.) and serve them to subsequent users, bypassing the need to repeatedly fetch them from the origin server. This results in faster page load times and reduced bandwidth consumption. However, misconfigurations or vulnerabilities in caching mechanisms can lead to serious security issues, most notably web cache poisoning.
0x01 Understanding Web Caching
Web cache poisoning occurs when an attacker manipulates a web server into caching a malicious response. This poisoned response is then served to other users who request the same resource, effectively spreading the malicious content to a wider audience.
The core principle is to influence the cache key. The cache key is what the caching server uses to identify a resource. If you can manipulate a request in a way that it gets cached under the same key as a legitimate request, but contains malicious content, you've successfully poisoned the cache.
Most modern stacks sit behind some caching layer:
CDNs like Cloudflare, Akamai, or Fastly.
Reverse proxies such as Varnish, Squid, or nginx with
proxy_cache
.Load balancers with caching modules bolted on.
The point is efficiency: instead of regenerating content, the server caches a copy and serves it to anyone who asks.
The risk comes from the cache key; the set of inputs the system uses to decide whether two requests are the same. If an attacker can manipulate that key, or trick the cache into storing the wrong response, every downstream user gets poisoned content.
That’s the heart of cache attacks: turn the server’s own “speed boost” into a global exploit.
0x02 Cache Poisoning Attacks
Cache poisoning is about planting something malicious in a response, then letting the cache spread it to everyone else.
The classic case is Host header abuse. If the cache keys on the Host
header but doesn’t sanitize it, you can poison the stored response:
curl -H "Host: attacker.tld" https://victim.com/ -v
If that response gets cached, the next visitor may receive a version of the page that points to your host.
Burp’s Param Miner extension is perfect here. It hunts for headers or parameters that affect the cache key but aren’t included in sanitization. Common suspects:
X-Forwarded-Host
X-Forwarded-Scheme
X-Original-URL
When those inputs influence caching but not content, your crafted request becomes the response for every user that follows.
0x03 Cache Deception Attacks
Cache deception flips the script. Instead of poisoning the response, you trick the cache into storing private data that should never be cached.
The classic trick: append a static file extension to a sensitive endpoint.
# Force account data into cache as if it's static
curl https://target.com/account.php/style.css -b session=VALID
The application still serves your private account data. But the cache sees /style.css
and thinks it’s a public, cacheable resource. Now, /account.php/style.css
might serve your sensitive data to anyone who requests it — no session needed.
That’s the danger: a cache deceived into treating authenticated pages like static assets can turn one valid request into a public leak.
How Cache Poisoning and Deception Work
The attack process generally involves these steps:
Identify Cacheable Resources: Determine which resources are being cached by the web server. Look for
Cache-Control
headers in the response, indicating caching behavior. Common cacheable resources include static assets (images, CSS, JavaScript) and sometimes even dynamic HTML pages.
Burp → Extender → Param Miner → Right-click on a request → Guess headers
Identify Unkeyed Inputs: Find request parameters (headers, cookies, query parameters, etc.) that are not used to generate the cache key. These are the parameters you can manipulate without changing the cache key itself.
Craft a Malicious Request: Construct a request that includes a malicious payload in an unkeyed input. This payload could be anything from XSS code to a redirect to a phishing site.
GET /news HTTP/1.1
Host: target.tld
User-Agent: <script>/*toxsec*/alert(1)</script>
Accept: text/html
Connection: close
Expected: You’re not trying to force script exec on yourself; you’re checking if any part of the response reflects User-Agent. If yes, and later you see a cache HIT with that reflection for clean requests, you’ve got cross-user impact.
Trigger Caching: Send the malicious request to the server. If the server caches the response, the cache is now poisoned.
Verify Poisoning: Request the same resource without the malicious payload. If you receive the poisoned response, the cache poisoning attack was successful.
# Poison step (with header)
curl -si -H 'User-Agent: <script>/*toxsec*/alert(1)</script>' https://target.tld/news | grep -Ei 'age:|cache|cf-cache|x-cache|via|etag|last-modified'
# Verify step (without header)
curl -si https://target.tld/news | grep -Ei 'age:|cache|cf-cache|x-cache|via|etag|last-modified'
Amplify the Impact: Wait for other users to request the same resource and receive the poisoned response.
0x04 Practical Exploits in the Wild
Caching bugs show up in different flavors, but the patterns repeat.
Cache Key Confusion
Two URLs render the same content, but only one respects authentication. Cache one, serve both.
# Normal request (auth required)
curl -b auth=valid https://victim.com/profile
# Poisoned request with extra param
curl -b auth=valid https://victim.com/profile?x=1
If the cache doesn’t treat ?x=1
as unique, a cached authenticated response can be replayed for unauthenticated users.
Header-Based Poisoning
Manipulating headers the cache mistakenly trusts.
curl -H "X-Forwarded-Host: attacker.tld" https://victim.com/ -v
If cached, every user downstream sees attacker-controlled host data.
Method Override Poisoning
When caches and apps disagree on HTTP verbs.
curl -X POST -H "X-HTTP-Method-Override: GET" https://victim.com/
The cache sees a GET, but the backend processes it as POST. That split can lead to poisoned or leaked responses.
0x05 Cache Poisoning Tools
Cache testing doesn’t require exotic exploits. It’s about quick iteration and careful observation. Burp Suite with Param Miner is the go-to for brute-forcing unkeyed headers and parameters, making it easier to spot inputs that influence the cache but aren’t sanitized. ffuf is useful for fast parameter fuzzing to uncover injection points, and can be paired with wordlists such as:
ffuf -w /usr/share/seclists/Discovery/Web-Parameter/test-params.txt:FUZZ \
-u https://target.tld/page?FUZZ=1 -fc 404
For lower-level testing, curl acts as the microscope—perfect for raw probes, experimenting with custom headers, and reproducing edge cases without overhead. The goal isn’t to flood endpoints with payloads but to answer a simple question: does this input affect caching, and if so, can it be controlled to serve malicious responses to other users?
0x06 Bug Bounty Context: Valid vs Noise
Caching bugs live or die on scale. Triagers don’t care that you got a weird header echoed back — they care if you can show one poisoned request turns into a multi-user compromise.
Valid impact cases:
Cache poisoning → your injected payload or header gets replayed to every visitor.
Cache deception → private account data cached as a public static resource.
Cache key confusion → authenticated responses cached and served to unauthenticated users.
Noise triage will kill:
Cache hit/miss behavior with no security angle.
“I can get a 404 with a weird URL.”
Reporting benign debug headers.
The rule: if the bug doesn’t let you poison, leak, or cross boundaries, it won’t pay.
0x07 Additional Tips for Bug Bounty Hunters
Before attempting to exploit cache poisoning vulnerabilities, take the time to understand the caching infrastructure used by the target website. This includes identifying the caching server (e.g., Varnish, Akamai, Cloudflare) and its configuration.
Test Thoroughly: Carefully test your exploits to ensure that they are reliable and reproducible. Provide clear and concise steps to reproduce the vulnerability in your bug bounty report.
Focus on Impact: When reporting a cache poisoning vulnerability, emphasize the potential impact on users and the business. Explain how the vulnerability could be exploited to steal credentials, deface the website, or launch other attacks.
Stay Up-to-Date: The landscape of web security is constantly evolving. Stay up-to-date on the latest cache poisoning techniques and vulnerabilities by reading security blogs, attending conferences, and participating in online communities.
0x08 Debrief - Web Cache Poisoning
Web caches are supposed to make apps faster and cheaper. But when they trust headers, parameters, or file extensions blindly, they create vulnerabilities.
For hunters, that’s the upside: caches turn single-request bugs into platform-wide exploits. Poison a response once, and every downstream user is compromised until the cache resets.
That amplification is what makes cache bugs so valuable in bug bounty. Few other issues let you weaponize one request into thousands of victims.