そのクロスドメインでcookie使えてますか？


#はじめに
クロスドメイン(複数のドメインをまたぐ)でcookieをiframeを使用してセットしようとした時、想像以上に歴史の深い問題にぶち当たったので調べたことをメモしてみる

#何がしたかったか

「異なるドメインのcookieをiframeでセットしてデータの引き渡しをしたい」文章で書くと非常に要件は簡単だが、図にしてみた。

![iframe_cookie.png](https://qiita-image-store.s3.amazonaws.com/0/8726/ff8598cf-c33c-d727-7244-3b2d6d3737ac.png "iframe_cookie.png")


###Cookieの決まり事

[RFC6265](http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html)

<!-- リンク切れ -->

>
* １クッキーあたり，少なくとも 4096 バイト（クッキーの名前, 値, 属性 の長さの総和で）
* １ドメインあたり，少なくとも 50 個のクッキー
* 全部で少なくとも 3000 個のクッキー

[7.1. 第三者主体（ third-party ）によるクッキー](
http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html#third-party-cookies)

>
一部の UA は第三者主体クッキーのふるまいを制約する。 例えば，これらの UA の一部は、第三者主体へ向けたリクエストの中の Cookie ヘッダの送信を拒否する。 他のものは、第三者主体へのリクエストに対する応答の中の Set-Cookie ヘッダの処理を拒否する。

**これによりhoge.comはvar.comのcookieにアクセス出来ない。**

そのため、hoge.comにいる間に、var.comのcookieを生成してhoge.comとvar.comで同じ値を使用できるように考えてみた。

#ハマったこと


##1.&アンパサンドがiframeのsrcに使えない

iframeのsrcに渡すURLにクエリパラメータを使用すると `IEでは` XSSと判定される

```html
<iframe src="hoge.com?ie=have&many=problem"></iframe>
```

[ここ](http://www.squarefree.com/securitytips/web-developers.html)によると `Text in HTML and HTML attributes: escape & < > " ' as &amp; &lt; &gt; &quot; &#39;` ということで&もエスケープしないといけないらしい。


##2.IEの場合にdocument.writeでiframeが生成できない 

Chrome / Firefoxなどでは下記の書き方でiframeを展開してくれるが、IEだと動作してくれない。
[iframe 要素内に動的に script 要素を出力すると Internet Explorer が応答なしになる場合がある](http://support.microsoft.com/kb/2982981/ja?wa=wsignin1.0)

```html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible"/>
</head>
<body>
<script type="text/javascript">
window.onload = function() {
    var iframe = document.createElement("iframe");
    document.body.appendChild(iframe);
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    doc.write("<script src='script.js'>\x3c/script>");
    doc.close();
}
</script>
</body>
</html>
```

##3.IEがcookieをセットしてくれない

###[P3P](http://www.iajapan.org/trans2japanese/w3c/rec-p3p-20020416j.html#compact_policy_vocabulary)(The Platform for Privacy Preferences)


####IEにも対応したP3Pの設定を行う為には（一般的に）
1. P3Pポリシーを作成する
2. P3Pポリシー参照ファイルを作成して、周知の存在場所(/w3c/p3p.xml)に置く
3. P3Pポリシーからコンパクトポリシーを作成してHTTPヘッダで出力するようにする
の設定を行います。

####コンパクトポリシーとは

>
コンパクト ポリシーは、P3P ポリシー全体を要約したものです。コンパクト ポリシーはパフォーマンスを最適化するためのもので、これにより、ユーザー エージェントで、ポリシーの適用に関して迅速な、即座の決定が可能となります。P3P version 1 のコンパクト ポリシーに含まれているのは、cookie に関連するポリシー情報のみです。P3P コンパクト ポリシーの元となっている P3P ポリシー全体は、cookie 内に格納されているデータと cookie が参照している Web サイトにあるデータの両方に適用されます。コンパクト ポリシーは、P3P ポリシー全体で参照されているすべての cookie を表している必要があります。
P3P のコンパクト ポリシーは、ユーザー エージェントとサーバーのどちらに対しても任意のものであることに注意してください。ユーザー エージェントで、ユーザーのプライバシー基本設定を適用するために必要な情報をコンパクト ポリシーから入手できない場合、ポリシー全体を取得する必要があります。

**ポリシーの一例**

```
compact-access =
"NOI" | ; for <nonident/>
"ALL" | ; for <all/>
"CAO" | ; for <contact-and-other/>
"IDC" | ; for <ident-contact/>
"OTI" | ; for <other-ident/>
"NON"   ; for <none/>
```

IE向けにどのサイトのこれを設定しているのか。。。？


###すごく大変だけど有名なサイトはどうしてるのか？

####facebookのp3p

https://www.facebook.com/help/327993273962160/

>
P3Pを策定した組織、W3C (World Wide Web Consortium)は、最新のほとんどのウェブブラウザがP3Pを完全にはサポートしていないことから、数年前にこの標準化作業を中断しました。結果として、現在ではP3P規格は時代遅れとなり、現在ウェブサイトで使用されている技術を反映しておらず、そのため、今ではほとんどのウェブサイトはP3Pポリシーを使用していません。

ヘッダーを確認してみる

```
$ curl -LI http://www.facebook.com
P3P: CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"
```

####googleのp3p

https://support.google.com/accounts/answer/151657?hl=ja

>
ブラウザの中には P3P プロトコル（リンク先は英語）によるプライバシー ポリシーを使用するようサードパーティ Cookie に求めるものがありますが、P3P プロトコルはこのような状況を想定して設計されてはいません。

ヘッダーを確認してみる


```
$ curl -LI http://www.google.co.jp
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."
```

**お？使わないってオプションがあるのか！？**

####念のため色々なところのp3pヘッダを見てみる

http://www.yahoo.co.jp

```
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p_jp.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
```

https://www.linkedin.com

```
P3P: CP="CAO CUR ADM DEV PSA PSD OUR"
```

http://www.microsoft.com/ja-jp/default.aspx

```
P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
```

さすがMicrosoftは色々設定してある...

##4.X-Frame-optionによりiframeを止められる

[クリッキングジャック攻撃](https://www.jpcert.or.jp/tips/2010/wr103601.html)を防止するために[X-Frame-Options レスポンスヘッダ](https://developer.mozilla.org/ja/docs/HTTP/X-Frame-Options)の設定が出来るのですが、コレによりiframeそのものが使用できない。

再度ヘッダを確認してみる。

```
$ curl -LI https://www.google.com
X-Frame-Options: SAMEORIGIN
```

|オプション|内容|
|---|---|
|DENY|サイト側の意図に関わらず、ページをフレーム内に表示することはできない|
|SAMEORIGIN|自身と生成元が同じフレーム内に限り、ページを表示することができる|
|ALLOW-FROM uri|指定された生成元に限り、ページをフレーム内に表示できる|


#まとめ

3rd party cookieについて昔から問題になっていることと、さらにセキュリティによる対策が何重にもなってきているためきちんと理解してないと、やりたいことだけでは設計だけではうまくいかないなとつくづく思いました