Help us understand the problem. What is going on with this article?

Chrome 80が密かに呼び寄せる地獄 ~ SameSite属性のデフォルト変更を調べてみた

Chrome 80で何が変わるのか

2020年2月4日にGoogle Chrome 80がリリース予定されています。
Google Developersの 新しい Cookie 設定 SameSite=None; Secure の準備を始めましょう の記事にあるように、
このバージョンから以下のように変わります。
【追記】SameSiteのデフォルト変更が適用されるのは2月17日の週になりました。
【更に追記】2月17日の月曜日はアメリカでは祝日であり、そこは避けられるとのことです。(SameSite Updates 2/3更新内容より)

  • Chrome 79まで
    • SameSiteが未指定の場合 None と同じになる。
  • Chrome 80から
    • SameSiteが未指定の場合 Lax と同じになる。
    • SameSiteにNone を指定する場合は、Secure属性が必須となる。

※Secure属性とは、HTTPS上だけで読み取りができるCookieです。

なぜ変わるのか

先のGoogle Developersのブログに書いてあることをざっくりまとめると以下のようになります。

  • SameSiteを使えるようにした。
    LaxStrictを指定すればCSRFは防げる。
  • でも誰も使っていないので大多数のサイトにCSRFの脅威がある。
  • ならばデフォルトをLaxにしてしまえ。そうすれば大多数のサイトはCSRFについて安全だ。
  • クロスサイトで使いたきゃ明示的にNoneを指定した上でSecure属性を付ければいい。

SameSiteとは?

CookieのSameSite属性はStrict Lax Noneの3つの値を取ります。
値により、クロスサイトでの通信でCookieの送信を制御します。

設定値

  • Aサイト…Cookieを発行したサイト
  • Bサイト…Aとは別ドメインのサイト
設定値 効果
Strict Aサイトに対し、Bサイトからどのようなリクエストがあっても、発行したサイトでCookieヘッダーに含めない (Cookieを使用しない)
Lax Chrome 80からのデフォルト値。
Aサイトに対し、BサイトからのPOSTや画像読み込み、XHR、iframeでのリクエストでは発行したサイトでCookieヘッダーに含めない (Cookieを使用しない)
GETであればCookieヘッダーに含める (Cookieを使用する)
None Chrome 79以下や他ブラウザのデフォルト値。
Chrome 80からこの値を設定する場合、Secure属性も必須となる。
Aサイトに対し、Bサイトからどのようなリクエストがあっても、発行したサイトでCookieヘッダーに含める (Cookieを使用する)

図にすると以下のようになります。

Strict

外部サイトからのアクセスではCookieを送らない。
image.png

Lax

外部サイトからのアクセスはGETリクエストのときだけCookieを送る。
image.png

None

従来通りの動き。
image.png
【追記】なおChrome 80以降でSecure属性を付けずSameSite=Noneを指定した場合、set-cookie自体が無効になります。

セキュリティ上の効果

CSRF対策になります。

CSRF (クロスサイト・リクエスト・フォージェリ) とは、
WEBサイトがユーザー本人の意図した動作であることを検証していないためにおこる脆弱です。

  • たとえば会員の退会ページを https://example.com/mypage/delete/で用意し、
    ボタン操作でsubmit=1が送信されて退会処理が実行される仕様の場合、
    パラメータが誰でもわかるので、外部に用意された悪意のあるフォームからも
    同じパラメータで送信することができます。
  • ログイン済みの会員ユーザーがその状態で悪意のあるフォームを操作してしまうと
    意図せず退会されていまいます。 image.png

CSRF対策でよくある方法は、
本人しかわからないパラメータ(ランダム文字列など)を発行して一緒に送信することで
ボタン操作が本人にひもづく動作であることを確認しています。

  • SameSite (Lax or Strict)の場合、ユーザー本人にひもづかないようにしてしまうことでCSRF対策としています。
    ユーザー本人かどうかWEBサイトが知るにはCookieに識別情報に持つことで実現しているのですが、
    外部の悪意のあるフォームなどからの送信でそのCookieを付けないようにすれば
    WEBから見ればログインしていない人が退会しようとしていますので、エラーとなります。 image.png

このようにCSRFに一定の効果があることから、Chrome 80からデフォルトをLaxとして扱うようになります。

対策

特に何もしなくても大丈夫なサイト

  • 特にCookieを発行していないサイト。
  • 外部からPOSTや画像のロード、XHR、iframeでの呼び出しが無いサイト。
  • 外部からPOSTなどされてくるけど、特にCookieが読み込めなくても問題ないサイト。

上記以外のサイトでは対策が必要になりそう

SameSite=Noneを付けた上でSecure属性を付与をすることで、従来通りの動作になります。
Secure属性を付けるためにはHTTPSである必要があるため、HTTPのサイトは証明書を取得しSSL/TLSに対応する必要があります。

画像やXHR、iframeなどを使ってユーザートラッキングのCookieを発行しているサイト
  • いわゆるサードパーティCookieを発行しているサイト。 image.png
ECやサービス系の会員サイトで、決済や認証などで外部サービスを利用し、外部サイトからPOSTで戻ってくるサイト
  • 決済でいえばクレジットカードの3Dセキュアが本人認証のためにイシュアのサイトにリダイレクトし、
    戻るときにPOSTしている可能性があります。
  • ユーザー識別をCookieで行っている場合、外部サイトから戻ってきたときにユーザーが識別できなくなります。
    つまり大抵はこういった外部サービスとの連携処理がエラーになります
    ECサイトであれば注文ができないことになるので損失が出る可能性があります。
  • ユーザー識別CookieはファーストパーティCookieですが、SameSiteは特にファーストパーティ、サードパーティかは区別しません。
    「サードパーティCookieだけだから関係ないんじゃない?」と誤解している人も周りに多くいました…。 image.png

テスト方法

  • Chrome 79以下では chrome://flags/ を開き、以下を Enabled にしてブラウザを再起動します。
    • SameSite by default cookies
    • Cookies without SameSite must be secure image.png

注意点

  • ただしChrome 78, 79では想定通り動いたり動かなかったりするような動作をします。
  • これはChrome 78以降は「POST+Lax」のとき介入サポートとして、
    Laxであっても2分間はCookieを送信するというChrome独自の動作によるものです。
  • この2分間の介入サポートは将来的に削除され、本来のLaxの動きになる予定です。
  • テストする際には2分待ちましょう。
    コマンドライン--enable-features=ShortLaxAllowUnsafeThresholdを付けると変えられるみたいです。(未検証)
  • Chrome Platform Status - Cookies default to SameSite=Lax より。

この2分間という介入サポート、かえって混乱を招くのでは…(ボソッ
【追記】2分間について補足を追加しました

まとめ

  • 2020年2月4日リリース予定のChrome 80からSameSite属性のないCookieはLaxになる。
  • 外部からPOSTや画像のロード、XHR、iframeでの呼び出しでCookieは付かなくなる。
  • つまりCookieを使った会員識別をしている際、外部からアクセスされると識別できなくなる。
  • サードパーティCookieを使っているサービスのほか、ファーストパーティCookieでも
    ECやサービス系の会員サイトで外部と画面上で連携している場合は早急に確認と対策が必要。

追記

2020/02/02

The Chromium Projects - SameSite Updates に1/30に更新された内容によると
2/4のStableリリースと同時に適用されず、2/17の週からごく一部のユーザーに適用され、段階的に適用を拡大するようです。
(Antoine Bourlonさん、情報ありがとうございます)

2週後ろ倒しになり、なおかつ段階的な適用拡大ということで大きな混乱は避けられそうです…。

The SameSite-by-default and SameSite=None-requires-Secure behaviors will begin rolling out to Chrome 80 Stable for an initial limited population starting the week of February 17, 2020. We will be closely monitoring and evaluating ecosystem impact from this initial limited phase through gradually increasing rollouts.

2020/02/03

iOS 12とmacOS 10.14のSafariでは
SameSiteにNoneもしくは無効な値を指定するとStrictとして扱われてしまいます
( @keitaromiura-link さん、情報ありがとうございます)

このためChrome 80以降への対応でNoneを付けつつ、これらのSafariでも動作させたい場合は
こちらのコメントにあるように正規表現でユーザーエージェントで判定し出し分ける方法があります。
コメントの例ですと下記にマッチするものはSameSiteを送信しない、としています。(あくまで例なのでよく検証ください)

^.*iPhone; CPU iPhone OS 1[0-2].*$
^.*iPad; CPU OS 1[0-2].*$
^.*iPod touch; CPU iPhone OS 1[0-2].*$
^.*Macintosh; Intel Mac OS X.*Version\/1[0-2].*Safari.*$

出し分けをしないという方法もありますが、StatCounterを見ると2020年2月現在で

と、まだまだシェアは多少あり、無視はしにくい印象です。
Strictとして扱われてしまうと単なるGETでの遷移でもCookieが付かなくなり影響が大きいため、
完全でないですが、ある程度緩和が期待できるこういった施策を入れるのが良さそうです。

2020/02/06

ユーザーエージェント判定について

NoneがStrictになるブラウザのユーザーエージェント判定を含め、
Noneに互換性のないブラウザ(ユーザーエージェント)をざっくり和訳&まとめました。
判定方法など詳しくはSameSite=None: Known Incompatible Clientsをご覧ください。
またそのページにもある通り、完全なものではなく、しっかりと動作検証する必要があります。
@sakai さん、情報ありがとうございます )

ブラウザ 概要
Chrome 51以上~66以下のブラウザ Noneを指定すると拒否する。
Chromium由来の古いバージョンのブラウザーとAndroid WebViewも同様
これは当時Noneが仕様に無かったから。
なお51未満は無視されるのでNoneと同じ動作になる。
AndroidのUC Browser 12.13.2未満 Noneを指定すると拒否する。
こちらも当時Noneが仕様に無かった。
macOS 10.14のSafariと組み込みブラウザ
iOS 12のすべてのバージョンのブラウザ
2020/02/03の追記と同じ。
Secure属性を付けずにSameSite=Noneを指定した場合の動き

Secure属性を付けずにSameSite=Noneを指定した場合、set-cookieヘッダー自体が無効となります。
すなわちCookie自体を持つことができません。

Chrome 80 (flagsで設定変更した上で) で確認したところ、F12を押して出てくるDevToolsのNetworkのHeadersで見てみると、
set-cookieの行末に⚠アイコンが表示されSameSite=NoneのときはSecureが必須である旨の警告が表示されます。
image.png
ほかSameSite未指定の場合のサードパーティCookie発行でも警告がでます。
image.png

またChrome 80ではDevToolsのNetworkに Only show requests with SameSite issues のチェックが追加されました。
ここにチェックを入れると、上記のような⚠アイコンのもののみにフィルタされます。

image.png

2020/02/09

SameSite無しのCookie発行後、2分間はPOSTでも送信できる点について

2020 年 2 月の SameSite Cookie の変更: 知っておくべきこと より、
2分間はPOST等でもCookieを送れる仕様について、
認証の過程でウェブサイトと認証の連携先(サードパーティプロバイダ)とでCookieを渡すときに
ログインに影響がないように配慮されたものとのことです。

2分である理由は書いていませんが、HTTPの接続タイムアウトが120秒であることが多いからでしょうか。
とはいえログイン時にユーザー識別Cookieを発行し
その場で外部と連携して2分以内に戻ってくる場合のみ有効
で、
ログイン前からユーザーセッションをCookieで管理をしていたり、
3Dセキュアのように2分で戻るかわからない場合には無効です。

また将来的には廃止されるとのことなので、
現在この仕様でうまく動いていてもいずれ対応が必要になってきます。

Support for this intervention ("Lax + POST") will be removed in the future.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした