2007年2月16日
あまり知られていない脆弱性:DOM Based XSSにご用心
こんにちは、SEの進地です。
XSS(Cross Site Scripting)脆弱性の中であまり注意を払われていないタイプにDOM Based XSSというものがあります。アナウンス自体は随分と昔から行われており、webappsec.orgでも2005/7/4にAmit Klein氏が"DOM Based Cross Site Scripting or XSS of the Third Kind"を発表しています。
Web 2.0的アプリなどでのAjaxの普及でJavaScriptが多用される現在のWeb開発では、DOM Based XSSが入り込む可能性は従来よりも高まっています。そこで、今回はこのDOM Based XSSについて説明しようと思います。
DOM Based XSSとは何か?
一般的にXSS脆弱性と聞いて思い浮かべるのは、攻撃者の悪意ある入力データ(JavaScriptなど)がサーバサイドでのエンコードや削除をすり抜けてクライアントにアウトプットされるというものだと思います。例えば、PHPで下記のようにGETパラメータをそのまま出力することで発生するXSS脆弱性です。
<?php if ( ! empty( $_GET['name'] ) ) { echo ("Hello, " . $_GET['name']); } ?>
このタイプのXSS脆弱性はサーバサイドでの入力データのエンコード、削除漏れによって生じています。つまり、攻撃者の悪意ある入力データは一旦サーバサイドに送られています。
DOM Based Cross Site Scripting or XSS of the Third Kindでは冒頭で3つのXSSのタイプについて説明しています。
第1のXSSは悪意ある入力データが先の例のように直ちに画面に出力されるタイプ、第2のXSSは悪意ある入力データが(例えば掲示板のように)一旦サーバにデータとして保存された後に画面に出力されるタイプです。
そして第3のXSSとして言及されているのがDOM Based XSSです。第1、第2のXSSが悪意ある入力データがサーバサイドを経由するという特徴があるのに対して、このDOM Based XSSでは悪意ある入力データが必ずしもサーバサイドを経由する必要がないという特徴を持っています。
DOM Based Cross Site Scripting or XSS of the Third Kindでは下記の例が示されています。
<HTML> <TITLE>Welcome!</TITLE> Hi <SCRIPT> var pos=document.URL.indexOf("name=")+5; document.write(document.URL.substring(pos,document.URL.length)); </SCRIPT> <BR> Welcome to our system … </HTML>
このHTML(http://example.com/welcome.htmlとします)に
http://example.com/welcome.html?name=Joe
とアクセスすれば、document.URL.*メソッドとdocument.writeメソッドの働きで画面上にJoeが出力されます。
そして、例えば
http://example.com/welcome.html?name=<script>alert(document.cookie)</script>
とアクセスすれば、画面上にブラウザが保持しているCookieがアラート表示されます(※1)。これがDOM Based XSSです。
ここで重要なのは、サーバから返されたページ内に攻撃スクリプトは一切含まれていないということです。攻撃者はクライアント(主にブラウザ)が構築するHTMLのDOM(Document Object Model)のオブジェクトやそのプロパティを操作することで攻撃を行い、生のHTMLにスクリプトを埋め込もうとはしません。つまり、サーバサイドは攻撃スクリプトを出力していません。
さらに、
http://example.com/welcome.html#name=<script>alert(document.cookie)</script>
とすることでもスクリプトを実行させることができます。IE、FireFox、その他多くのクライアントにおいて#以降の文字列はサーバサイドに送出せず、クライアント内で処理を行います。その為、サーバのアクセスログにはhttp://example.com/welcome.htmlのみが記録され、攻撃の痕跡はサーバサイドに残らず、サーバサイドは攻撃を検知できません。
まとめると、DOM Based XSSの重要な特徴は
・サーバサイドは攻撃スクリプトを出力していない
・サーバサイドに攻撃スクリプトを送出せずに攻撃が可能な場合があり、この場合、サーバサイドは攻撃を検知できない
ということになります。
従って、DOM Based XSSの対策として、第1、第2のXSSの対策である、サーバサイドでの入力データのエンコード、削除は効果がないということになります。また、生のHTMLに攻撃スクリプトが現れないため、静的な解析ツールでは脆弱性を検出できないという特徴もあります。
DOM Based XSSを使った攻撃シナリオ
サーバサイドで攻撃コードが出力されないDOM Based XSSでは、例えば次のような攻撃シナリオを考えられます。
1.DOM Based XSS脆弱性を持つ会員サイトXがある
2.A(攻撃者)はXの会員であるB(被害者)に対してサイトX上でDOM Based XSSを起動するパラメータ付きのURLを(メールや、自分のサイト上に記載するなどして)踏ませる。パラメータにはBがサイトXで保持しているCookieをAに送出するスクリプトを仕込んでおく。さらに、TinyURL等を利用してパラメータ付きURLを短いURLにカムフラージュしておき、Bに不信感を持たせずにアクセスさせる工夫もできる。
DOM Based XSSだけに限らず、XSSに対して多い誤解ですが、対象サイト上に攻撃スクリプトを生に埋め込めなくても、パラメータ付きURLを被害者にアクセスさせることによってXSSは起動できることに注意してください。従って、上の攻撃シナリオは第1のXSSでも利用できます。
DOM Based XSSへの対策は?
DOM Based XSSに対する包括的な対策、体系的な対策は残念ながらありません。
サーバサイドを経由する第1のXSS、第2のXSSのようにサーバサイドで対策(エンコード等)すればよいというものではないからです。
上述の"DOM Based Cross Site Scripting or XSS of the Third Kind"ではEffective defenses(効果的な防御法)としてDOM Based XSS脆弱性を生み出さないために守るべき指針が3つ挙げられています。
1.クライアントサイドのデータを使ってドキュメントを書きかえたり、リダイレクトしたり、その他細かな動きをすることを避けます。これらの動きはなるべくサーバサイドの処理に置き換えます。
2.ドキュメント(HTML、およびJavaScriptコード)を攻撃者によって影響を受けるようなDOMのオブジェクト、プロパティの使われ方がされていないか精査します。例えば、下記のオブジェクト、メソッド、プロパティの使われ方に注意します(なお、これが全てではありません)。
document.URL
document.URLUnencoded
document.location (および、document.locationの持つ多くのプロパティ)
document.referrer
window.location (および、window.locationの持つ多くのプロパティ)
document、window等のオブジェクトは他の変数に参照を持たせて、参照から各メソッド、プロパティを利用できることにも注意が必要です。つまり、window.locationと呼び出すこともできるし、locationと呼び出すこともできるし、また、変数some_windowに何かのwindowオブジェクトの参照が入っていれば、some_window.locationと呼び出すこともできます。従って、単純な静的解析では不充分で、スクリプトのロジックを追いながら精査する必要があります。
また、DOMを操作してドキュメントを書き換えたり、リダイレクトしたり、スクリプトを実行したりするあらゆるコードに注意を払う必要があります。"DOM Based Cross Site Scripting or XSS of the Third Kind"に特に注意すべきプロパティ・メソッドがリストされていますが、それが全てではありません。何故なら、クライアントがくみ上げるDOMにはクライアント毎に様々な拡張があり、今後も変化していくこと、新しいクライアントが登場することが予測されるからです。
3.厳しいポリシーを組み込んだIPSを用意し、認められたパラメータ以外が送られてきた場合はドキュメントを返さないようにします。ただし、この方法は先に説明した#name=<script・・・のようにクライアントがサーバサイドに攻撃コードを送出しない場合は効果がありません。
まとめ
DOM Based XSSは入力データがサーバサイドを経由する第1、第2のXSSと異なり、必ずしもサーバサイドを経由する必要がなく、また生のHTMLソース上に攻撃コードが含まれないため、サーバサイドでの対策(入力データのエスケープ)は効果がありません。そもそも攻撃を検知できない可能性もあります。
ですので、DOM Based XSSを防ぐためには、まずこういう攻撃が存在することを知り、愚直にHTMLソースのコードレビューを行い、JavaScriptによるクライアントサイドでの入力チェックも徹底する必要があります(※2)。クライアントサイドの入力データでDOMを書きかえる操作もなるべく避け、サーバサイドでそれらの処理を行うように設計しましょう。
XSSは常にサーバサイドが原因で起こるという認識は誤りです。Web 2.0的アプリ、Ajaxの利用の普及でJavaScriptが多用される現在のWeb開発においては、SE・プログラマだけでなく、マークアップやJavaScriptによるスクリプティングを担当するデザイナにもXSSの知識は必要になってきていると言えると思います。
※1
FireFoxではURLに指定された<、>を自動でエンコードするので再現しません。IEで実験してみてください。
※2
ただし、JavaScriptでの入力チェックは攻撃者にそのチェックロジックが見えてしまうため、穴があれば、直ちにそこを突かれてしまうことにも注意が必要です。
カテゴリー: セキュリティ(システム開発)
タグ:
« 前の記事:地球温暖化:社内に共用エコバッグを置いてレジ袋の消費を減らしてみる
» 次の記事:ビッグイシューの勝手広報:自殺対策支援センター「ライフリンク」の清水康之さん
アークウェブの本
Zen Cartによるオンラインショップ構築・運用テクニック―オープンソース徹底活用
内容充実のZen Cart公式本(v1.3対応)がついに発表です。アークウェブのスタッフをはじめZen-Cart.JPの中心メンバーが共著で執筆しました。続きを読む
新着はてブ
カテゴリー
- Shopify(ショピファイ)オンラインショップ構築
- NGO・NPO向け情報
- スマートフォン
- だれもが使えるウェブコンクール
- mixiアプリ
- OpenSocial (システム開発)
- アークウェブのCSR
- A-Form, A-Member, A-Reserve(MTプラグイン)
- Ruby on Rails(システム開発)
- necoったー
- Miqqle
- WebSig24/7
- ecoったー
- ビッグイシュー(The Big Issue)
- CSR(企業の社会的責任)
- マッシュアップ
- RIA (システム開発)
- セキュリティ(システム開発)
- 唐松(アクセス解析)
- Ajax (システム開発)
- テスト(システム開発)
- データベース
- PukiWiki
- Web 2.0
- SEO・サーチエンジン最適化
- XP・アジャイル(システム開発)
- Web・ITニュースクリップ
- Webアクセシビリティ
- Webデザイン
- SEM・サーチエンジン広告
- Webユーザビリティ
- CMS・MovableType
- Zen Cart(オンラインショップ構築)
- Snippy(SNS・ソーシャルブックマーク)
- アークウェブ
- オープンソース
- CMS(コンテンツマネジメント・システム)
- Webマーケティング
- AMP
- SNS