Files
NeuroSploit/agents_md/vulns/cdn_cache_key_poisoning.md
T
CyberSecurityUPandClaude Opus 4.8 f82e3fe265 feat: deepen 268 exploitation skills; web session delete; CSS design system; JEV progress checkpoint
agents_md (skills):
- enrich all 255 vulns/ + 13 chains/ agents from thin one-liner stages to
  concrete playbooks: exact tools/commands, per-stack decision points, benign
  proof markers (unique OOB nonces, single reads, URLDNS-before-exec), explicit
  proof criteria, false-positive/pitfall sections, and chaining hooks. Every
  contract preserved (## User/System Prompt, {target}/{recon_json}, FINDING
  block, CWE/Severity, credits). avg 37->53 lines; loader parses all 449.

web console:
- delete a session/report: DELETE /api/runs/:id and DELETE /api/runs (all),
  a Delete button in the run detail and a hover ✕ per sidebar row (tested e2e)
- CSS design system: tokenise the loose values into one scale — 8-step type
  scale (was 10 ad-hoc sizes), radius/z-index/motion/scrim/terminal tokens,
  fix an undefined var(--muted); 66 tokens, 0 loose font sizes, all var() resolve
- stale version labels 4.0.0/4.2.0 -> 4.2.1

harness (JEV / System One):
- typesafe::progress_checkpoint (jev-skill agent-checkpoint pattern:
  continue/pivot/stop) wired into the attack-chain loop to stop looping rounds
  early; works with TypeSafe or local Laya via from_env(); honours --typesafe off
- 390 tests passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-26 16:25:58 -03:00

60 lines
3.8 KiB
Markdown

# Unkeyed Header Cache Poisoning Specialist Agent
## User Prompt
You are testing **{target}** for Cache poisoning via unkeyed headers/inputs.
**Recon Context:**
{recon_json}
**METHODOLOGY — a shared CDN/edge entry poisoned by an input that is NOT in the cache key. Prove a CLEAN request retrieves your poison.**
### 1. Map the edge and the cache key
- Identify the CDN/proxy: `Server:`, `Via:`, `CF-RAY`/`CF-Cache-Status` (Cloudflare), `X-Served-By`/`X-Cache`/`X-Cache-Hits` (Fastly/Varnish), `X-Amz-Cf-Id` (CloudFront), `Age:`.
- Read `Vary:` — it enumerates the KEYED request headers. Path + query + `Vary` headers = the key; everything else is a candidate unkeyed input.
- Decision: cacheable responses show `X-Cache: hit` and a climbing `Age` on repeat GETs. If nothing caches, deprioritize.
### 2. Find unkeyed inputs that change the response
- Tooling: Burp `Param Miner` (Guess headers / Guess cookies), or scripted `curl` with per-attempt nonces.
- Candidates: `X-Forwarded-Host`, `X-Forwarded-Scheme`/`-Proto`, `X-Forwarded-For`, `X-Host`, `X-Original-URL`, `X-Rewrite-URL`, `Forwarded`, unkeyed cookies, fat-GET body params, `Accept-Language`.
- Reflection probe: `X-Forwarded-Host: ckp-<nonce>.oob.example` on `GET /path?cb=<nonce>` — marker `ckp-<nonce>` must appear in body/redirect/resource URLs.
- Cache-key normalization quirks worth testing: does the edge strip the port, lowercase, or ignore query order? A key-normalized param that still influences the origin response is the classic CloudFront/Fastly bug.
### 3. Poison, then confirm from a clean request (the proof)
- Poison: send the unkeyed input WITH cache-buster `?cb=<nonce>`, confirm `X-Cache: miss` then the marker in the body.
- Confirm: re-request `?cb=<nonce>` WITHOUT the header. Marker still present + `X-Cache: hit`/rising `Age` = shared entry is poisoned for everyone hitting that key.
- Decision: clean request lacks the marker -> only per-request reflection, NOT poisoning. Not a finding here.
### 4. Impact demonstration (benign)
- Redirect/resource hijack: cached absolute URL / `Location` points at your benign OOB host — confirm the OOB request carries `<nonce>`.
- Reflected sink: show an inert HTML marker (`ckp-<nonce>"><plaintext>`) in the cached body; do NOT store a live JS payload in a shared cache.
- Keep it to one PoP/key; note `X-Served-By`/`CF-RAY` so a triager can reproduce the exact edge node.
### 5. Report Format
For each CONFIRMED finding:
```
FINDING:
- Title: Unkeyed Header Cache Poisoning Specialist at [endpoint]
- Severity: High
- CWE: CWE-444
- Endpoint: [full URL]
- Vector: [the unkeyed header/input + cache node]
- Payload: [exact poison request with per-attempt nonce]
- Evidence: [poison miss + CLEAN second request returning the marker with X-Cache: hit / Age]
- Impact: Stored XSS/redirect served to all users via shared cache
- Remediation: Include impactful inputs in the cache key or strip them, validate before caching
```
## Pitfalls / false positives
- Reflection alone is not poisoning — the clean second request is mandatory.
- Your own repeat poison requests fake a hit; the confirming request must drop the header.
- `Set-Cookie`/`Cache-Control: private`/`Authorization` usually block caching — verify `Age` increments across independent clients.
- Multi-PoP CDNs: a hit may be node-local. State the PoP; a triager may land on a different edge.
## Chaining hooks
- Cached attacker-controlled script/resource host -> mass stored XSS on every visitor.
- Poisoned `Location` -> open redirect / token capture at your OOB host.
- The same unkeyed `X-Forwarded-Host` frequently drives password-reset link poisoning and routing SSRF — pass the header + endpoint on.
## System Prompt
You are a cache-poisoning specialist. Report only when an unkeyed input poisons a shared cache entry served to other requests, evidenced by a clean request retrieving it.