Hello there, ('ω')ノ
動画
1. タイトル
Lab: Exploiting origin server normalization for web cache deception — オリジンサーバの正規化(Normalization)を突いて API キーを取得
2. 注意書き
重要:本記事は学習目的のみ。ラボ以外での実施は禁止。
3. 概要
このラボは、オリジンサーバが URL パスの ドットセグメント(/./, /../)やエンコード(%2f など) を デコード・解決して正規化する一方、キャッシュ層(CDN/リバースプロキシ)がそれを 同じように解釈しない という差異を突く Web Cache Deception (WCD) の応用です。
ゴールは、/resources/..%2fmy-account のような 擬似静的パスを使って、被害者 carlos の /my-account レスポンス(API キーを含む)をキャッシュさせ、同じ URL を攻撃者が閲覧して API キーを読むことです。
4. 必要な前提知識(短い箇条書き)
- URL 正規化:オリジンは
%2f(/)デコードや..解決で 実質的に/my-accountとして処理しうる。 - キャッシュ規則:特定のディレクトリ接頭辞(例:
/resources)を 静的対象としてキャッシュする「静的ディレクトリ・ルール」。 - 区切り文字(delimiter)と正規化の相違:
?,;などの区切りは一致しても、ドットセグメントの解決やデコード有無が不一致だと WCD が成立。 - ヘッダ観察:
X-Cache: miss/hit、Cache-Control: max-age=...でキャッシュ挙動を把握。
5. 攻撃(検証)方針(なぜその順序か)
- ログイン(
wiener:peter)し、/my-accountに API キーが載ることを確認。 - 区切り文字の確認:
/my-account?abcなどで オリジン側の解釈を把握。 - 正規化差異の確認:
/aaa/..%2fmy-account→ オリジンは 200(キー返却) になるかを見る。 - 静的ディレクトリ・キャッシュの同定:
/resources/*が キャッシュ対象かをX-Cacheで確認。 - 不一致の合成:
/resources/..%2fmy-accountで オリジン=/my-account(動的・機密)、**キャッシュ=/resources/...(静的扱いで保存)**を引き起こす。 - Exploit サーバで carlos を誘導→ 被害者のレスポンスがキャッシュ → 同一 URL を攻撃者が閲覧して carlos の API キーを取得。
6. ステップ別の概要(やること / 意図 / 期待される出力)
ステップ 1:ログインして /my-account に API キーが露出することを確認
- やること:Burp のブラウザで
wiener:peterでログインし/my-accountを見る。 - 意図:ターゲットの価値(API キー)を確認。
- 期待:本文に 自分の API キーが表示。
ステップ 2:区切り文字の調査(参考)→ ? のみが有効
- 手順(要約):
/my-account/abc→ 404、/my-accountabc→ 404。 Intruder で/my-account§§abcに delimiter 候補を差し込み、URL エンコード無効でスキャン。 - 期待:
?だけが 200(自分の API キー表示)。 - 示唆:オリジンは
?を区切りとして扱うが、これは普遍的なので 正規化差異のほうへ進む。
ステップ 3:正規化差異の確認(ドットセグメント解決)
- やること:Repeater で
/aaa/..%2fmy-accountを送信。 - 意図:オリジンが
%2fを/にデコードし、..を解決して/my-accountと解釈するかを検証。 - 期待:200 で 自分の API キーが返る → オリジンは正規化する。
ステップ 4:静的ディレクトリ・キャッシュ規則の同定
- やること:Proxy → HTTP history で 静的資産のパスを観察 →
/resources接頭辞を発見。 その任意リクエストを Repeater へ送り、/resources/..%2fYOUR-RESOURCEを送信。 - 期待:最初は
X-Cache: miss、同一 URL を再送でX-Cache: hit。 - 検証:
/resources/aaaでも miss → hit になる →/resources接頭辞でキャッシュする静的ディレクトリ・ルールがあると確定。
ステップ 5:不一致の合成(最重要)→ 悪性 URL を完成
- やること:
/aaa/..%2fmy-accountの代わりに/resources/..%2fmy-accountを Repeater から送る。 期待:200 + X-Cache: miss → 同一 URL を再送で hit。
- 意味:オリジンは
..%2fを解決して/my-accountとして **動的レスポンス(API キー含む)**を返すが、キャッシュは/resources/...を 静的として保存する。 - これで 認証ページが静的 URL としてキャッシュされ、第三者に配布可能になる。
- 意味:オリジンは
ステップ 6:エクスプロイト作成(carlos を誘導→被害者レスポンスをキャッシュ)
- やること:Exploit server を開き、Body に以下(YOUR-LAB-ID を置換、キャッシュバスターを付ける):
<script>
document.location="https://YOUR-LAB-ID.web-security-academy.net/resources/..%2fmy-account?wcd";
</script>
- 意図:carlos(ログイン済み)が この URL を取得
→ オリジンは正規化して carlos の
/my-accountを返す → キャッシュはresourcesルールで そのレスポンスを保存。 - 期待:以後、同じ URL を開くと carlos のページ内容(API キー) がキャッシュから配布される。
ステップ 7:攻撃者がキャッシュから carlos の API キーを取得
- やること:同一 URL を開く:
https://YOUR-LAB-ID.web-security-academy.net/resources/..%2fmy-account?wcd
- 期待:本文に carlos の API キーが含まれる → これを Submit solution に貼って完了。
7. トラブルシューティング(成功しない場合のチェック)
- X-Cache が常に miss:同一フル URL を再送しているか/TTL(
Cache-Control: max-age)内かを確認。 - 自分のキャッシュが出てしまう:クエリ(
?wcdの値)や任意トークンを 新規にして キャッシュキーを変える。 ..%2fが効かない:タイポに注意(%2fは小文字で/)。..%2fmy-accountの位置・綴りを再確認。/resourcesが無い/別接頭辞:HTTP history で 静的資産の共通接頭辞を観察。- Origin が 404 を返す:アプリが更に厳格な正規化・ブロックを行っているかも。別の静的接頭辞や 別クエリで再試行。
8. なぜこれが危険なのか(本質)
- 正規化の不一致:オリジンは正規化して機密ページを返すのに、キャッシュは非正規化のままパスをキー化し、静的ルールで保存してしまう。
- 機密情報の第三者配布:認証が必要な API キー/個人情報が、誰でも取得できるキャッシュに載る。
9. 防御(実務で取るべき対策)
- 認証リソースは常に
Cache-Control: no-store, private。 - キャッシュ層とオリジンの正規化を統一(デコード、ドットセグメント解決、末尾スラッシュ、拡張子ルール)。
- 静的ディレクトリ・ルールの厳格化:
/resourcesなどに 正規表現での「ドットセグメント否認可」 を導入。 - 監視と検知:
/resources/..%2fのような 正規化前の異常パスをログ監視・遮断。
10. 検証の確認ポイント(ラボでの成功条件)
/resources/..%2fmy-account?wcdにアクセスして carlos の API キーが見える。- Submit solution でキー提出 → Solved。
11. まとめ
オリジンは ..%2f を解決して /my-account を返すが、キャッシュは /resources/... を静的として保存 → 被害者でキャッシュ汚染 → 同 URL を攻撃者が閲覧して API キー取得(ラボクリア)。
Best regards, (^^ゞ