クロスサイトスクリプティングって何だ?
Wikipediaによると
クロスサイトスクリプティング(英: cross site scripting)とは、 ウェブページの部分をユーザからの入力をそのままエコーバック (オウム返し)することによって生成しているアプリケーションの セキュリティ上の不備を利用して、サイト間を横断して悪意のある スクリプトを注入する攻撃のことをいう。また経緯上、 それを許してしまう脆弱性についても、このように呼ばれている。
とのことらしい。 全然わからんかったので、自分でHTMLを書いてみたらようやく理解できた。
超簡単なXSSのサンプル
入力内容をそのままページに表示するプログラムを書いてみる。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> <p></p> <h4><a href="http://google.com">Google</a></h4> <ul> <li>今日はいい天気</li> </ul> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <input type="text" name="name" id="inputed_text" value=""> <input type="button" name="name" id="btnRegist" value="投稿"> <script type="text/javascript"> $(function() { $('#btnRegist').on('click', function() { var inputed_text = $('#inputed_text').val(); $('ul').append('<li>'+ inputed_text +'</li>'); }); }); </script> </body> </html>
投稿ボタンを押すと入力内容がそのままページに表示される。これはサンプルとしてHTMLだけで書いたが、実際には入力内容はサーバーに保存され、このWebサービスを使う全ユーザが同じ内容を共有できるようになっていると仮定する。
この入力欄に下記のような一文を挿れて投稿してみる。
</li> <script type="text/javascript"> $('a').attr('href','http://yahoo.co.jp'); </script> <li>
するとHtmlはこのようになる。
<html lang="ja"><head> <meta charset="utf-8"> </head> <body> <p></p> <h4><a href="http://yahoo.co.jp">Google</a></h4> <ul> <li>今日はいい天気</li> <li></li> <script type="text/javascript"> $('a').attr('href','http://yahoo.co.jp'); </script> <li></li></ul> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <input type="text" name="name" id="inputed_text" value=""> <input type="button" name="name" id="btnRegist" value="投稿"> <script type="text/javascript"> $(function() { $('#btnRegist').on('click', function() { var inputed_text = $('#inputed_text').val(); $('ul').append('<li>'+ inputed_text +'</li>'); }); }); </script> </body></html>
ul要素(リスト)の中にscriptが埋め込まれ、Googleのリンク先が Yahoo!JAPANに変わっている。
今回のサンプルはリンク先を変えただけだが、input要素のPostの送信先を改ざんしてクレジットカード番号を抜き取るというようなことが行われているらしい。
対策は?
入力内容に含まれる危ない文字(<とか>とか&やら)をエスケープするのが基本的な対策法。
RubyOnRailsはRails2までは、明示的なエスケープ処理を書く必要があったけどRails3からはエスケープがデフォルトになったんだそう。