2013/12/11

CVE-2013-5612: Firefoxのcharsetの継承によるXSS

Firefox 26で修正された、 オリジンを超えて文字エンコーディングを継承させることができたため、 XSSを引き起こせる場合があったバグについて書きます。

MFSA 2013-106: Character encoding cross-origin XSS attack
https://www.mozilla.org/security/announce/2013/mfsa2013-106.html


一言で言います。

エンコーディング指定がないページに対し、POSTリクエストを送ると、たとえオリジンが異なっても、 POSTリクエストを送ったページのエンコーディングを使ってページを表示することができていました。
つまり、エンコーディング指定がないページで自動選択されるエンコーディングを、外部のサイトが自由に選択できたということです。


発見のきっかけはZDResearchという情報セキュリティ会社の以下のXSSチャレンジに挑戦していたときです。

https://zdresearch.com/challenges/xss1/


このページにはエンコーディングの指定がなく、ページのエンコーディングを想定外のもので表示できればXSSできるのに、と考えていたところ、この問題に気が付きました。
そのときの解が以下です。Firefox26未満のブラウザでXSSできます。

http://l0.cm/zdresearch_xss_challenge.html


ISO-2022-KRがPOSTを送ったページ l0.cm から継承され、 「0x0E」から「0x0F」が2バイトで1文字表現となり、期待するHTML構造を破壊し、onmouseover属性を埋め込むことができています。

(ちなみに、この発見の賞品として、ZDResearchから以下の写真の A Bug Hunter's Diary: A Guided Tour Through the Wilds of Software Security を頂きました。Thank you ZDResearch!)



余談として、現在Firefoxがサポートしているエンコーディング( http://l0.cm/encodings/table/ を参照 )はほとんどが安全なものに限られており、また、 エンコーディング自体のバグの多くも修正されているので、全く無理ではないものの、 HTMLの構造をうまく変更してXSSすることが難しいです。UTF-7とか、X-Mac-Farsiがサポートされている頃に発見していたらもうちょっとおもしろかったんですけど!

とはいえ、このバグが修正されても、そもそもウェブページにエンコーディング指定がない時点でどのエンコーディングで表示されるかが保証されないので、今後もエンコーディング指定がないページでは、場合によっては想定外のものが自動選択され、XSSが起きる場合はあり得ます。引き続き、サイト管理者はContent-Typeヘッダ(※こっちで確実にすることを推奨します)やmetaタグで、エンコーディング指定をきっちりすべきです。

2013/11/30

MS13-037: エンコーディングの自動選択の強制によるXSS

2013年5月の月例パッチ、MS13-037で修正された、Internet Explorerでエンコーディングの自動選択を強制的に起こせたバグについて書きます。

http://technet.microsoft.com/ja-jp/security/bulletin/ms13-037
 このセキュリティ情報に組み込まれている多層防御についてマイクロソフトと協力してくださった Masato Kinugawa 氏

アドバイザリには問題に対する説明がありませんが、多層防御で修正されたのがこの問題です。

今回は、ざっと、報告書っぽく。
 --------------------------------------------


報告日:
2012年11月23日

問題の概要:

IEで特定の方法でページを表示しようとすると、ページのエンコーディングの指定にかかわらず、ページに含まれるバイト値からブラウザ側でエンコーディングを判断する、"エンコーディングの自動選択"が勝手に発生する。

ページのエンコーディングがユーザーにより切りかえられるとXSSが起きる場合があるという記事を以前書いた( http://masatokinugawa.l0.cm/2012/12/encoding-self-xss.html )ように、 この動作は、単なる表示上の問題だけでなく、XSSなどのセキュリティ上の問題を引き起こす場合があり、好ましくない。


発見したきっかけ:

IEでページを見ていた際に、適切にエンコーディングの指定がされているページで文字化けが発生したことから。



再現させた環境:

Windows Vista sp2 IE9(2012年11月までに提供されたパッチをすべて適用済み)


再現方法:

以下のように細工したページを用意することで、強制的に自動選択を起こすことができる。

<script>
function go(){
window.open("http://vulnerabledoma.in/r_slow?url=http://target/","x")//手順1
window.open("http://vulnerabledoma.in/h_back.html","x")//手順2
}
</script>
<button onlclick=go()>go</button>

手順は、

1. ターゲットのページに対して "少し細工をした300台のリダイレクト" を起こすページをwindow.openする
2. そのページに対してすぐに「戻る」操作だけが書かれたページ( <script>history.back()</script> )をwindow.openでかぶせる


これでターゲットのページに「戻ったとき」、文字化けが起こる。

1のリダイレクトの細工とは、リダイレクトが完了するまでに意図的に数秒の遅延を発生させるようにしてあること。 実際に http://vulnerabledoma.in/r_slow?url=https://www.google.com/ にアクセスしてみると、 リダイレクトするまでに時間がかかることがわかると思う。

このリダイレクトははさまなくても化かすことはできるのだが、  ターゲットのページが完全に読み込まれる前に「戻る」動作がされると問題が起こる挙動であったため、読み込みがはやいページでは、化かすのに失敗することがあった。遅延のあるリダイレクトをはさむと、読み込みがはやいページでも確実に問題を起こすことができる。

XSSで攻撃するときには、ターゲットのページの文字列を出力できる部分から、特定のエンコーディングの特徴的なバイト列を並べ、特定のエンコーディングで作られているように装えばよい。うまくいけば、IEは自動選択でそのエンコーディングを選択し、HTMLやJavaScriptもろとも構造を変えることができる。

--------------------------------------------


もちろん、前提条件として、ターゲットのページが特定のエンコーディングで表示されたとき、XSSが起きるような作りになっている必要があります。難しそうですが、できないこともありません。
実際に、GoogleのサービスでXSSが可能な箇所を複数確認しており、報告しています。(なお、この情報提供に対し、特別に$500を頂きました。)

これがそのときに報告したページの1つです。

https://docs.google.com/spreadsheet/embeddedform?formkey=dDBuQjhkWVozbV9JR1NSRDBHNHRHVWc6MQ
 
このページを先ほどの仕掛けにかけると、ページに含んだ [0x1B]$)C という特徴的なバイト列から、ISO-2022-KRが選択され、XSSが起きていました。

(※ただし、このGoogleの問題を再現させる場合、ページで右クリック→「文字コード」→「自動選択」のチェックが入っている必要があります。この設定はすべてのページで永続的に適用されます。この設定がオンになっていないと、システムロケールがエンコーディングの決定にかかわってきて、うまくISO-2022-KRが選択されません。)
 
なお、報告した11月から修正が発表された5月まで、細かい動作が変更されているかもしれないので、もし再現させてみようという方がいれば、2013年4月より、2012年11月までさかのぼった方が確実です。実際、僕が2月くらいにみたときはうまく動かなかった気がします。多分途中で、軽減策として自動選択で選択されるエンコーディングが制限されて、ISO-2022-KRなどが選択されなくなったのではと思います。

そこまで戻すのが面倒な人は、上のGoogleのページを開いて「エンコード」→「韓国語」で疑似体験ができます。

おまけの話として、パッチが提供された後、再現方法が少し違う文字化けの問題に対しても、パッチ後に問題が起きなくなったというWeb上の投稿があったりして( http://answers.microsoft.com/ja-jp/ie/forum/ie9-windows_7/%E6%88%BB%E3%82%8B%E3%83%9C%E3%82%BF%E3%83%B3/2b34b6ea-17f4-4499-ac07-aa8a007ac251 )、目に見える表示上の問題も直ってよかったなーと思いました。


そんなんでした。
エンコーディングの記事は基本人気がない気がしますが、次もエンコーディングの記事を書く予定です!

2013/10/29

Referrer文字列によるXSS

リファラを使ったXSSの小ネタです。

今回取り上げるのは、ターゲット自身が、細工したページを経由することでつけられたリファラによって攻撃を受けるケースです。このような攻撃の場合は、現実に経由可能なページからでしか攻撃文字列を送りこむことができません。

例えば、以下のように、document.referrerをそのままdocument.write()しているページがあるとします。

http://vulnerabledoma.in/location/


リファラを書き出している部分でXSSできるでしょうか。

IEでは単純です。
IEはURLのクエリに、エンコードせずに「"<>」などを含めることができるので、これらを含むURLから、リファラを書き出しているページへ遷移させれば、XSSが起きます。

http://l0.cm/xss_referrer.html?<script>alert(1)</script>


Firefox・Chrome・Safariなどのブラウザの場合は、「"<>」はクエリ中でエンコードされるのでこのPoCではスクリプトは実行されません。

IE×リファラ でXSSが可能なことは、知ってる人は知っているのではないかと思いますが、 今回は、ChromeやSafari(6.1で確認)でも攻撃が可能だということを紹介します。今日言いたいのはここです。たぶん、まだ誰も公開していない手法だと思います。

はい:

data:text/html,<meta name="referrer" content="always"><script>if(location.protocol!='data:'){alert(1)}else{location.href="http://vulnerabledoma.in/location/"}</script>


「<meta name="referrer" content="always">」という、リファラ送信を制御するタグ( http://wiki.whatwg.org/wiki/Meta_referrer )をつけると、通常はリファラを送信しないdata: URLからでもリファラを送信してくれるようです。こうすると、ChromeやSafariで「"<>」をリファラに含められます。
Firefoxでも今後、 <meta name="referrer">をサポートしたら攻撃が可能になるかもしれません。

以上、XSS小ネタでした。

2014/6/30 追記
この手法は2014/6/30時点で最新のChrome(35.0.1916.153)/Safari(7.0.4)で動かなくなっています。
Safariで動作する別の手法について新しい記事を書きました。(基本的にはdata: からblob: にしただけ)

Referrer文字列によるXSS part2
http://masatokinugawa.l0.cm/2014/06/referrer-xss-part2.html

2014/9/22 追記
Safari(7.1)で確認したところ、動かなくなりました。