August 26, 2026
Web Cache Poisoning: One Response, Every Victim
Whatβs up everyone! Nitin here π

By Nitin yadav
2 min read
Most bugs affect one victim at a time. Web cache poisoning affects everyone who loads the page. That's what makes it so powerful β you poison a single cached response, and the CDN or reverse proxy then happily serves your payload to every subsequent visitor. The trick hinges on one concept: unkeyed inputs β parts of your request that change the response but aren't part of what the cache uses to identify it. Let's poison the well (responsibly).
The core concept: keyed vs unkeyed
A cache decides "have I seen this request before?" using a cache key β typically the method + host + path + query string. Everything else in your request (most headers) is unkeyed: it can influence the response the server generates, but the cache ignores it when deciding what to store and serve. So if an unkeyed header changes the response and that response gets cached under the normal key, you've stored a malicious response that gets served to users who never sent your header. That's the entire bug.
Step 1: Understand the cache
First confirm the page is cached and learn its behavior:
- Look for cache headers:
X-Cache: hit/miss,Age:,CF-Cache-Status: HIT,X-Served-By. - Send the same request twice β the second should show a
hit/ non-zeroAge. - Note what's in the cache key (change a query param and see if you get a fresh response).
Step 2: Find an unkeyed input that reflects
Now look for headers that (a) aren't in the cache key and (b) get reflected into the response. Classic culprits:
X-Forwarded-Host: evil.com
X-Forwarded-Scheme: nothttps
X-Host: evil.com
X-Forwarded-Server / X-Original-URL / X-Forwarded-PrefixX-Forwarded-Host: evil.com
X-Forwarded-Scheme: nothttps
X-Host: evil.com
X-Forwarded-Server / X-Original-URL / X-Forwarded-PrefixSend one with a canary and check whether it appears in the HTML β especially inside a <script src>, <link href>, a redirect, or an absolute URL:
GET /?cb=nitin123 HTTP/1.1
X-Forwarded-Host: evil.com
β <script src="//evil.com/main.js"></script> in the responseGET /?cb=nitin123 HTTP/1.1
X-Forwarded-Host: evil.com
β <script src="//evil.com/main.js"></script> in the responseUse a cache buster (?cb=random) during discovery so you only poison your own unique key and never real users while testing.
Step 3: Get the poisoned response cached
Once you've found a reflected unkeyed input on a cacheable path, send the malicious header on the real URL (no cache buster) and confirm the poisoned response gets stored:
- Send
GET /withX-Forwarded-Host: evil.com. - Request
GET /again without the header. - If you still get the
evil.compayload (withX-Cache: hit), the cache is poisoned β every visitor now receives it.
For the report, do this against a cache-buster key to prove the mechanism without impacting production traffic, and clearly describe how it would apply to the live key.
What you can poison into
- Stored XSS β poisoned
<script src>/<link>pointing at attacker JS = XSS for all users (highest impact) - Open redirect / forced redirect to attacker site
- Content spoofing / defacement
- DoS β cache a broken/oversized/error response so real users get it (cache the 400)
- Cookie/CSP/host-based secondary effects
Detection tooling
Burp's Param Miner has a "guess headers" / "guess cookies" mode built specifically for finding unkeyed inputs β it fires known cache-poisoning headers and detects reflections/cache behavior automatically. Pair it with manual verification of the cache hit.
The impact ladder
- Unkeyed reflection but not cacheable / self-only β low
- Cache poisoning β redirect / content spoof β medium/high
- Cache poisoning β stored XSS served to all users β high/critical
- Poisoning an auth/JS resource that enables ATO β critical
Conclusion β the cache-poisoning playbook
- Unkeyed inputs change the response but aren't in the cache key.
- Confirm the page is cached (
X-Cache,Age). - Find an unkeyed header (
X-Forwarded-Hostet al.) reflected into the response. - Cache it (test with a cache buster), confirm the hit serves your payload.
- Poison into stored XSS / redirect / DoS β impact is everyone.
If you Love reading my blogs. Check my Youtube Channel too.