前回 http://d.hatena.ne.jp/mala/20111125/1322210819 の続きです。
前回のあらすじ
- ブラウザベンダーはサードパーティCookieをデフォルトでオフにしたかったんだけどお前らがサードパーティCookieに依存したサイト作るし使うからオフに出来なかったんだよ!!!!!
といった事情を踏まえた上でWebアプリケーションにおけるサードパーティCookieの利用の歴史について書きます。前提知識の共有が済んだので、ここからはある程度個人的な意見も含まれます。実装面での技術的な内容も含みます。
サードパーティCookieが必要とされてきた歴史
広告のためのトラッキングCookie以外にも、サードパーティCookieに依存したサービスが数多く存在してきた。個人的に把握しているいくつかのサービスについて時系列で述べる。ついでに広告業界の流れについても重要なのを幾つか混ぜる。
2005年
- Netvibes、iGoogleなどのパーソナライズホームページサービスが登場する。
- 「ガジェット」としてログイン済みの外部サイトをiframeで埋め込むものが存在してきた。
- GoogleはP3Pヘッダを使ってログイン状態の外部サイトを埋め込むことが出来ると案内している
- NetvibesはSafariユーザーに対して全てのCookieを受け入れるように案内している
- JSONPが使われ始める
- JSON with Padding http://ajaxian.com/archives/jsonp-json-with-padding
- 関数名固定のcallbackが呼ばれるものから、クエリパラメータでcallback関数名を指定できるものが広く使われるようになる
- MyBlogLogが開始
- アクセス解析サービスで、ユーザ登録することでBlogに誰が訪問したのか分かるサービス。
- 後に米Yahooに買収、日本でも類似のサービスがいくつか出ることになる。
2006年
- JSONPを使ったクロスドメインでのマッシュアップ手法について試行錯誤が行われる
- 一方で、JSON Hijackの問題も知られ始める。Gmailのコンタクトリストを外部サイトから盗み取るものなど。
2007年
- 1月、YahooがMyBlogLogを買収する。
- 4月、GoogleがDoubleClickの買収を進める
- 7月、はてなスターがリリース(七夕の季節)
- はてなドメインのサードパーティCookieによって認証されたJSONPに依存した実装
- リリース当時、IEでは外部サイト上ではてなスターを付けられないという状態であった。
- 事情通によると、開発者全員がFirefox + Greasemonkeyによって外部サイト上でのはてなスターの動作確認をしていたので、IEで動かないことに気付いていなかった。
- P3Pヘッダを出力してこの問題を解決 http://d.hatena.ne.jp/hatenastar/20070712/1184231961
- 10月、DISQUS 埋め込みのコメント欄を提供するサービス、サードパーティCookieによって認証している。類似のサービスが幾つか。
- サードパーティCookieも含めて送受信を許可するように案内している http://gyazo.com/95c71b727abcb50cf664f147812b0119
- 参考 http://docs.disqus.com/help/26/
- 12月、gooがgooあしあとを提供開始 http://itpro.nikkeibp.co.jp/article/NEWS/20071220/289990/
- 12月、米連邦取引委員会がGoogleによるDoubleClick買収を承認した http://www.itmedia.co.jp/news/articles/0712/21/news017.html
2008年
- 3月、Yahoo JapanがYahooログールをリリース。yahoo.co.jpのCookieを使用。足あとが残るのは登録ユーザーのみ。
- 3月、欧州委員会がGoogleによるDoubleClick買収を承認した http://www.itmedia.co.jp/news/articles/0803/12/news016.html
- 6月、Firefox3がリリースされる。
- このタイミングで、FirefoxにおいてはサードパーティCookieのブロックによって送信もブロックされるようになった。
- 逆に言えば、IE対応(P3Pヘッダ送信)さえすれば「既にログインしているサイト」の外部サイト埋め込みに対してブラウザ側での制約が無かった。
- サードパーティCookieをオフにすることによって「ログイン済みサイトによるトラッキング」や「外部リソース埋め込みに起因する脆弱性」を抑止できるようになった。
- 8月、Yahoo Japanがインタレストマッチを開始
- 9月、クリックジャッキングの問題が知られるようになる。
- 全てのブラウザ、全てのWebサイトに影響するとしてブラウザベンダーが対応を表明した。
- 11月、はてなブックマークリニューアル http://gihyo.jp/news/report/2008/11/0501
- 追加画面で、ログイン状態のiframeを外部サイト上に埋め込むタイプのブックマークレットを採用した。
- このタイプのブックマークレットは当時日本では珍しく、同じくソーシャルブックマークサービスのBlueDot(2006-)から影響を受けたものだと記憶している
- Evernoteもこのタイプのブックマークレットを採用している
2009年
- 1月、IE8RCがリリース、クリックジャッキング対策としてX-Frame-Optionsが導入される。
- Webサイト側でフレーム拒否のヘッダを出力するというもので、サイト側の対応が必須であった。3月にIE8が正式リリース。
- 3月、Googleが興味/関心に基づいた広告を開始
2010年
- 4月、Facebookが外部サイト向けのlikeボタンを提供する http://jp.techcrunch.com/archives/20100421facebook-like-button/
- サードパーティCookieの送信をオフにした場合こうなる http://ssig33.com/facebook%E3%81%B2%E3%81%A9%E3%81%84
- 9月、mixiが外部サイト向けのmixiチェックボタンを提供する
- 12月、mixiが外部サイト向けのイイネボタンを提供する http://developer.mixi.co.jp/connect/mixi_plugin/favorite_button/get_html_code/
- 似たような機能を続けてリリースしているがチェックボタンはポップアップウィンドウで投稿、イイネボタンはワンクリックで投稿完了するものとなっている http://developer.mixi.co.jp/connect/mixi_plugin/difference_of_mixicheck_favorite/
- イイネボタンは、イイネを押した友人の一覧が表示できるようになっている(サードパーティCookieによる表示のパーソナライズを行なっている)
- イイネボタンはサードパーティCookieを送信しないとエラーが起きて動作しない。
2011年
- 足あと終了ブーム
- 3月、gooあしあとが終了する http://blog.goo.ne.jp/ashiato_01/e/876cfd81489c43363b60ac4f4305624b
- 5月、米YahooのMyBlogLogが終了する
- 6月、Yahoo Japanの Yahooログールが終了する
- 6月、mixiは足あと機能を先週の訪問者に変更する(念のため書くと、他のサービスと違い外部サイト上からmixiアカウントを把握されうるのはmixiにとっては意図せぬ挙動である)
- 6月、Googleが外部サイト向けの+1ボタンを提供する http://googlejapan.blogspot.com/2011/06/1.html
- サードパーティCookieオフの状態では動作せず。一度認証ポップアップウィンドウが開いてエラーが発生する。
- 7月、サードパーティCookieブロックすると google.co.jp にログインできない状態になる
- https://twitter.com/bulkneets/status/87321175977500672
- https://twitter.com/bulkneets/status/87767649244823552
- imgタグやiframeによるCookieのセットに成功すると期待して、シングルサインオンを設計した場合、ユーザーの設定によっては全くログイン出来ないことになる。
- いつから発生していたのか不明、比較的直ぐに解決されたと記憶している
- 8月、Google Puzzleが公開
- 途中までプレイできるがサードパーティCookieをブロックしているとエンディングが見れない
- https://twitter.com/sh4/status/103803450004996096
- 11月、はてなブログ
- サードパーティCookieをオフにしている場合、記事投稿などはできるものの、幾つかの機能が使用不能になる
寸評
個々のサービスついて色々と思うところもあるが特にこの記事で深く掘り下げたりはしない、把握している範囲で述べているだけなので、これ以上に影響の大きいサービスもあったかもしれない。
- ブラウザの機能追加によって、仕様を設計する段階では想定されていなかったリスクが発生している。
- 攻撃手法がWeb開発者に知れ渡るまでにも時間がかかる。JSON Hijackやクリックジャッキングが知られるようになったのは「ブラウザの実装上そのような攻撃が出来る状態」になってから随分と先のことだ。
- 開発者がどういったリスクが発生するのかを知らずに実装してしまうケースが多々ある。
- 意図せずに足あとを残す(訪問者のユーザーアカウントを特定する)リスクがあるサービスは、近年、機能を変更したり終了する傾向にある。
- 2007年ごろ(はてなスター登場時)、自分は、サードパーティCookieに依存したサービスを作ることで、ユーザーやブラウザがプライバシーに配慮したデフォルト設定を選択することができなくなる、と主張していた。
- 実際にブラウザはプライバシーやセキュリティに配慮したデフォルト設定に変更することが出来なかったし、今もなっていない。
- GoogleはDoubleClick買収以降、サードパーティCookieを積極的に利用する傾向にある。
- ちなみにGoogleはログイン時に P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." というヘッダを送る
- 誰が望んでこうなったのかと言い切ることはできないだろう。Web業界渾然一体となってサードパーティCookieに依存したサービスを作り、無効化すると利用できなくなったり、不具合に遭遇したり、不便を被ったりする世の中を作ってきた。
Web開発者の多くは、単にブラウザの仕様に合わせてサイトを作っているだけで、自分の作るサイトがブラウザベンダーの意思決定に影響を与えているという自覚が希薄かも知れない。また「悪用されたら対策を考えれば良いだろう」とリリース時には単にspamやイタズラに使える程度であろうと考えていた脅威が、実際にはサービスの性質そのものに関わる問題であり対処のしようがない、と後から気付いた所で手遅れだったりもするだろう。ユーザーに対して「そのようなサービスを使うべきではない」と言った所で、自己責任で片付けられてしまうだろう。サードパーティCookieの送受信に依存したWebサイトを作る(あるいは使う)ということは、大多数のインターネットマニアでもセキュリティオタクでも何でもない普通の人たちがWebを安全に利用することができないという、そういう状況を肯定することに繋がっている。
Web開発者はどうすべきなのか?
- まずWeb開発者は(少なくとも自分が開発に関わるサービスの動作確認をする時には) サードパーティCookieの送信をオフにすることを強く推奨する。ついでにリファラの送信も止めていい。
- サードパーティCookieをブロックする設定にしたFirefoxかGoogle Chromeで動作確認をすれば良い。
- 上で挙げたような「ログイン状態のiframeやJSONを外部サイト上から利用する機能」が動かなくなる、ということを把握していれば、大した不便を感じることは無いだろう。
- ブラウザは不適切なデフォルト設定を修正してこれなかっただけなので、自信を持っていい。IEとSafariを見習うべきである。
- ユーザー目線に近いように「ブラウザをデフォルト設定で使う」というポリシーの人もいるだろう。しかしこれは「本来ユーザーに与えられていた選択肢」を取り戻すためのものだ。
- サードパーティCookieオフでは全く動作しない(ログイン出来ない、表示できない、無限リダイレクトする)ようなものは論外で、回避手段を用意すべきである。
- 足あとを残すサービスは、そもそもが、悪意のある第三者に訪問者のユーザーアカウントを特定されるリスクが伴うことになることを理解すべきである。
ブラウザはこれからどうするべきなのか?
- 2001年とは状況が変わっている、現実問題サードパーティCookieに依存したWebサイトが多くあり、トラッキングCookieを利用したターゲティング広告が広く普及し、その収益に依存したWebサイトが多く存在している。
- (よほどユーザーの関心が高まらない限り) WebブラウザがデフォルトでサードパーティCookieをブロックするということが現実的にありえないという状況になっている。動作しないサイトが出てきて文句を言われるためだ。
- デフォルトでサードパーティCookieをオフにした場合、evercookieのような、ユーザーにとって、より一層制御が困難な追跡手段が広く用いられる可能性がある。
- サイトごとにサードパーティCookieを許可するための設定が、より簡便に行えるようにならないと、多くのサイトが不具合を起こし、Web開発者の反発を招くだろう。
- Do Not Trackの策定によってプライバシーを気にする人、トラッキングされたくない人はDNT: 1を送ればいいじゃん、という風潮になりつつある。
- しかしDo Not Trackヘッダでは「ログイン状態で外部サイトに埋め込まれることによって発生している諸々のセキュリティ上の問題」が全く解決しないままである。
サードパーティCookieが無効でも動作するようにするにはどうすればよいか
- 今からサービスを作る人は、単にサードパーティCookieを無効化して動作確認をすれば良い。
- 現実問題ユーザーはサードパーティCookieを送ってくるので、ログイン状態で外部サイト上に埋め込まれることで発生する諸々のセキュリティ上の問題に対処しなくてはいけない。
- サードパーティCookieに依存したサービスを作っているのであれば、ブラウザ側の問題であると主張するのは自己矛盾である。
- 既にサードパーティCookieに依存したサービスを作ってしまっている場合に、どうすれば良いのかについて述べる。
ダメなシングルサインオンサービス編
- iframeやimgタグでCookieをセットできる前提で設計されていると、サードパーティCookieオフの場合に動作しない。
- OpenIDやOAuthのように、リダイレクトしてパラメータを受け渡し、ファーストパーティCookieとしてセッションCookieをセットしましょう。
- ログインフォームをiframe内に表示するのはやめましょう。フィッシング耐性が下がります。
ソーシャルボタン編
1. 単純に別windowでlikeなり+1なりスターなり押させれば良い
- 未ログインの場合には、どうせ別windowで認証画面を開く実装になっているのが殆どである。
- 別windowではファーストパーティCookieとして認証Cookieが送られるのだから、何の問題もない。
- クリックジャッキングも防げる。
- ユーザー毎に表示をカスタマイズしたりするのは、諦めるか、localStorageを使う
2. サードパーティCookieの代替手段として、localStorageを使う
- localStorageにユーザーを識別するためのAPI tokenなどを保存しておくことで、サードパーティCookieの代わりに使うことができる。
- localStorageはCookieと違って、サーバーに勝手に送信されることがない。
- 訪問した段階ではサーバーサイドで誰がアクセスしてきたのかを識別せず、ボタンをクリックした段階でユーザーを識別することが出来る。
- 主サービスとCookieを共有しない別ドメインで提供すれば、ログインCookieをトラッキング目的で使っているという疑いを晴らすことが出来る。
- 純粋にlocalStorageとして使われるのか、保存した値がサーバーに送信されるのかはコードを読まなければ判別が付かない。
- よってサードパーティlocalStorageのトラッキング目的での利用が横行すれば、ブラウザはデフォルトでブロックすべきであろう。
- Google ChromeはサードパーティCookieがブロックされていれば、サードパーティのlocalStorageもブロックされるようになった(設定UIをシンプルに保つ都合上、区別をしていないのだと思われる)
- しかし、キチンと実装されれば、Cookieと違って、ユーザーのプライバシーも利便性も損ねない実装をすることが出来る。
- ブラウザはサードパーティlocalStorageの利用に対して、ユーザーに対して通知バーを出し許可を求められるようにすべきである。
「全ユーザー共通のレスポンスを返す」ような埋め込みパーツは、この方式で完全に置き換えることができる。問題は「このページをいいねと言っている友人の一覧」など、ユーザー毎にパーソナライズされたレスポンスを出力する必要があるケースだ。幾つか解決手段があるだろう。
- そのような機能を必要とする人に対して、Web履歴を把握されうることを周知させた上で、オプトインで提供する。
- 友人の付けた「いいね」一覧をlocalStorageにキャッシュし、完全にクライアントサイドでパーソナライズされた表示を実現する。
- アクセスログを共有しない第三者のサーバーを経由して、特定URL(またはURLのハッシュ値)に対して特定ユーザーがいいねと言っているかどうか判別するAPIを提供する
- iframe内のサードパーティlocalStorageに依存した認証を行なった場合に、確認なしで反映されるような機能はオプトインで提供されなければならない。
- なぜかというとサードパーティCookieを無効化してもクリックジャッキングの被害に合うことになってしまうからである。
パーソナライズドホームページの類
- OAuthを使う例が紹介されている http://code.google.com/intl/ja/apis/gadgets/docs/fundamentals.html#Cookies
- 上記のように、今であればlocalStorageを代替手段として使うことも出来るだろう。
- サーバーサイドでOAuthのプロキシをしなくても、localStorageやpostMessageといったHTML5の機能を使うことで、クロスドメインでのデータの受け渡しは容易になっている。
- 例えばiframe内からポップアップウィンドウを開き、Cookieで認証済みのポップアップウィンドウからiframeに対して認証が必要なデータにアクセスするためのAPI tokenをpostMessageで受け渡す、といった具合。
- サードパーティlocalStorageが使える状態であるならば、tokenをlocalStorageに保存しておけば良い。
- この方式であれば、tokenの受け渡しがブラウザ内だけで完結し、第三者のサーバーにtokenを受け渡す必要がない。
OAuthによる認可を与えたり、URLにpasswordやAPI tokenを付加するなどの方法が考えられるが、これは、ガジェット機能を提供しているプラットフォーム(この場合はGoogle)がその気になればユーザーのデータにアクセス可能であることを意味する。認証情報を預かっている以上、ユーザーに代わって操作できる状態になってしまうことが避けられない。つまり、プラットフォームが信頼できないのであれば、サードパーティCookieによって認証されたiframeを読み込んで直接操作したほうが安全、ということになる。外部サービスにidとpasswordを預けるよりもログイン状態のiframeを埋め込んだほうが遥かに安全である。
足あと機能や、勝手に共有の類
- それは単純に自分のプロフィールを勝手に掲示板に投稿するというCSRF脆弱性そのものなので、作るべきではない。
クリックジャッキングのような問題にどう対処すれば良いのか
- クリックジャッキングに対するブラウザベンダの対応はX-Frame-Optionsによってフレーム内表示を拒否するという方法だった。
- 「iframeを使ってログイン状態で埋め込み、確認なしでワンクリックで反映される」という機能を作る以上、クリックジャッキングは防げない。
- ログイン済みのiframeを外部サイトに埋め込むことを前提とした場合、そもそも安全に実装することが出来ない。
- そのような機能を作るなといっても、もう作ってしまった場合にどうすれば良いのかについて述べる。
- どうしても確認なしで実行することに拘りがあるのであれば「勝手にクリックされても、大きな影響がない程度の機能にのみ用いる」というアプローチが考えられる。
取り消しが可能な操作であっても、ボタンを押したことが第三者に伝わるのであれば、それは意図せずにユーザーアカウントを外部から特定可能な脆弱性となる
- クリックした結果が知られるのが「自分のみ」に限定されているなら、意図せずにクリックされても影響は軽微と言えるだろう。単に効率の悪いspamである。
- またクリック結果が知られるのが「友人のみ」でも、早期に気付くことが出来ればワーム的に拡散していくことは防げる。
クリックしたことをWebサイト側からスタイル制御不能なブラウザ側のUIで通知して、取り消し可能にするというアプローチもあるだろう
- 単純にwindow.confirmでユーザーが実行しようとしたアクションに対して確認ダイアログを表示する。
- ブラウザの拡張機能やWeb Notificationsと連携し、アクションを起こしたことの通知を出し、取り消し可能にする
- 拡張機能を入れていない人に対しては確認画面を出せばよい
外部サイトに広く埋め込まれるようなサービスを設計する際にどうすればいいのか
- 外部サイト埋め込みを前提としたサービスは、主サービスとCookieを共有しない別ドメインで提供し、登録ユーザーにだけ使わせるべきである。
- 別ドメインにする理由は単純だ、Web履歴を収集されても構わないと考えているユーザーだけが有効化にすることが出来るからだ。
- 「広告」や「外部埋め込みパーツ」にGoogleやFacebookやYahooなど、既にログインして広く受け入れられているCookieを用いることに、倫理的な問題がある。
- ユーザーは単に提供される便利なサービスを利用するために、Cookieを受け入れたのであって、外部サイトのWeb訪問履歴を把握されうるということについて、正確な知識を持ち合わせていない。
- (実際にやっているかどうかともかく) その気になれば彼らはGoogle Facebook Yahooのユーザーアカウントと紐付けて、外部サイトの訪問履歴を把握することができる。
- 一般的にアクセスログは記録されるし、IPアドレスや、ブラウザのヘッダの特徴などから、Cookieを使わずとも高い精度でユーザーを識別することは出来る。
- 大手ポータルサイトやSNSが、サードパーティCookieに依存した外部埋め込みパーツを提供し、サードパーティCookie無効では動作しない機能を提供してしまっている。
- 単に実装した人が「サードパーティCookieオフで動作確認をしていないマヌケ」である可能性もあるが、意図的にこういったことをやっている可能性もある。
- 穿った見方をすれば「外部サイトの訪問履歴を収集したいがために」意図的にサードパーティCookieに依存した機能を提供し「Cookieを全て受け入れる設定にしてください」という案内をしている可能性がある。
ブラウザの設定変更を促すことについての問題
- サードパーティCookieがオフでも正常に動作する代替手段があるにも関わらず、実装の簡便さのために、サードパーティCookieに依存した手抜き実装がまかり通ってしまっている。
- サードパーティCookieに依存しない実装をすることが一番良いが、そのような変更を行うことが困難な場合は、リスクを周知した上でサイト毎にサードパーティCookieを許可する設定を案内することが考えられる。
- Safariのようにサイトごとに受け入れ設定を変更することが不可能な場合、ブラウザ全体の設定変更を案内する結果となってしまっている。Safariが悪い。
- IE6以降やSafariにおいては、キチンと理由があってサードパーティCookieをブロックするデフォルト設定を採用しているわけだが、ほとんどのサイトがCookieを全て受け入れる設定に変更するにあたってどのようなリスクがあるのかを的確に説明していない。
- DISQUSのように、提供サービスのドメインのみをCookie許可のホワイトリストに入れるよう案内する方がマシである(Optional:の部分) http://gyazo.com/95c71b727abcb50cf664f147812b0119
まとめ
- サードパーティCookieに依存したWebアプリケーションの歴史と、Web開発者が取るべき対策について書いた。
- mixi足あと機能に関するコメントは差し控えください。私は真面目な話をしています。
Part3ではターゲティング広告におけるトラッキングCookieの利用や、実装上の問題点について書きます。