クロスドメインのHTML読み取り(IEのバグ CSSXSS)とCSRF

Security 4月 2, 2006
(Last Updated On: )

追記:このブログを記載する理由となったURLを記載された方が内容を削除されたようです。「間違っている」と言われるのは心外である、と思ったことは確かですがページの内容が削除されるのは私の本意ではありません。書かれていた情報はとても役に立つ情報だと思います。非常に残念なので再度掲載されることを望みます。(本当
—–

セキュリティ対策ではよくあることですが、条件の見落としによりセキュリティ対策を行っていても脆弱性が発生することがあります。「Webアプリセキュリティ対策入門」に書かれているCSRF対策にも「クロスドメインのHTML読み取り(IEのバグ)」の問題が修正されていない為、書籍に記載した対策を行ってもバグを持つIEに対してはCSRFに脆弱になります。

しかし、このバグの影響を持って「Webアプリセキュリティ対策入門」のCSRF対策を「間違った対策」と書かれても困ります。妥当な表現はバグがあるブラウザに対して「不十分な対策」ではないでしょうか。

このブログを書くきっかけは以下のURLです。

http://www.jumperz.net/texts/csrf.htm

問題点を整理してみます。(IEのCSSXSSバグ問題として知られる問題)

IEはスタイルシートとしてCSS以外のファイル、例えばHTMLファイル、を外部サイトから読み込めてしまうバグがある。

つまり、HTML等に埋め込まれた情報は第三者のサイトから盗む事が可能となる。

つまり、HTML等に秘密情報(トークン等)が記載されていると意図しないフォーム送信(CSRF)を行える。

同じくIEのバグが原因のXST(Cross Site Tracing)に似ている問題と言えると思います。
汎用性(複数のページを開いている場合)の考慮はされていませんが

http://www.jumperz.net/texts/csrf.htm

に利用可能な対策が紹介されています。重要なのは以下の2つです。

  • HTMLにトークン(フォーム送信を一意に特定できる値)を書かない
  • トークンをセッションIDと紐付ける

この2つを実行することでIEのバグを回避し、CSRFを防止することがWebサイト側で可能になります。

ところで、この問題の本質はセキュリティの基本中の基本であるCIAをブラウザが守れない事に原因があります。(Confidentiality, Integrity, Availavility – の内のConfidentiality(機密性)が守られていない。)マイクロソフトも直すつもりはあるようで

http://d.hatena.ne.jp/hoshikuzu/20051204#P2005204MATANGILLON

に、直すつもりがある旨が記載されています。実際現在のIEはCSSファイルのように見えなければHTMLの中身が読み取れない状態らしく半分直した(?)ような状態になっているようです。(前にSJISは使わない方が良い、とブログで書きましたがこの件でもSJISをページのエンコーディングに使うのは危険なようです)

jumperz.netの対策はバグを持つIEユーザ向けCSRFの対策としては使用できますが、ページに表示されている情報を盗み見れて困るのはCSRF(CSRFの場合、hiddenタグのトークン情報)だけではありません。様々な情報には他人に見られるだけでも困る物も多くあります。例えば、メールや銀行/証券/保険会社の口座情報を広く公開しても気にしない、と言う人は少ないと思います。

セッションIDをページに記載する手法は、キャッシュ制御をしっかりしないとプロキシ等のキャッシュ(どんなヘッダを送ってもキャッシュする、しないはプロキシ次第ですが)にセッションIDが記録されるので簡易な対策として紹介しています。この方法はCSRF対策を行っていないアプリが、普通のブラウザと環境においてCSRF対策を行う場合、問題も少なく、最も対策が簡単だからです。

本来外部サイトのHTMLページはコンフィデンシャルな情報であり、それが守れない状態であるIEが根本的な問題です。重要な情報をページに表示できないのであれば、重要な情報を表示するアプリはインターネットに公開する事はできません。

CSRFだけ考えても、数え切れないほどの開発者が開発しているWebサイトより、MSが開発しているIEのバグを直す方が速いのは明らかと思います。この手のバグに対する対処は仮りに書籍に書くとしても注意事項として小さく書く程度が限界かと思います。出版した頃にはもう解決済みの問題となっている可能性も高いですから。このあたりは紙メディアの限界ですね。

マイクロソフトはPassportアカウントのメールアドレスがvbscriptでどのサイトからでも参照できるバグを長期間放置していた実績があり、今回のバグが長い間放置される可能性も少なくありません。もしかしてIE7では直っている、とアドバイザリを出すつもりなのかも知れません?!火が付けばパッチ出す!?と言うことで、広く知れた事なので騒ぐが勝ちかも知れません。

とは言っても、MSは昨年に分かっていた問題に対して未だに完全なパッチを提供していない事は事実なようです。このような状況ではWebサイト側でも対策しないとMSがいつ対応してくれるか分かりません。情報を盗み見られるも困りますが情報を改竄される方が大きな被害である事に議論の余地は無いと思います。jumperz.netにはクッキーとJavaScriptを使った対策が紹介されていますが、これにはもう少しスマート(汎用的)なやり方もあります。

JavaScriptの使用を前提とするなら「Webアプリセキュリティ対策入門」書かれているフォームID(フォームのトークン – hiddenタグに記載)とセッションID(クッキーに保存)でMD5でメッセージダイジェストを取り、フォームにセットして送信します。サーバ側ではCSRFが行われていないかメッセージダイジェストを比較するロジックを追加するだけでOKです。この手法の場合、複数のページを同時に開いても問題無く処理でき、同じフォームの複数回送信も防げます。

作業量はさておき、この変更自体は簡単ですよね? フォームの方はhiddenタグの追加と簡単なJavaScriptを追加するだけ、サーバ側はMD5の値を作って追加されhiddenタグと値を比べるだけです。hiddenタグの値が無い場合は、CAPTCHAまたはパスワード入力方式にfallbackしても良いかも知れません。本を読んだ方でこの説明で対処方法がよく解から場合はコメントをお願いします。

# MD5関数はJavaScriptにはありませんが、探せば沢山実装が見
# 付かります。
#
# 個人的には、自前のフォームクラスを使っているアプリの場合、
# 上記の修正を加えるにはを少しフォームクラスを修正するだけ
# で対応できました。
#
# ところで.NET ASPで作ったWebサイトはViewState等の為(?)
# このIEのバグによるCSRFの影響は受けないのでしょうか?
# MSの腰が重い理由はこのあたりあるのかな?と疑いを持って
# いる次第です。識者の方、コメント頂ければ幸いです。

Web開発者としては過去のブラウザバグまで考慮して開発するのは困った物です。ユーザとしてもJavaScriptとクッキーを使ったフォーム送信がデフォルトになるとFirefoxのNoScript拡張を使っていると面倒が一つ増えます、IEでもActiveScriptを無効に設定している人も同じ面倒が増えます。仮りにIEのバグが直ったとしてもまた同じ問題が他のブラウザや新しいIEでも発生する事も考えられます。直したハズの問題がまた表れるのもよくある事です。

多分少しするとIEのバグも修正されると思います。JavaScriptとクッキーを使ったCSRF対策を次の書籍等の著作物に入れるべきなのか、省略すべきなのか、悩ましい所です。

蛇足:
Session IDのクッキーに非標準のHttpOnly属性を使いたい方は、Sessionを初期化する場合に別のCSRFチェック用のHttpOnly属性無しクッキーを初期化して使用します。

蛇足2:
時々「IEを使うのは止めときましょう」と、このブログにも書いていますがこの問題もIEを使わない理由の一つですね。2004年はIEが安全に使えた日は7%日しかなかったという調査もあります。2005年は多少まし(?)かも知れませんが、2006年は2004年に似たような数値になるのかも知れませんね。

蛇足3:
PHPの透過的セッション管理(trand_sid)は利用しない、といつも言っていますがtrans_sidを行っているサイトの場合、フォーム送信ページをリクエストする事によりセッションIDを簡単に盗まれます… セッションIDをフォームに記載したCSRF対策も同様にセッションIDを盗まれます。念のため。

投稿者: yohgaki