SameSite属性の付与によるCSRF脆弱性対策

# 概要

CookieにSameSite属性を付与することで、CSRF脆弱性[^1]に対していくらかの防御ができる。

- SameSite属性は`Strict`,`Lax`,`None`の3つの値を取り、設定値により効果の範囲は異なる
  - `Strict`を設定することで、CSRFを防げる。ただし、Webサイトの使いやすさが損なわれる場合がある
  - `Lax`を設定することで、POSTメソッドのリクエストのみを受け付ける処理でCSRFを防げる
  - `None` は従来通りの動作であり、外部サイトからCookieを送信する
  - Webサイトのセキュリティ要件により、設定すべき値が異なる
- SameSite属性は[主要なブラウザすべてで対応されている](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility)

## SameSite属性の付与がCSRF脆弱性への防御とならないケース

- 実行にCookieを必要としない処理
- [Windows 10 RS3（2017 Fall Creators Update）未満のIE 11](https://caniuse.com/#feat=same-site-cookie-attribute)など、SameSite属性をサポートしていないブラウザの利用
- `SameSite=Lax`を設定した場合における、GETメソッドのリクエストを受け付ける処理
- Cookieのスコープ内のWebサイトからの攻撃
- [XSS脆弱性が存在する場合](https://jpcertcc.github.io/OWASPdocuments/CheatSheets/Cross-SiteRequestForgeryPrevention.html#No_Cross-Site_Scripting_.28XSS.29_Vulnerabilities)

[^1]: [一般社団法人JPCERTコーディネーションセンター クロスサイトリクエストフォージェリ(CSRF)とその対策](https://www.jpcert.or.jp/securecoding/AntiCSRF-201510.pdf)

# SameSite=StrictとSameSite=Laxの違い

Cookieを発行してセッション情報を保持するようなWebサイトにおいて、ログイン済みの状態でアクセスした際の挙動が異なる。

## SameSite=Strict

外部サイトからは常にCookieを送信しない。
POSTメソッドだけでなく、GETメソッドでの遷移時(Top Level Navigation)にも送信されなくなる。

このため、ログイン済みのサイトに対して、外部サイトから遷移し直すと、未ログイン状態として処理される。
過度に不便なようにも思えるが、銀行などのWebサイトでは、ログイン済みのページに対する外部サイトからのリンクを望んでいないため、最も適切とされる。

## SameSite=Lax

外部サイトからのGETメソッドでの遷移時(Top Level Navigation)のみ、Cookieを送信する。
これにより、Webサイトの使いやすさとセキュリティを両立させることができる。

外部サイトからのPOSTメソッドや画像読み込み、Ajaxで用いられるXMLHttpRequest(XHR)、iframeでの埋め込みによるリクエストでは、Cookieを送信しない。
このため、該当の処理の実行が**Cookieを必要としており、POSTメソッドのリクエストのみを受け付けるように制御**できていれば、CSRFを防げる。

ただし、[Top Level Navigationとなる攻撃手法への耐性はない](https://blog.jxck.io/entries/2018-10-26/same-site-cookie.html#lax)。
このため、GETメソッドのリクエストを受け付ける処理に対しては、依然として[Token Based Mitigation](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#token-based-mitigation)などの対策が必要となる。

# ミドルウェアでのSameSite属性の付与方法

## Tomcat

Tomcat 9.0.21または8.5.42以降では、`CookieProcessor`を利用して付与することができる。

```xml:META-INF/content.xml
<Context>
 <CookieProcessor sameSiteCookies="strict" />
</Context>
```

- [Apache Tomcat 8 Configuration Reference (8.5.55) - The Cookie Processor Component](https://tomcat.apache.org/tomcat-8.5-doc/config/cookie-processor.html)
- [How to set SameSite Cookie in Tomcat&#39;s Cookie Processor? - Stack Overflow](https://stackoverflow.com/questions/57505939/how-to-set-samesite-cookie-in-tomcats-cookie-processor)

## Apache HTTP Server

```config:Apache&nbsp;HTTP&nbsp;Server
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Strict
```

```config:Apache&nbsp;HTTP&nbsp;Server&nbsp;2.2.4未満
Header set Set-Cookie HttpOnly;Secure;SameSite=Strict
```

- [SameSite / Security Headers to use on your webserver - DEV](https://dev.to/shostarsson/security-headers-to-use-on-your-webserver-3id5#samesite)

# 参考資料

- [HTTP Cookie - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies)
- [SameSite Cookie Attribute / OWASP Cross-Site Request Forgery Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#samesite-cookie-attribute)
- [Cookie の性質を利用した攻撃と Same Site Cookie の効果 | blog.jxck.io](https://blog.jxck.io/entries/2018-10-26/same-site-cookie.html)
- [5.3.7. The SameSite Attribute / draft-ietf-httpbis-rfc6265bis-02 - Cookies: HTTP State Management Mechanism](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.3.7)
- [Chrome 80が密かに呼び寄せる地獄 ～ SameSite属性のデフォルト変更を調べてみた](https://qiita.com/ahera/items/0c8276da6b0bed2b580c)