Cookie のセキュリティフラグ完全ガイド|Secure / HttpOnly / SameSite / __Host-
Web アプリケーションのセッション管理で最もよく使われる Cookie ですが、正しく設定しないと セッションハイジャック (session hijacking)、CSRF (cross-site request forgery)、XSS 経由のトークン窃取といった攻撃を招きます。本記事では Cookie に付けるべき 4 つの主要フラグ (Secure / HttpOnly / SameSite / __Host- プレフィックス) の意味と、実装時の落とし穴を整理します。
Cookie の Set-Cookie ヘッダ構造
サーバがブラウザに Cookie をセットするとき、HTTP レスポンスに以下のようなヘッダを返します。
Set-Cookie: session_id=abc123; Path=/; Domain=example.com; Expires=Wed, 22 Apr 2026 10:00:00 GMT; Secure; HttpOnly; SameSite=Lax
セミコロンで区切られた複数の属性がありますが、大きく分けて次の 2 種類があります。
- スコープ属性: Path / Domain / Expires / Max-Age — Cookie がいつどこに送られるかを決める
- セキュリティ属性: Secure / HttpOnly / SameSite — 送信/アクセスを制限する
Secure — HTTPS でのみ送信
Secure 属性が付いた Cookie は、ブラウザは HTTPS 接続のときだけ サーバに送信します。付けないと、被害者が http:// でサイトにアクセスした瞬間に Cookie が平文で流れ、中間者攻撃 (Man-in-the-Middle) でセッション ID を盗まれる可能性があります。
鉄則: 認証系の Cookie には必ず付ける。ローカル開発は localhost のため HTTPS でなくても Secure Cookie が送られますが、本番の HTTPS を前提にすれば問題ありません。
HttpOnly — JavaScript からアクセス不可
HttpOnly を付けると document.cookie で読み取れなくなります。これにより、XSS 攻撃で挿入された JavaScript が Cookie を窃取できなくなります。
XSS は依然として起こりうる脆弱性なので、セッション Cookie には必須と考えてください。JavaScript 側で Cookie の値を読む必要がある場合 (例: CSRF トークン) は、読み取り専用の別 Cookie を作る か、<meta> タグ経由 で値を渡すのがセオリーです。
SameSite — クロスサイトリクエストでの送信制御
SameSite 属性は CSRF 対策の中核です。値は以下の 3 つ:
| 値 | 挙動 | CSRF 防御 |
|---|---|---|
Strict | クロスサイトリクエストに一切送らない (外部リンクから来たときも) | 最強 |
Lax (デフォルト) | トップレベル GET ナビゲーションでのみ送る (リンククリック OK、POST フォームは NG) | 強い |
None | すべてのクロスサイトリクエストで送信 (Secure 必須) | なし |
2020 年以降のモダンブラウザは SameSite 未指定を Lax として扱うため、明示しなくても最低限の CSRF 保護は得られますが、意図を明確にするために明示する方が良いです。
SSO 連携や iframe 埋め込みで SameSite=None を使う場合は、必ず Secure も付ける のが現代ブラウザの要求仕様です。Secure が無い SameSite=None Cookie はブラウザに拒否されます。
__Host- / __Secure- プレフィックス
Cookie 名が __Host- で始まる場合、ブラウザは次の 3 条件を強制します。
Secureフラグ必須Domain属性を付けてはならない (=リクエストを送った正確なホストのみ)Path=/でなければならない
これらは「他のサブドメインから上書きできない」「Host ヘッダ詐称で勝手に Cookie を置けない」という強力な保証を与えます。セッション Cookie には __Host-session のようにプレフィックスを付けるのが最も堅牢です。
もう一方の __Secure- プレフィックスは Secure フラグ必須のみを強制します (Domain / Path の制約なし)。
4096 バイト制限
Cookie の value は RFC 6265 で 合計 4096 バイト と推奨されています。大きな JSON や配列を Cookie に詰めると越えて、ブラウザに黙って切られることがあります。大きなデータはサーバサイドセッションに置いて、Cookie にはセッション ID だけ入れるのが定石です。
実装例: 認証セッション Cookie
正しく設定された認証 Cookie は以下のような形です。
Set-Cookie: __Host-session=eyJ0eXAi...; Path=/; Max-Age=3600; Secure; HttpOnly; SameSite=Lax
__Host-: サブドメイン汚染・ホスト偽装を防ぐPath=/: サイト全体でアクセス可能Max-Age=3600: 1 時間で期限切れSecure: HTTPS でのみ送信HttpOnly: JavaScript からアクセス不可SameSite=Lax: クロスサイト POST では送らない (CSRF 保護)
PHP (Laravel) の例
// config/session.php
return [
'secure' => true, // Secure フラグ
'http_only' => true, // HttpOnly フラグ
'same_site' => 'lax', // SameSite=Lax
'path' => '/',
'cookie' => '__Host-session',
];
Node.js (Express) の例
const session = require('express-session');
app.use(session({
name: '__Host-session',
secret: process.env.SESSION_SECRET,
cookie: {
secure: true,
httpOnly: true,
sameSite: 'lax',
path: '/',
maxAge: 3600 * 1000,
},
}));
既存サイトの Cookie 設定をチェックする方法
自分のサイトや他社サイトの Cookie が正しく設定されているかは、DevLab の Cookie 検査ツール で一瞬で確認できます。URL を入れるだけで、返ってきた Set-Cookie ヘッダすべてを解析し、次のような診断を表示します。
- 各 Cookie の Secure / HttpOnly / SameSite の有無
- SameSite=None なのに Secure が無いなどの違反
- __Host- プレフィックスの整合性
- 4096 バイト超過の警告
- 全体サマリー (Secure 率 / HttpOnly 率 / SameSite 分布)
まとめ
Cookie のセキュリティフラグは「なんとなく付けておく」ではなく、攻撃シナリオと対応を理解した上で設定するのが重要です。最低限、本番環境の認証セッション Cookie には Secure + HttpOnly + SameSite + __Host- プレフィックス + 短い Max-Age を付けましょう。既存サイトの設定見直しには Cookie 検査ツール の利用を推奨します。