本文へスキップ
サイト総合診断

Cookie の Secure・HttpOnly・SameSite 属性

Cookie の Secure・HttpOnly・SameSite 属性は、セッション Cookie を盗難やなりすましから守るための設定です。Secure は平文送信を防ぎ、HttpOnly は JavaScript からの読み取りを封じ、SameSite はクロスサイトからの送信を制御します。セッション Cookie には HttpOnly・Secure・SameSite=Lax の 3 つをまとめて付けるのが基本です。

執筆: 公開:

Cookie の属性とは何ですか?

Cookie の属性は、Set-Cookie ヘッダーで各 Cookie に付ける「取り扱いのルール」です。Secure・HttpOnly・SameSite の 3 つがセキュリティの要で、それぞれ送信経路・読み取り可否・クロスサイト送信を制御します。属性を付け忘れた Cookie は既定の緩い挙動になり、セッション ID を盗まれる隙になります。

Cookie は、ログイン状態を保つセッション ID などをブラウザに保存し、リクエストのたびにサーバーへ送り返す仕組みです。 この Cookie が第三者に渡ると、パスワードを知らなくてもそのままログイン中の利用者になりすませます。 だからこそ、Cookie を「いつ・どこへ・誰に読めるか」を絞る属性が重要になります。中でも守りの中心は次の 3 つです。

セキュリティに効く 3 つの Cookie 属性と、防ぐ脅威
属性防ぐ脅威仕組み
Secure通信の盗聴(平文送信)HTTPS 接続のときだけ Cookie を送る
HttpOnlyXSS によるセッション窃取JavaScript の document.cookie から読めなくする
SameSiteCSRF(クロスサイトの偽リクエスト)クロスサイトのリクエストに Cookie を付けない

これらはすべて、サーバーが返す Set-Cookie ヘッダーに書きます。付け忘れた属性は緩い既定値で扱われるため、「書いていない=安全側」ではない点に注意してください。まずは基本形を見ます。

セッション Cookie の基本形 / 属性なしの NG 例
# セッション Cookie の基本形: 3 属性をまとめて付ける
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/

# 属性なし(NG)。http でも送られ、JS から読め、クロスサイトでも送られる
Set-Cookie: session=abc123

Secure 属性は何を防ぎますか?

Secure 属性を付けた Cookie は、HTTPS 接続のときだけブラウザから送信されます。付けないと http の平文通信でも送られ、同じ回線を盗聴した第三者にセッション ID を読み取られます。HTTPS のサイトでも Secure が無ければ、http へ誘導する攻撃で Cookie が漏れるため、セッション Cookie には必須です。

Secure を付けた Cookie は、HTTPS のときだけ送信されます。付けないと、http の平文通信でも Cookie が流れ、 公衆 Wi-Fi など同じ回線を盗聴した第三者に、セッション ID を丸ごと読み取られます。 「うちは全ページ HTTPS だから大丈夫」と思っても、攻撃者が利用者を一度だけ http のリンクへ誘導できれば、 Secure の無い Cookie はその平文リクエストに付いて漏れてしまいます。

そのため、サイト全体の HTTPS 化(HSTS による HTTPS の強制を含む)と、 Cookie 側の Secure両方そろって初めて意味を持ちます。どちらか一方では、平文送信の穴が残ります。

HttpOnly 属性はなぜ必要ですか?

HttpOnly を付けると、その Cookie は JavaScript の document.cookie から読めなくなります。これは XSS(スクリプト混入)でセッション ID を盗み出す攻撃を防ぐためです。XSS を完全に塞ぐのは難しく、万一スクリプトが実行されてもセッション Cookie だけは盗ませない、という多層防御の一枚として効きます。

HttpOnly を付けると、その Cookie は document.cookie から一切読めなくなります。 これは XSS(Cross-Site Scripting)でセッション ID を盗む典型的な手口を封じるためのものです。 攻撃者が投稿欄などから <script> を紛れ込ませ、その中で document.cookie を外部へ送ろうとしても、 HttpOnly の Cookie は最初から読めないので盗めません。

SameSite の Strict・Lax・None はどう違いますか?

SameSite はクロスサイトのリクエストに Cookie を付けるかを決めます。Strict は同一サイト内の遷移のみ、Lax は既定で外部からのトップレベル GET 遷移だけ許可、None は常に送るがクロスサイトでは Secure が必須です。Lax 以上にすると、外部サイトからの偽リクエストに Cookie が付かず、CSRF の緩和になります。

SameSite は、別サイトから自分のサイトへ送られるリクエストに Cookie を付けるかを制御します。 これが効くのは CSRF(Cross-Site Request Forgery)— 攻撃者のページに仕込まれたフォームや画像から、 利用者のログイン状態を悪用して勝手に送信させる攻撃です。SameSite で外部からのリクエストに Cookie が付かなければ、 偽リクエストは「ログインしていない誰か」として届き、無害化されます。値は 3 つです。

SameSite の 3 つの値と挙動
クロスサイト送信主な用途
Strict送らない外部リンクからの遷移でも未ログイン扱いでよい、最も厳格な用途
Lax(既定)トップレベルの GET 遷移のみ送る一般的なセッション Cookie。利便性と安全のバランス
None常に送る(Secure 必須)外部サイトへの埋め込みなど、クロスサイト連携が必要な Cookie

現在のブラウザは、SameSite を指定しない Cookie を実質 Lax として扱います。 Lax では、外部リンクをクリックしてページを開く(トップレベルの GET 遷移)ときだけ Cookie が送られ、 外部からの POST や、画像・iframe に埋め込まれた形の読み込みには付きません。多くのサイトはこの Lax で十分です。

SameSite の 3 パターン
# 同一サイトの遷移でしか送らない(最も厳格)
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict; Path=/

# 既定。外部からのトップレベル GET 遷移だけ許可(推奨の落としどころ)
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/

# 常にクロスサイトで送る。このとき Secure は必須(無いとブラウザが破棄)
Set-Cookie: embed=xyz; Secure; SameSite=None; Path=/

セッション Cookie にはどう設定すべきですか?

セッション Cookie には HttpOnly・Secure・SameSite=Lax(または Strict)の 3 つをまとめて付けます。HttpOnly で XSS による窃取を、Secure で平文送信を、SameSite で CSRF を、それぞれ別の攻撃に対して塞ぎます。1 つでも欠けると対応する経路が開くため、3 点セットで指定するのが標準的な構成です。

3 つの属性はそれぞれ別の攻撃に対応しており、互いの代わりにはなりません。だからセッション Cookie では、 原則としてまとめて付けます。整理すると次のようになります。

  • HttpOnly — XSS でセッション ID を読み出させない
  • Secure — 平文通信で Cookie を漏らさない(盗聴対策)
  • SameSite=Lax(または Strict)— クロスサイトの偽リクエストに Cookie を付けない(CSRF 緩和)

外部サイトからの遷移で最初からログイン状態を見せたい、といった要件が無ければ、SameSite=Strict がより安全です。 逆に、外部リンクを踏んで来た人にもログイン状態を保ちたい一般的なサイトでは Lax が現実的な既定になります。 いずれにせよ、1 つでも欠けると、その属性が塞いでいた経路がそのまま開く点を忘れないでください。

__Host- や __Secure- プレフィックスとは何ですか?

Cookie 名の先頭に付ける特別な接頭辞で、ブラウザに一定の条件を強制させます。__Secure- は Secure 属性を必須にし、__Host- はさらに Path=/ と Domain 指定なしを強制して、サブドメインからの上書きを防ぎます。名前を変えるだけで安全側の設定を保証でき、セッション Cookie には __Host- が最も堅牢です。

プレフィックスは、Cookie の名前そのものにルールを埋め込む仕組みです。ブラウザは名前の接頭辞を見て、 条件を満たさない Set-Cookie を拒否します。属性の付け忘れや、後述のサブドメインからの上書きを、名前レベルで防げます。

  • __Secure-Secure 属性が付いていることを必須にする
  • __Host-Secure かつ Path=/ かつ Domain 指定なしを強制する。最も厳格

__Host-Domain 指定を禁じるのには理由があります。Domain を付けた Cookie はサブドメインでも共有されるため、 乗っ取られた or 信頼できないサブドメインから、親ドメインのセッション Cookie を上書き・固定される危険があります。__Host- は Cookie を発行元のホストだけに閉じ込め、この経路を断ちます。セッション Cookie には __Host- が最も堅牢です。

__Host- / __Secure- プレフィックスと、拒否される例
# __Host- : 最も厳格。Secure 必須・Path=/ 必須・Domain 指定禁止
Set-Cookie: __Host-session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/

# __Secure- : Secure を必須にする
Set-Cookie: __Secure-token=xyz; Secure; SameSite=Lax; Path=/

# 条件違反はブラウザが無視する(__Host- なのに Domain 付き / Path が / でない)
Set-Cookie: __Host-session=abc; Secure; Domain=example.com; Path=/app

設定できているかどう確認しますか?

ブラウザの開発者ツールで確認します。Application(または Storage)タブの Cookies を開くと、各 Cookie の Secure・HttpOnly・SameSite の列が一覧で見えます。Network タブで実際の Set-Cookie ヘッダーを確認する方法もあります。本ツールのセキュリティ診断でも、主要な Cookie 属性の有無を検出します。

目視での確認は、ブラウザの開発者ツールが早いです。Application(Firefox では Storage)タブの Cookies を開くと、Cookie ごとに SecureHttpOnlySameSite の列が並び、一覧で過不足を確認できます。 サーバーが実際に送っている値を見たいときは、Network タブでレスポンスの Set-Cookie ヘッダーを開きます。

注意したいのは、機械が判定できるのは「属性が付いているか」までだという点です。 その Cookie がセッション用として妥当か、SameSite=None が本当に必要かといった判断は、人が用途を踏まえて行う必要があります。 関連して、ヘッダー全体の見直しは セキュリティヘッダ 7 種の意味と設定 も参照してください。

参考にした一次情報

関連する解説

自分のサイトは、実際どうなっているか

この記事で説明した項目は、すべて無料の診断ツールで実測できます。URL を入れるだけ・登録不要です。

無料で診断する