utsuroi xss labs Lab 05 / 5 — Practitioner
05

コンテキスト脱出 — 属性値の中で破られるエスケープ

XSS via context escape — partial encoding fails for attributes

うつろい カウンセリング予約サイトの確認画面。お名前(?name=)が画面の2か所に展開される:

  • テキストとして表示(これは textContent なので安全)
  • マイページへのリンクの URL 部分:<a href="/mypage/{name}">

サーバはエスケープを実装しているつもりだが、htmlspecialchars() のフラグ指定が ENT_NOQUOTES になっており、"' がエスケープされない。属性値の中では破綻する。

?name= パラメータにペイロードを入れて、Lab 01 の素朴な <script> 注入とは違う方法で alert を実行させてください。<> はエスケープされるので、別のベクトルが必要です。

URL: 未送信
booking.utsuroi.example.com / confirm
サーバ側のエスケープ(中途半端な実装)
// PHP — フラグ指定が不適切
$name_html = htmlspecialchars($_GET['name'], ENT_NOQUOTES, 'UTF-8');
//                                            ↑ クォートをエスケープしないモード

// 出力先は2か所:
echo '<p>お名前: ' . $name_html . '</p>';            // テキスト → 安全
echo '<a href="/mypage/' . $name_html . '">...</a>';  // 属性 → 破綻

ENT_NOQUOTES< > & だけをエスケープし、"'そのまま残します。テキストコンテキストでは問題ないが、属性値では " でクォートを閉じられて属性ブレイクアウトされる。

ペイロード解析 — 属性値での挙動
<a href="/mypage/山田花子">...</a>
解析結果
    ヒント 1 — 何がエスケープされ、何が残るか

    サーバがエスケープしているのは < > & のみ。"' はそのまま残ります。属性値はクォートで囲まれているので、これを使って何かできるはず…

    ヒント 2 — 属性ブレイクアウト

    href="..." の中に " が入ると、属性の終わりとして解釈されます。属性が終わった後に新しい属性を書ける。onmouseover= のようなイベントハンドラ属性を追加して JavaScript を実行可能。

    ヒント 3 — もう1つの脱出経路

    属性値を脱出しなくても、href 自体に javascript: スキームを入れれば、リンクをクリックした時に JavaScript が実行されます。ただし「クリック」が必要。onmouseoveronfocus を併用すれば自動発火が可能。

    正解(ネタバレ)— 2通り

    解 A:属性ブレイクアウト

    " onmouseover="alert('XSS')

    これで生成される HTML は <a href="/mypage/" onmouseover="alert('XSS')"> となり、リンクにマウスを乗せると alert。

    解 B:javascript: スキーム + autofocus

    javascript:alert('XSS')

    ただしこれだと href の中身が /mypage/javascript:alert('XSS') になってしまうので、別の脆弱性パターンが必要。本ラボでは解 A が正解

    このパターンは「コンテキスト依存エスケープ」の代表例。HTML 本文・HTML 属性・URL 内部・JavaScript 内部・CSS 内部 でそれぞれ必要なエスケープが異なります。