「Ajaxブラウザセキュリティ - 主戦場をDOMに移したXSS」

IPAから情報セキュリティ技術動向調査(2011 年上期) のひとつとして「Ajaxブラウザセキュリティ - 主戦場をDOMに移したXSS」という報告が公開されていますので、ちょっと読んでみた感想などを…。

まずは些末なツッコミから。


(5.2. Ajaxの登場と進化)
JavaScriptの中からのWebサーバとの間の非同期の通信を可能にしたAPIは、XMLHttpRequestという組み込みオブジェクトである
XMLHttpRequest として最初に実装されたIEのそれは、ActiveX Object であり「組み込みオブジェクト」ではありません。


(5.5. 「同一源泉」の制約)
「同一源泉」の制約
「同一源泉」なんていう独自用語使わずに、"Same Origin Policy" そのままか、あるいは「同一生成元ポリシー」と書けばいいのに。


(5.9. XHRレベル2)
例えば、次のようなレスポンスヘッダをWebサーバが返してくる場合、
Access-Control-Allow-Origin: 呼び出し側ドメイン
ここに示された 呼び出し側ドメインに該当する「出身地」のコンテンツからは当該サーバへクロスドメイン呼び出しが許され、他は許されない。
書かれている意味がわかりにくいです。XMLHttpRequestを発行したドメインAccess-Control-Allow-Origin: で返されるドメインが一致すれば、XMLHttpRequest を利用しているJavaScriptから responseText 等を利用してクロスドメインなコンテンツを利用可能、というのが現実で、注意しなければならないのは XHR level 2を実装するブラウザでは、サーバ側の Access-Control-Allow-Origin: の有無とは関係なくHTTPのリクエストは発行できる、という点であり、Access-Control-Allow-Origin により許可された場合のみJavaScript内からそのコンテンツにアクセスすることができる、ということです。


(5.9. XHRレベル2)
お気づきのとおり、これらのレスポンスヘッダはWeb API側が「呼び出し元」に対して制約をかけるものである。呼び出し側が「呼び出せる先」の範囲を制約するような仕組みはいまのところ用意されていない。呼び出し側が何らかの干渉を受け、悪意のWeb APIを誤って呼び出すよう仕向けられた場合には、被害が生じるおそれがある。
まったく意味がわかりませんが、これは「正規のサイト(信頼するに値するサイト)が何らかの干渉を受け、悪意あるサイトにXHR level 2 を使ってアクセスする可能性があるが、現状のXHR level 2 にはそれを防ぐ仕組みはない」と言いたいんでしょうか。「何らかの干渉を受け」がさっぱりわかりませんが、それって多分クロスサイトスクリプティングそのものだったりするので、XHR level 2の仕組みとして防ぐようなものでもないと思いますし、わざわざこういう文脈で取り上げている意味がやっぱりよくわかりません。


(5.10. 新しいタイプのスクリプト注入(XSS)攻撃)
DOM上の危険な入力地点(ソース)から得たデータに含まれる攻撃パターンをそのままにして危険な出力地点(シンク)へ送り出すことで、Webページ内に悪意のスクリプトが侵入する
「ソース」「シンク」という用語は、XSSで攻撃する立場としては便利ですが、この文章でこの用語を出しているのは、いたずらに話を複雑にしているだけに思います。


(5.11. 従来型のスクリプト注入(XSS)攻撃)
サーバ側プログラムの「ソース」から入ってくる攻撃パターンを見過ごして「シンク」へそのまま出力することで攻撃が成立する。したがって対策は、「シンク」に危険な内容が出力されないよう、サーバ側プログラムの中で特殊記号を無害化する等、比較的単純なもので済んでいた。
サニタイズ脳的なニオイがそこはかとなく…。
「HTMLを生成する時点でエスケープするという原則を守る」というように書けば、先にも書いたとおり「ソース」「シンク」のようなXSS厨用語を使わなくても済むのに。


(5.12. DOMを舞台とするスクリプト注入(XSS)攻撃)
DOMを舞台とするスクリプト注入(XSS)攻撃
ここも「DOMを舞台とするスクリプト注入」みたいな独自用語ではなく、"DOM based XSS" あるいは「DOMベースのXSS」などで十分だと思います。

…ここからが本題のDOM based XSS対策な話だけど、ここまで書いて力尽きたので、続きはまたそのうち気が向いたら。

あ、これだけ書いておく。
DOM based XSSといっても新しい点はそんなになく、原則としては「HTMLを生成する時点でエスケープ」なので、JavaScript内でHTML(DOM)を生成する時点で意図しないDOM構造にならないようきちんとエスケープする(あるいはcreateTextNodeのような方法を使う)といった点に気をつけるのと、<a href> や location への代入で javascript: スキームや data: スキームが入らないようにするといった、通常サーバサイドで行っているXSS対策と変わらないことをJavaScript上でやるだけです。