結論(CookieのSameSite属性)
CookieのSameSite属性とは、Set-Cookieに付ける属性で、別のサイトから始まったリクエストにそのCookieを付けて送るかをブラウザに指示するものです。値はStrict・Lax・Noneの3つで、適切に設定するとクロスサイト・リクエスト・フォージェリ(CSRF)の被害を大きく抑えられます。未指定時の扱いはブラウザによって異なるため、Cookieの目的に応じた値を明示することが求められます。
この記事のポイント
- Strictは同一サイトからのリクエストだけ、Laxは加えて別サイトからのリンク遷移(GET等)、Noneはすべてのリクエストで送信されます。
- ここでの「サイト」は登録可能ドメイン(eTLD+1)とスキームの組み合わせで、同じドメインのサブドメイン同士は同一サイトです。
- Chromeは80以降SameSite未指定をLax扱いにしていますが、ブラウザ間で既定の動作はそろっていないため明示が必要です。
- SameSiteはCSRF対策の一部にすぎず、CSRFトークンや再認証との多層防御が前提です。
- 診断ではSameSiteが無い、または不正な値のCookieが1件でもあれば△(重み2×0.45)です。
| 診断項目名 | CookieのSameSite属性 |
|---|---|
| 項目ID | cookie.samesite |
| 分類 | Cookie・セッション管理 |
| 重大度・配点の重み | 中(medium) 重み 2 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V3.3.2(Level 2)/OWASP WSTG-SESS-02(Testing for Cookies Attributes)・WSTG-SESS-05(Testing for Cross Site Request Forgery)/OWASP Session Management Cheat Sheet/draft-ietf-httpbis-rfc6265bis/CWE-1275(Sensitive Cookie with Improper SameSite Attribute)/CWE-352(CSRF) |
CookieのSameSite属性とは
CookieのSameSite属性とは、サーバーが Set-Cookie ヘッダーで発行するCookieに付ける属性で、「別のサイトから始まったリクエストに、このCookieを付けて送るか」をブラウザに指示するものです。値は Strict・Lax・None のいずれかです。
Set-Cookie: PHPSESSID=…; path=/; secure; HttpOnly; SameSite=Lax
SameSite属性を適切に設定すると、悪意あるサイトが利用者のブラウザに勝手にリクエストを送らせ、ログイン中の権限で処理を実行させる クロスサイト・リクエスト・フォージェリ(CSRF) の被害を大きく抑えられます。
OWASP ASVS 5.0.0 は V3.3.2(Level 2)で「各Cookieの SameSite 属性値が、Cookieの目的に応じて設定されていること」を求めています。OWASP Session Management Cheat Sheet は、セッションCookieには Strict(推奨)または Lax を明示し、ブラウザの既定値に頼らないよう勧めています。
SameSiteのStrict・Lax・Noneの違い
値ごとの送信範囲
| 値 | 送信される場面 |
|---|---|
Strict | Cookieを設定したサイトと同じサイトから始まったリクエストだけ |
Lax | 同一サイトのリクエストに加え、別サイトからのトップレベル遷移(リンクのクリック等)で、GETなど安全なメソッドの場合 |
None | 別サイトからのリクエストを含むすべて(Secure が必須) |
「同じサイト」の範囲
ここでの「サイト」は、登録可能ドメイン(eTLD+1)とスキームの組み合わせです。www.city.example.lg.jp と shinsei.city.example.lg.jp は同じサイトとみなされる一方、Public Suffix Listで区切られる別ドメイン(例:異なる github.io サブドメイン)は別サイトです。このため、同一サイト内のサブドメインからの攻撃は SameSite では防げません。
SameSite属性が無い場合の既定値
Chrome は バージョン80(2020年)以降、SameSite が無いCookieを Lax として扱っています(トップレベルのPOSTについては、設定から2分以内に限り送信を許す一時的な緩和措置があります)。MDNは「一部のブラウザは SameSite 未指定時に Lax を既定値とする」と説明しており、ブラウザ間で既定の動作がそろっているわけではありません。つまり属性を省略すると、利用者のブラウザによって保護の有無が変わります。そのため、目的に応じた値を 明示 することが求められます。
自治体サイトでSameSiteの値を選ぶ考え方
自治体公式サイトでは、トップページや記事ページ自体はログイン不要で、Cookieは主に次の用途で発行されます。
- CMSや電子申請・施設予約システムのセッション
- ロードバランサーの振り分け(スティッキーセッション)
- 文字サイズ・背景色・言語切替などのアクセシビリティ設定
多くの場合、セッションCookieは Lax、表示設定も Lax で問題ありません。ロードバランサーのCookieは、製品によってクロスサイト用(SameSite=None; Secure)と通常用の2種類が発行されることがあり、通常用に属性が無いとこの項目が△になります。製品の設定で属性を付けられるかを確認してください。
CookieのSameSite属性についてよくある誤解
- 「SameSiteを付ければCSRF対策は完了」:同一サイト内(他のサブドメイン)からの攻撃、GETで状態を変更する実装、
Laxで許されるトップレベル遷移などは防げません。ASVSやIPAが求めるCSRFトークン、再認証、送信元確認と組み合わせる「多層防御」の一部です。IPA「安全なウェブサイトの作り方」のCSRF対策(6-(i))は、トークン・再認証・Refererの確認を根本的解決としています。フォームのトークンの有無は「POSTフォームのCSRF対策兆候」で確認します。 - 「Strictが常に最善」:
Strictでは、メールや他サイトのリンクから訪れたときにログイン状態が引き継がれず、利用者が再ログインを求められます。セッションCookieはLaxで運用し、重要操作の確認画面だけ別のStrictCookieで保護するといった設計もあります。 - 「Noneは危険な値」:外部サイトに埋め込まれる仕組み(埋め込み型の予約ウィジェット、SSO連携など)では
None; Secureが必要な場合があります。用途に合っていれば正しい設定です。
CookieのSameSite属性の診断基準(セキュリティAIチェッカー)
取得方法
- トップページ(転送後の最終応答)と、トップページの同一オリジンリンクから選んだ最大4ページ(ログイン・管理・マイページ系を優先)を GETのみ で取得します。ログアウト・削除系のURLや静的ファイルは巡回しません。
- 各最終応答の
Set-Cookieを1件ずつ収集します(転送途中の応答のCookieは観測しません)。 - 削除用のSet-Cookie(
Max-Age=0以下、または過去のExpires)は除外します。 - 有効なCookieが0件なら対象外(na)です。
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| ○ 問題なし(pass) | 観測した有効なCookieすべてに SameSite=Lax・Strict・None のいずれかが明示されている | 重み2 × 1.00 |
| △ 要確認(warn) | SameSite が無い、または上記以外の値(綴り誤り等)のCookieが1件以上ある | 重み2 × 0.45 |
| 対象外(na) | 有効なCookieを観測できなかった(結果には重大度medium・重み2のまま記録) | 得点計算から除外 |
| × 要改善(fail) | 使用しません | ― |
- 値は大文字小文字を区別せず、
=の前後の空白を許容して判定します。SameSite=Lax_のような不正な値は「未設定」と同じ扱いです(ブラウザも不正な値は無視します)。 - この項目は「明示しているか」を評価します。
Noneを使う場合のSecure必須要件は「SameSite=NoneとSecureの組み合わせ」で評価します。 - 値が用途に合っているか(たとえばセッションCookieに
Noneを使う必要があるか)は公開情報からは判断できないため、×ではなく△としています。
自治体サイトでの判定例
| 観測したSet-Cookie | 判定 |
|---|---|
PHPSESSID=…; path=/; secure; HttpOnly; SameSite=Lax | ○ |
AWSALBCORS=…; Path=/; SameSite=None; Secure と AWSALB=…; Path=/(SameSiteなし) | △ |
JSESSIONID=…; Path=/; Secure; HttpOnly(SameSiteなし) | △ |
| Cookieの発行なし | 対象外 |
SameSite属性がないとどんなリスクがあるか
- CSRFによる意図しない操作:ログイン中の利用者が攻撃者のページを開いただけで、裏で自治体サイトへのフォーム送信が行われ、登録情報の変更、施設予約の取消、メールマガジンの登録変更などが実行されます(CWE-352)。
SameSiteが無いと、ブラウザによってはこのリクエストにセッションCookieが付与されます。 - ログインCSRF・クリックジャッキングとの組み合わせ:ASVSも
SameSiteを、UIリドレス攻撃(クリックジャッキング)やブラウザ経由のリクエスト偽造の影響を抑える手段として位置付けています。 - ブラウザ差による保護の不均一:既定値に依存すると、ある利用者は守られ、別の利用者は守られないという状態になり、検証や説明が難しくなります(CWE-1275)。
CookieのSameSite属性の設定方法(PHP・Apache・nginx・IIS・Next.js)
PHP
<?php
// php.ini / .user.ini(PHP 7.3以降)
// session.cookie_samesite = "Lax"
session_set_cookie_params([
'path' => '/', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax',
]);
session_start();
PHP 7.2以前では samesite オプションが無いため、PHPのバージョンアップが基本対応です。
Apache(補助策)
<IfModule mod_headers.c>
Header always edit Set-Cookie "(?i)^(?!.*;\s*samesite\s*=)(.*)$" "$1; SameSite=Lax"
Header edit Set-Cookie "(?i)^(?!.*;\s*samesite\s*=)(.*)$" "$1; SameSite=Lax"
</IfModule>
Apacheは応答ヘッダーを2つの内部表で管理しており、CGI・FastCGI(mod_proxy_fcgi)由来の Set-Cookie は always 側、それ以外の多くは既定(onsuccess)側に入るため、両方の条件で記述します。
nginx(リバースプロキシ)
proxy_cookie_flags ~ samesite=lax;
IIS(ASP.NET 4.7.2以降)
<system.web>
<sessionState cookieSameSite="Lax" />
<httpCookies sameSite="Lax" requireSSL="true" httpOnlyCookies="true" />
</system.web>
Next.js(Vercel)
import { cookies } from "next/headers";
(await cookies()).set("session", token, { sameSite: "lax", secure: true, httpOnly: true, path: "/" });
段階的な導入と注意点
- Cookieを用途ごとに分類します:①セッション・認証(
LaxまたはStrict)、②表示設定など(Lax)、③外部サイトからの埋め込み・SSO・決済の戻りで必要なもの(None; Secure)。 - 外部の決済代行・SSO(SAML等)から POSTで戻ってくる 画面がある場合、
LaxにするとセッションCookieが送られず、ログイン状態が失われることがあります。該当する画面はテスト環境で必ず確認してください。 - Webサーバーでの一律付与は③の用途を壊す可能性があるため、アプリケーション側での個別設定を優先します。
- 確認します。
curl -sSI https://www.city.example.lg.jp/ | grep -i '^set-cookie'
SameSiteに加え、状態を変更する処理にはCSRFトークンの検証を実装してください。
HTTPSでのみ送信させる「CookieのSecure属性」、JavaScriptからの読み取りを防ぐ「CookieのHttpOnly属性」とあわせて設定するのが基本です。
よくある質問(FAQ)
SameSiteのStrictとLaxはどちらを使えばよいですか?
自治体サイトでは、セッションCookie・表示設定ともLaxで問題ないことが多いです。Strictはメールや他サイトのリンクから訪れたときにログイン状態が引き継がれず再ログインが必要になるため、重要操作の確認画面だけ別のStrict Cookieで保護する設計もあります。OWASPのCheat SheetはセッションCookieにStrict(推奨)またはLaxの明示を勧めています。
SameSiteを指定しないとどうなりますか?
Chromeはバージョン80(2020年)以降、SameSiteが無いCookieをLaxとして扱っています。ただしMDNは「一部のブラウザ」がLaxを既定値にすると説明しており、ブラウザ間で動作はそろっていません。利用者のブラウザによって保護の有無が変わるため、値を明示してください。
SameSiteを付ければCSRF対策は完了ですか?
完了しません。同一サイト内の別サブドメインからの攻撃、GETで状態を変更する実装、Laxで許されるトップレベル遷移などは防げません。IPAが根本的解決とするCSRFトークン・再認証・Refererの確認と組み合わせてください。
SameSite=Noneは使ってはいけない値ですか?
外部サイトに埋め込まれる予約ウィジェットやSSO連携など、サイトをまたぐ送信が必要な用途ではSameSite=None; Secureが正しい設定です。Noneを使う場合のSecure必須要件は「SameSite=NoneとSecureの組み合わせ」の項目で評価します。
SameSite=Laxにしたら外部決済やSSOから戻ったときにログインが切れました。なぜですか?
外部の決済代行やSAML等のSSOからPOSTで戻ってくる画面では、LaxだとクロスサイトのリクエストになるためセッションCookieが送られず、ログイン状態が失われることがあります。該当画面はテスト環境で必ず確認し、必要なCookieだけNone; Secureにするなどアプリケーション側で個別に設定します。
SameSite=Lax_ のような値はどう扱われますか?
Lax・Strict・None以外の不正な値はブラウザに無視されるため、診断でも「未設定」と同じ扱いで△になります。値は大文字小文字を区別せず、=の前後の空白は許容して判定します。
この項目を含む127項目を、URLを入れるだけで無料診断します。