このように、IEにおけるスタイルシートの記述方法は非常に柔軟です。そのため、「expression」や「url」といったスクリプトを動作させるきっかけとなる文字列を、Webアプリケーション側で検出するのは非常に困難です。
Webアプリケーション側でこのようなXSSを防ぐには、以下のような方法が考えられるでしょう。
ユーザーに書式の指定などを行わせるのが目的であれば、ユーザーから直接スタイルシートを入力させるのではなく、Wikiなどのように独自の文法で書式情報を記述し、それを基にWebアプリケーション側でスタイルシートを生成するなどが考えられます。
Webメールのように、自由なスタイルシートの入力を許容せざるを得ないWebアプリケーションでは、前項のような対策は採れませんので、スタイルシートを検査しなければなりません。
スタイルシートをパースする場合には、スタイルシートを安全な要素だけで構築し直すホワイトリスト的な方法と、入力されたスタイルシートから危険な文字列を探すブラックリスト的な方法が考えられます。
ホワイトリスト的な検査を行うライブラリとしては、「HTML Purifier」などがあります。このライブラリは、スタイルシートだけでなくHTMLについても検査を行います。
HTML Purifierはデモページも用意されており、自由にHTMLおよびCSSを入力し、それらを基にどのようなHTMLが再構築されるのかを実際に確かめることができます。私もさまざまなパターンを試してみたのですが、HTML Purifierを攻略することはできませんでした。
【参考】
HTML Purifier Live Demo
http://htmlpurifier.org/demo.php
一方、ブラックリストによるスタイルシートの検査としては、はてなダイアリーの対策方法が広く知られています。
スタイルシート内から「expression」をはじめ、危険性にありそうな文字列を削除するという方法になっていますが、そもそもこの対策方法は、前述のさまざまな「expression」の表記方法の模索とともに、破られては改修するという流れを何度も繰り返してできたものです。また、はてなダイアリー自身にXSSが見つかり対策した場合でも、この対策方法の内容が改定されていないこともありました。そのため、この対策方法だけをうのみにスタイルシートの検査を実装することは、正直お勧めできません。
可能であれば、ホワイトリストによる検査あるいは自由なスタイルシートの入力の禁止といった別の対策をとることをお勧めします。
【参考】
はてなダイアリーXSS対策 - はてなダイアリーのヘルプ
http://hatenadiary.g.hatena.ne.jp/keyword/はてなダイアリーXSS対策
また、IE8ではスタイルシートにおける「expression」は、標準モードでは動作しないように変更されました。
【参考】
Internet Explorer 開発チーム ブログ 2008/10/16 CSS Expressions のサポート終了について
http://msdn.microsoft.com/ja-jp/ie/dd253083.aspx
そのため、保険的な対策となりますが、IE8を使っているユーザーに対しては、コンテンツをIE8標準モードとしてレンダリングできるように(Webアプリケーション自身がIE8標準モードで問題なく動作することが前提条件となりますが)、以下のような<meta>要素を含めて、強制的にIE8標準モードが使われるようにしておくのもよいでしょう。
<meta http-equiv="X-UA-Compatible" content="IE=8" /> |
IE8での標準モードでのexpressionの未サポートなどを見ていると、マイクロソフト自身が過去の互換性と安全で標準に準拠した実装のバランスをとることに苦心していることが見てとれるようです。
前述のように、2007年ごろには全角で「expression」と記述した場合でもスクリプトは動作していました。当時マイクロソフトに問い合わせたところ、やはり「仕様に基づく動作です」という回答だったのですが、現在のIE6ではこの記述ではスクリプトが動作しないようになっており、いつの間にか安全な方向に仕様を転換したようです。
第1回「IEの引用符の解釈」にも書きましたが、過去の互換性を犠牲にしてでも安全な実装に変えていくには、やはり多くのユーザーが声をあげていくことが最善の方法だと思っています。
【編集部注】
記事初出時、「数値文字参照」と書くべき個所を「実体参照」と記述していました。また、「expression」の一部の表記方法について、現在のIE6では動作しないと記述していましたが、あらためて確認しましたところ、現在のIE6においても動作することを確認しました。
ご指摘頂きました読者の方にお礼申し上げます。
Copyright © ITmedia, Inc. All Rights Reserved.