# Gotta cache 'em all: bending the rules of web cache exploitation

URL parser discrepancies between CDNs and origin servers enable arbitrary web cache poisoning and deception, letting attackers hijack sensitive responses or poison highly-visited paths.

- Payout: Research
- Severity: high
- Program: Web caches/CDNs
- Credited: PortSwigger Research
- Disclosed: 2024-08-08
- Write-up quality: 9/10
- Original: https://portswigger.net/research/gotta-cache-em-all
- Library page: https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-gotta-cache-em-all
- Tags: domain:web impact:data-leak impact:integrity kind:research platform:research sev:high tech:cdn tech:nginx technique:chained technique:parser-differential vuln:cache-deception vuln:cache-poisoning

**Target:** CDN cache proxies and origin HTTP servers (CloudFlare, CloudFront, Azure, Akamai, Imperva, Fastly, Nginx, IIS, OpenLiteSpeed, Spring, Rails)
**Root cause:** Cache and origin parsers disagree on path delimiters (semicolon, dot, %00, %0a, hash) and normalization (dot-segments, encodings, backslashes), so the same URL maps to different resources and cache keys.
**Steps:**
1. Detect origin delimiters: send non-cacheable request to `/home`, then `/homeabcd`, then `/home$abcd`; identical responses reveal `$` as delimiter.
2. Detect cache delimiters: send cacheable `/static-endpoint<DELIM><rand>` and compare to base; identical means delimiter.
3. Detect decoding: compare `/home/index` vs `/%68%6f%6d%65%2f%69%6e%64%65%78`; same non-cached response means origin decodes.
4. Detect normalization: compare `/home/index?cb` vs `/aaa/../home/index?cb`; identical means dot-segments resolved.
5. Cache deception: `GET /<Dynamic_Resource><Delimiter><Encoded_Dot_Segment><Static_Directory>` where cache normalizes but origin uses delimiter.
6. Cache poisoning: `GET /<Backend_Path><Delimiter><Path_Traversal><Poisoned_Path>` to control the cache key of a visited path.
7. Front-end delimiter variant: `GET /<Poisoned_Path><Front-End_Delimiter><Path_Traversal><Backend_Path>` (e.g. hash on Azure).
**How found:** Systematically tested each ASCII character (encoded and unencoded) as potential delimiter against origin and cache, then tested encoding and dot-segment normalization behaviors to map parser discrepancies across frameworks and CDNs.
**Exploitation:** Attacker crafts a URL exploiting delimiter/normalization mismatch so the cache stores a dynamic authenticated response (deception) or a malicious response under a popular key (poisoning). Deception link is sent to victim; poisoning requires no interaction and can redirect /main.js to attacker JS via X-Forwarded-Host open redirect, achieving site takeover.
**Escalation:** Chains 'unexploitable' bugs (self-XSS, X-Forwarded-Host open redirect) with cache key confusion to poison /main.js and infect every visitor, or full site defacement when redirect is cacheable.
**Insight:** Enumerate delimiter and normalization behavior per parser independently (origin vs cache) using response-equality oracles; a character meaningless to the cache but a delimiter to the origin (or vice versa) yields arbitrary key control.
