皆さんは Cookie の SameSite 属性について意識したことはあるでしょうか?
恥ずかしながら私はこれまで SameSite 属性について知りませんでした。 😅
SameSite 属性とは?
いくつか記事を当たってみた感じ 2016 年頃から主要ブラウザに実装されはじめたようです。
値は Strict, Lax, None が指定出来、何も設定しないとデフォルトで Lax が適用されるらしく、
特別な理由がない限りは Lax で問題ないらしく、
普通はあまり意識する必要はなさそうです。
SameSite 属性のそれぞれの値の動作
値 | 動作 |
---|---|
Strict | クロスサイトの cookie 送信を不許可。 サイトを直接訪問した時にだけ cookie を送信 直接アクセスのみなので他サイトからのリンクで訪問した場合も cookie が送信されません。 Session でログイン管理している場合は弊害がありそうですね。 |
Lax | クロスサイトの cookie 送信を不許可。 Strict と違い、外部リンクからのアクセスの場合も cookie を送信する。 (iframe での表示, 外部サイトからの POST, 外部サイトからの XMLHttpRequest, etc. では cookie を送信しない。) |
None | クロスサイトの cookie 送信を許可。 広告トラッキングなどで利用される。 |
SameSite 属性はなんのために存在するか
主に、CSRF(クロスサイトリクエストフォージェリ)対策のため導入されたらしい。
CSRF とはどんな攻撃だったか思い出す
【前提】
- 利用者がとある サイトA にログイン済み
- サイトAは Session によってログイン管理している
【攻撃手順】
- 悪意のある サイトX に利用者を誘導。メールで URL を踏ませるなど。
- サイトX から サイトA に悪意のある POST リクエストを送信
(この時 cookie が送信されてしまうと サイトA からは正規のリクエストとして処理されてしまう。) - 利用者が意図しない操作が サイトA で行われてしまう
SameSite 属性が、Strict や Lax では Cookie が送信されないので、CSRF 攻撃は失敗するので安心ですね。
その他の CSRF 対策
CSRF トークンを事前に Session に保存しておき、Form に hidden で CSRF トークンを埋め込み、リクエストを処理するタイミングで CSRF トークンを突き合わせて利用者による正規の操作か判別するという手法もありますね。
私が昔、PHP フレームワークの Laravel と jQuery を使って Web サイト制作などの仕事をしている時は、CSRF 対策といえばこれでした。
SameSite 属性があるから絶対安心というわけではない
気を付けたいのは、SameSite 属性を実装していないブラウザを利用者が使っていたり、主要ブラウザでも古いバージョンを使っている場合は、CSRF 脆弱性が発生してしまうので、CSRF トークンによる対策も同時に行った方がより安全ということらしい。