以下の内容はhttps://cysec148.hatenablog.com/entry/2025/09/16/074912より取得しました。


Lab: Cache key injection

Hello there, ('ω')ノ

全体像(何がどう繋がる?)

  1. /login のリダイレクトが不備

    • クエリの utm_contentキャッシュキーから除外する正規表現が甘い。
    • これにより lang=en?utm_content=...後ろ未キー化のパラメータ列実質追記できる(=unkeyed append)。
  2. /login/ が読み込む /js/localize.js が CSPP

    • lang の値をURLエンコードせずに import へ渡すため、&cors=1&x=1... といった追加クエリそのまま混入できる(= client-side parameter pollution)。
  3. /js/localize.jsOrigin でレスポンスヘッダー注入

    • cors=1 を付けるとサーバは Origin を見て CORS 用のヘッダーを返す。
    • Origin 値に CRLF(%0d%0a) を入れると ヘッダー分割→ボディ差し込みが発生(= response header injection)。
  4. cache key injection が可能

    • Pragma: x-get-cache-key を付けると実際に使われるキャッシュキーが分かる。
    • 観察すると、URL上の特殊トークンで“ヘッダーを合成”してキーを作る挙動($origin=...$ など)がある=ヘッダー注入が URL 経由で再現できる。

これらを 「①直接キャッシュ汚染 → ②被害者を /login から汚染済みJSへ誘導」 の2手で決めます。


事前設定(Burp Repeater)

  • Protocol: HTTP/2 に切替(Inspector → Request attributes)。
  • ヘッダー名は小文字に統一(origin など)。
  • 自動 URL エンコードに注意。本文中の %0d%0a%250d%250a(二重エンコード)はそのまま送る。

ステップ1:cache key の“見える化”(なぜ必要?)

  1. Repeater で次を送る(任意のパスでOK):
GET /js/localize.js?lang=en HTTP/2
pragma: x-get-cache-key
  • 応答に キャッシュキーが出ます。
  • ここから、URL内に $$origin=value$$ を入れるとキーに “h:origin=value” のような形で反映されることが分かる=cache key injection のサイン。
  • 後続の「URLだけでヘッダーを合成」する作戦の確信を得ます。

ステップ2:まず“JSオブジェクト”を汚染(直接キャッシュに毒を入れる)

ねらい:/js/localize.js特定キーalert(1)ボディとしてキャッシュさせる。 ポイント:HTTP/2 ではヘッダー値に生 CRLF は送れないため、%0d%0a を使う。origin は小文字

リクエスト:

GET /js/localize.js?lang=en?utm_content=z&cors=1&x=1 HTTP/2
origin: x%0d%0aContent-Length:%208%0d%0a%0d%0aalert(1)$$$$
  • cors=1 で CORS 分岐へ入る。
  • origin:%0d%0a を入れ、Content-Length: 8空行を注入 → 以降の alert(1)レスポンスボディになる。
  • 末尾の $$$$ は“お守り”のパディング(CLを越える分は無視される想定)。
  • これで 「パス=/js/localize.js、クエリ=lang=en?utm_content=z&cors=1&x=1、ヘッダー=origin: x...キャッシュエントリalert(1) が保存されます。

なぜ utm_content=z を入れる? 次のステップで /login の不備を利用して、被害者の /login から同じキーlocalize.js を引かせるための“型合わせ”です。


ステップ3:/login の unkeyed append から同じキーの JS を読ませる

ねらい:被害者が /login にアクセス → ページ内の localize.jsimport URLCSPP で汚染され、ステップ2と同じキーの JS を取りに行くようにする(=キャッシュヒットalert(1) 実行)。

リクエスト(キャッシュ汚染用の /login への“仕込み”):

GET /login?lang=en?utm_content=x%26cors=1%26x=1$$origin=x%250d%250aContent-Length:%208%250d%250a%250d%250aalert(1)$$%23 HTTP/2

ここが肝(細かい文字の意味)

  • lang=en?utm_content=...

    • /login のリダイレクトで utm_contentキャッシュキーから除外されるため、“後続の文字列が unkeyed で付く”
    • さらに localize.js?lang=... の**lang** はURLエンコードされずに import に渡るため、&cors=1&x=1...そのままクエリへ混入(=CSPP)。
  • %26& のエンコード(URLの中でクエリ区切りとして解釈させたい)

  • $$origin=...$$

    • cache key injection の“書式”。URLの中origin ヘッダーを合成させます。
    • HTTP/2準拠で小文字 origin にしている点が重要。
  • %250d%250a%0d%0a の二重エンコード

    • まずプロキシが %25xx%xx1段階デコード
    • 次にアプリ(または中間層)が %0d%0a → CRLF2段階目で解釈し、ヘッダー分割が成立。
  • 末尾 %23# のエンコード(以降をフラグメント扱いにさせ、不要な文字列を無視させるための切り捨て)。

これで /login?lang=en へ来る被害者は、redirect→loginページの中で /js/localize.js?lang=en?utm_content=z&cors=1&x=1(相当)を読み込み、ステップ2で汚染済みのキャッシュから alert(1) を受け取ります。


動作確認とコツ

  • 被害者はChrome想定:あなたが上記 2 リクエストを送った/login を別タブで普通に開く(または何度か開く)。
  • 期待挙動:localize.js の読み込みalert(1) が発火。
  • うまくいかない場合:

    • HTTP/2か? Repeater の Protocol を再確認。
    • ヘッダー名は小文字? origin が大文字だと弾かれる。
    • 二重エンコードは維持? %250d%250a%0d%0a に勝手に変換されていないか。
    • まず Pragma でキーを見たか? $$origin=...$$cache key がどう変わるかを見てから本攻撃へ。
    • 順序ステップ2(JS毒入れ)→ステップ3(/login誘導)。逆だとヒットしない。

まとめ(最小実行セット)

  1. JSを毒化(直接キャッシュ汚染)
GET /js/localize.js?lang=en?utm_content=z&cors=1&x=1 HTTP/2
origin: x%0d%0aContent-Length:%208%0d%0a%0d%0aalert(1)$$$$
  1. /login から同じキーを読ませる(unkeyed append + key injection)
GET /login?lang=en?utm_content=x%26cors=1%26x=1$$origin=x%250d%250aContent-Length:%208%250d%250a%250d%250aalert(1)$$%23 HTTP/2

これで /login?lang=enリダイレクト先ページ毒化された localize.js を参照し、被害者ブラウザで alert(1) が実行されます。


よくある質問(Why系)

  • なぜ origin は小文字? HTTP/2 ではヘッダー名は小文字。大文字混じりはプロトコル違反で落ちる。
  • なぜ二重エンコード? URL → 1段階デコード(%25%)→ その後 CRLF(%0d%0a)として解釈、という二段階を通すため。
  • なぜ Content-Length: 8 alert(1)8文字。ぴったりにしてボディを確定させる。
  • なぜ utm_content キャッシュキーから除外されるため、キーを変えずに後続パラメータ(&cors=1...)を実質的に追加できる。

Best regards, (^^ゞ




以上の内容はhttps://cysec148.hatenablog.com/entry/2025/09/16/074912より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14