utsuroi cache poisoning labs知識ベース 01 / 01
Web Cache Poisoning · Knowledge Base
01

Web Cache Poisoning の基礎

When a single attacker poisons everyone

CDN や Reverse Proxy のキャッシュに「悪意ある応答」を保存させ、その後の全ユーザに配信する攻撃。1人の攻撃者の1リクエストで、何千人もの被害者が同じ罠を踏みます。

1. キャッシュキーとキャッシュ可能性 #cache-key

CDN(Cloudflare、Akamai、CloudFront 等)や Varnish 等のリバースプロキシは、レスポンスをキャッシュキー(通常は URL のパス + クエリ + ホスト)で識別して保管します。同じキーへのリクエストにはキャッシュから即返答するので、サーバ負荷が下がり、応答が速い。

// キャッシュキー = (Method + Host + Path + Query) のハッシュ
GET https://shop.utsuroi.example.com/products/nagi
↓ キャッシュキー: "shop.utsuroi.example.com/products/nagi"
↓ 初回: オリジンサーバから取得 → キャッシュ
↓ 2回目以降: キャッシュから即返答

2. Unkeyed Input(キャッシュキーに含まれない入力) #unkeyed-input

レスポンス生成に影響するが、キャッシュキーに含まれないリクエスト要素。

典型的には HTTP リクエストヘッダの一部:X-Forwarded-HostX-Original-URLUser-Agent、Cookie 等。これらがサーバ側でレスポンスに反映されるのに、キャッシュキーには含まれていないと攻撃が成立する。

例:アプリが X-Forwarded-Host を信用してリンクを生成

GET /home HTTP/1.1
Host: shop.utsuroi.example.com
X-Forwarded-Host: evil.com          ← unkeyed input

オリジンの応答(キャッシュされる):
<link rel="canonical" href="https://evil.com/home">
<script src="https://evil.com/static/main.js"></script>

→ 後続の正規ユーザがこのレスポンスを受ける → 攻撃者の JS が実行

3. 典型的な攻撃 #typical-attacks

4. 正しい防御 #defense

  1. キャッシュキーに「レスポンスに影響する全要素」を含める — Cloudflare の Cache Key カスタマイズ、Varnish の vcl_hash で明示
  2. CDN/プロキシで信頼できないヘッダを破棄X-Forwarded-HostX-Original-URLX-Rewrite-URL 等を CDN レイヤで除去
  3. アプリケーション側で信頼できないヘッダを使わない$_SERVER['HTTP_X_FORWARDED_HOST'] ではなく、設定ファイルの canonical URL を使う
  4. キャッシュ可能なエンドポイントを限定 — 動的・個別化されるエンドポイントは Cache-Control: no-store
  5. 監視 — キャッシュヒット率、レスポンスサイズの異常、Vary ヘッダの不一致をモニタリング