XSSとは
XSS(クロスサイトスクリプティング)は、脆弱性のあるWebサイトに対して、悪意のある不正なスクリプトを挿入する攻撃のことを示します。
挿入したスクリプトを、サイトに訪れたユーザーに実行させる攻撃のため、ウェブサイトそのものではなく、サイトを利用するユーザーに被害が発生します。
XSS対策を行っていないサイトでは、どのように攻撃されるのか例を見てみます。
XSS対策をしていないサイトの例とXSS攻撃方法
「投稿する」ボタンを押下すると、入力データが保存された後、次の投稿一覧画面に表示されるサイトとします(今回テーマから逸れてしまうので、データベースに保存する処理を省略しています)。
例:投稿フォームと一覧画面
<h1>投稿フォーム</h1>
<form action="comment_index.php" method="post">
<p>コメント</p>
<input type="text" name="comment">
<input type="submit" value="投稿する">
</form>
<h2>投稿一覧</h2>
<?php
$sql = 'SELECT * FROM comment;
$comments = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
foreach ($comments as $comment)){
echo '<p>'.$comment['comment'].'</p>'.PHP_EOL;
}
?>
図:「投稿する」ボタンをクリックしたらコメント一覧の下に表示される
このようなXSS対策を行っていないサイトでは、入力フォームにJSコードを書き込まれると、そのままコードが出力されるため、読み込み時に動作してしまいます。
以下のようなコードを書き込むと、当該ページへアクセスした利用者全員に、alertメッセージが強制的に表示されてしまいます。
<script>window.alert('このメッセージを表示したユーザー全員にアラートメッセージを表示');</script>
図:サイトのユーザー全員にアラートメッセージが表示されてしまう
このような脆弱性のある環境では、次のような3つの攻撃が予想されます。
攻撃①:サイトの改ざん
JSのコードの差し込みができると、画面の表示内容を変更することができます。
例のようなコメント一覧サイトに、次のようなコードを送信することで、全く別の内容を表示させる事ができます。
改ざんすることで、他にもECサイトで表示価格を変更させたり、会員サイトで再度ログイン画面などを出すことで個人情報を盗み出すといった被害が考えられます。
<script>document.getElementsByTagName("h1")[0].innerHTML = "ウイルスに感染しました!";document.getElementsByTagName("h2")[0].innerHTML = "ウイルスに感染しました!以下のサイトで、大至急セキュリティーソフトをダウンロードしてください";document.getElementsByTagName("p")[0].innerHTML = "";document.getElementsByTagName('h2')[0].insertAdjacentHTML('afterend','<a href=”http://罠サイト”>ダウンロードリンク</div>');</script>
攻撃②:フィッシング詐欺
また、以下のようなにJSのコードを送信することで、アクセスと同時に偽サイトに転送させることが可能です。
<script>window.open('http://罠サイト');</script>
本物そっくりのサイトを作成してそこに転移させることで、個人情報を入力させて盗み出すといった被害が考えられます。
攻撃③:セッションハイジャック
コンピューター通信で利用する「セッション」を奪い、「なりすまし」で不正アクセスをする行為です。
方法に関してはこちらの方が詳しく書かれていたので、リンクを載せておきます。
対策:サニタイズ(無効化)する
XSSの対策は、サニタイズが有効です。
サニタイズとは、ユーザからフォームの値を取得した際に、htmlで特別な意味を持つ以下の記号を別の記号に置換することです。
置換することで、先程のようなスクリプトが実行できなくなるため、被害を防ぐことができます。
記号 | サニタイズ |
---|---|
< | < |
> | > |
& | & |
" | " |
' | ' |
PHPの場合:htmlspecialchars()を用いる
<?php
foreach ($comments as $comment)){
$comment = htmlspecialchars($comment['comment'], ENT_QUOTES, 'UTF-8');
echo '<p>'.$comment.'</p>'.PHP_EOL;
}
CakePHPの場合:h()メソッドを使用する
htmlspecialchars()と同義となっています。
<?php
foreach ($comments as $comment)){
echo '<p>'.h($comment['comment']).'</p>'.PHP_EOL;
}
また入力フォームでFormHelperを使用することでも、自動でサニタイズしてくれます。
<?php
echo $this->Form->control('comment');
Laravel(blade)の場合: {{ }}で囲む
これによって、自動的にhtmlspecialchars関数を通してくれます
<?php
{{ $comment['comment'] }}
XSS対策まとめ
PHP | CakePHP | Laravel |
---|---|---|
htmlspecialchars() | h() | {{ }} |