うつろい カウンセリング予約サイトの確認画面。お名前(?name=)が画面の2か所に展開される:
- テキストとして表示(これは
textContentなので安全) - マイページへのリンクの URL 部分:
<a href="/mypage/{name}">
サーバはエスケープを実装しているつもりだが、htmlspecialchars() のフラグ指定が ENT_NOQUOTES になっており、" と ' がエスケープされない。属性値の中では破綻する。
うつろい カウンセリング予約サイトの確認画面。お名前(?name=)が画面の2か所に展開される:
textContent なので安全)<a href="/mypage/{name}">
サーバはエスケープを実装しているつもりだが、htmlspecialchars() のフラグ指定が ENT_NOQUOTES になっており、" と ' がエスケープされない。属性値の中では破綻する。
?name= パラメータにペイロードを入れて、Lab 01 の素朴な <script> 注入とは違う方法で alert を実行させてください。< と > はエスケープされるので、別のベクトルが必要です。
// 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>
サーバがエスケープしているのは < > & のみ。" や ' はそのまま残ります。属性値はクォートで囲まれているので、これを使って何かできるはず…
href="..." の中に " が入ると、属性の終わりとして解釈されます。属性が終わった後に新しい属性を書ける。onmouseover= のようなイベントハンドラ属性を追加して JavaScript を実行可能。
属性値を脱出しなくても、href 自体に javascript: スキームを入れれば、リンクをクリックした時に JavaScript が実行されます。ただし「クリック」が必要。onmouseover や onfocus を併用すれば自動発火が可能。
解 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 内部 でそれぞれ必要なエスケープが異なります。