はじめに
OWASPでは、開発者に向けたセキュリティ対策のためのドキュメントやチートシートを多数用意しており、XSSへの対策としても「XSS (Cross Site Scripting) Prevention Cheat Sheet」というドキュメントが用意されています。
ただし、このXSS Prevention Cheat Sheetはシンプルなルールを定めたチートシートであるとうたいつつも、開発者が直面するあらゆる場面で包括的に適用できる抜けのないものを目指しているために、多岐にわたる条件のもとでの詳細なルールが定められており、残念ながら決して誰しもが簡単にすぐ適用できるものではないというのが現状です。
そこで、本稿では、より一般的で頻繁に遭遇する共通的な状況下に限定することで、XSSへの対策方法を簡潔に説明したいと思います。
本稿では物足りない方、本稿だけでは自身の開発しているWebアプリケーションへの対策として不十分だと感じた方はぜひXSS Prevention Cheat Sheetのほうにも目を通してみてください。
復習:そもそもXSSとは
XSSへの対策方法を解説する前に、あらためてXSSとはどのような脆弱性であるのかを振り返っておきましょう。
例えば、http://shop.example.jp/search?item=OWASPというURLでアクセスすると、商品名に「OWASP」を含む商品の一覧を表示するショッピングサイトがあったとします。
レスポンスとして返されるHTMLの一部には、URLのitemパラメータで指定された文字列「OWASP」が含まれています。
<div> <span>OWASP</span>に関する検索結果:20件 </div>
ここで、http://shop.example.jp/search?item=<s>OWASP</s>のように「OWASP」という文字列のかわりに「<s>OWASP</s>」という文字列を与えてアクセスした場合に、サーバ側がそのまま「<s>OWASP</s>」という文字列をHTML内に含めて返したとします。
<div> <span><s>OWASP</s></span>に関する検索結果:0件 </div>
ブラウザ上に文字列として「<s>OWASP</s>」と表示させるには、HTML内には「<s>OWASP</s>」と生成されなければいけないのですが、サーバ上でHTMLを生成する際に「<」や「>」をエスケープせずにそのまま出力しているために、ブラウザ内ではそのままHTMLタグとして取り扱われてしまいます。
このように、HTMLを生成する段階でのエスケープに漏れのある状態で、攻撃者が「<script>alert("hacked!")</script>」のような文字列を与え、そのときのURL http://shop.example.jp/search?item=<script>alert("hacked!")</script> (注1)をSNSなどを通じて多数の人に拡散したとします。
このURLにアクセスした一般の利用者は、ブラウザ上でいきなり表示される「hacked!」のメッセージに、このショッピングサイトが攻撃者に改ざんされてしまったのではないかと強い不安を感じてしまうでしょう。
注1
実際にはURLのitemパラメータはitem=%3Cscript%3E……のようになりますが、ここでは可読性を優先して便宜上URLエンコーディングを解いた状態で表記します。以降のURLに対する例も同様です。
この例では、攻撃者はalert関数によってメッセージを表示させるという単純で実質的には無害なことしか行っていませんが、攻撃者の作成したJavaScriptが利用者のブラウザ上で動くということは、より悪質な攻撃が行えるということを意味しています。
例えば、攻撃者はJavaScriptによってHTMLに自由にメッセージを書き込む見かけ上の改ざんを行うこともできますし、このショッピングサイトに利用者自身が登録している氏名や住所、メールアドレスなどを盗み見ることもできます。また、偽のクレジットカード番号入力画面を作成し、そこに入力されたカード番号を搾取することや、セッションCookieにhttponly属性が付与されていない場合にはdocument.cookieを通じて利用者のセッションを攻撃者がまるまる乗っ取ってしまうこともできます。
このように、HTMLを生成する際に文字列がエスケープされておらず、攻撃者によって作成されたHTMLタグやJavaScriptが利用者のブラウザ上で表示、実行される脆弱性をXSSと呼びます。