コンテンツにスキップ

Cookie のセキュリティフラグ完全ガイド|Secure / HttpOnly / SameSite / __Host-

カテゴリ:Web セキュリティ

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 種類があります。

  1. スコープ属性: Path / Domain / Expires / Max-Age — Cookie がいつどこに送られるかを決める
  2. セキュリティ属性: 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 検査ツール の利用を推奨します。

📚 関連記事

PNG vs WebP vs AVIF|画像フォーマットの選び方と変換方法

PNG / JPEG / WebP / AVIF の特徴・用途・ブラウザ対応状況を比較。picture 要素での出し分け、DevLab の画像フォーマット変換ツールの使い方も解説。

2026-04-18

Whois でドメイン情報を調べる方法|有効期限・ネームサーバー・登録者

Whois でわかること (登録者・有効期限・レジストラ・NS)、GDPR によるプライバシー保護の影響、ドメイン管理の実務的な使い方を解説。

2026-04-18

HTTP ステータスコード完全ガイド|よくあるエラーの原因と対処法

開発者が頻出する HTTP ステータスコード (200/301/302/400/401/403/404/413/422/429/500/502/503/504) の意味・原因・対処法を解説。301 vs 302 の SEO 影響、400 vs 422 の使い分けも。

2026-04-18

cURL コマンドを JavaScript fetch・Python requests に変換する方法|DevTools 連携

Chrome DevTools の Copy as cURL を fetch / axios / Python requests / PHP cURL / Go net/http に変換する手順を解説。主要 cURL オプション (-X / -H / -d / -F / -u / -b / -L) の変換パターン、認証トークンの扱い、注意点まで。

2026-04-16

JWT のセキュリティベストプラクティス|alg none 攻撃 / 有効期限 / 署名検証

JWT (JSON Web Token) の代表的な脆弱性 6 種類 (alg none 攻撃 / 鍵混同 / 無期限トークン / payload への機密情報 / 失効不可 / 弱いシークレット) と対策。リフレッシュトークンパターン、失効リスト、HttpOnly Cookie 格納まで。

2026-04-16

ExcelでCSVを正しく開く・保存する方法|文字化けしないUTF-8 BOM対応

ExcelでCSVを開くと文字化けする原因と解決策。UTF-8 BOM付きCSVの作り方、Excelインポート手順、PHPとPythonでのBOM付きCSV出力コード例。macOS版Excelの注意点も解説。

2026-04-14