MENU

CookieのHttpOnly・Secure・SameSite属性とは?セッションハイジャックを防ぐ正しい設定ガイド

WebアプリにログインするたびにCookieが発行されている。そのCookieが盗まれれば、攻撃者はパスワードを知らなくてもログイン済み状態を再現し、システムを自由に操作できてしまう。

セッションハイジャックやCSRF(クロスサイトリクエストフォージェリ)といった攻撃を防ぐ最初の砦が、Cookieの「セキュリティ属性」だ。HttpOnly・Secure・SameSite——3つの属性を正しく設定するだけで、Webアプリのリスクは大幅に下がる。

この記事では、それぞれの属性の意味・仕組み・具体的な設定方法を、現場で使えるレベルで解説します。自社のWebサービスや社内Webシステムを運用している情シス担当者の方は、ぜひ最後まで読んでみてください。

CookieのHttpOnly・Secure・SameSite属性とは?セッションハイジャックを防ぐ正しい設定ガイド - 解説

目次

CookieとセキュリティーなぜCookieが攻撃者の標的になるか

Cookieとは、WebサーバーがブラウザにSet-Cookieヘッダーで渡す小さなデータだ。ログイン後の「セッションID」もCookieに格納される。ブラウザはリクエストのたびにCookieを自動送信するため、サーバー側はセッションIDを見て「この人はログイン済みだ」と判断する仕組みになっている。

つまり、セッションIDが書かれたCookieを入手できれば、攻撃者はパスワードを知らなくてもログイン済み状態を再現できる。これがセッションハイジャックだ。

Cookieを盗む主な手口は次の2つだ。

・XSS経由の窃取: 攻撃者が悪意のあるスクリプトをページに埋め込み、document.cookieでCookieの値を読み取って外部サーバーに送信する
・通信の盗聴: HTTPSではなくHTTPで通信しているとき、CookieがプレーンテキストとしてネットワークXに流れ、途中で盗み見られる

これらの攻撃経路を封じるのが、Set-CookieヘッダーのHttpOnly・Secure・SameSite属性だ。それぞれの役割を順番に見ていこう。

HttpOnly属性 — JavaScriptからのCookie窃取を防ぐ

HttpOnlyは、CookieをJavaScriptからアクセスできないようにする属性だ。

Set-CookieヘッダーにHttpOnlyを付与すると、ブラウザはdocument.cookieを通じたCookieの読み書きを禁止する。これにより、ページにXSSの脆弱性があり、悪意のあるスクリプトが埋め込まれてしまったとしても、セッションCookieを読み取って外部に送信することができなくなる。

Set-Cookieヘッダーでの記述例を見てみよう。

# セッションCookieにHttpOnlyを設定する例 Set-Cookie: sessionid=abc123xyz; HttpOnly # 複数の属性を組み合わせた推奨形式 Set-Cookie: sessionid=abc123xyz; HttpOnly; Secure; SameSite=Lax

HttpOnlyで防げること・防げないこと

HttpOnlyはXSS経由のCookie窃取を防ぐが、万能ではない。何が防げて何が防げないかを整理しておこう。

・防げる: XSS攻撃でのdocument.cookie読み取りによるセッションCookie窃取
・防げない: 別ドメインからの偽リクエスト送信(CSRF攻撃)。CookieはHTTPリクエスト時に自動付与されるため、HttpOnlyでは防げない。ここはSameSiteが担う
・防げない: HTTP通信での盗聴。これはSecure属性が担う
・防げない: XSS攻撃そのもの。スクリプトが動けばフォーム改ざんなど他の被害が起きる。入力値エスケープやCSPとの併用が必要だ

セッションCookie(ログイン状態を管理するCookie)には、必ずHttpOnlyを付けておくことを現場の基本ルールとして徹底してほしい。フロントエンドのJavaScriptがどうしてもCookieにアクセスしたい場合は、セッションとは別のCookieを使い、そちらにはHttpOnlyを付けないという使い分けが必要になる。

Secure属性 — HTTPS通信のみにCookieを限定する

Secure属性を付けると、ブラウザはHTTPS(TLS)で暗号化された接続のときだけCookieを送信する。HTTP(平文)接続ではCookieを送らないため、通信経路での盗聴リスクを排除できる。

# Secure属性の設定例 Set-Cookie: sessionid=abc123xyz; Secure # HttpOnlyと組み合わせた最低限の推奨設定 Set-Cookie: sessionid=abc123xyz; HttpOnly; Secure

Secure属性はHTTPSの利用が前提だ。HTTPSに対応していない環境ではSecure付きのCookieはブラウザから送信されなくなるため、ログイン状態が保持されなくなる。2026年現在、常時HTTPS化はWebサービスの当然の対策となっているが、まだ対応できていない古い社内システムも存在する。Secure属性の活用に先立ち、まずHTTPS化を優先しよう。

開発環境でHTTPを使っている場合、Secure属性のせいでCookieが送信されず動作しないことがある。そのような場合は、環境変数で本番環境とステージング・開発環境を切り替え、本番だけSecureを有効にする設計にする。

SameSite属性 — クロスサイトリクエストを3段階で制御する

SameSite属性は、別のドメイン(クロスサイト)からのリクエスト時にCookieを送信するかどうかを制御する。CSRF攻撃への主要な対策として機能する属性だ。

CSRFとは何か、簡単に整理しておこう。ログイン済みのユーザーが悪意のあるサイトを訪問したとき、そのサイトが裏でサービスへの偽リクエストを自動送信する攻撃だ。ブラウザはリクエストにCookieを自動付与するため、サーバー側は正規ユーザーからの操作と区別できなくなる。SameSiteはこの「自動送信」を制限することでCSRFを防ぐ。

SameSiteには3つの値がある。それぞれの挙動と使い所を説明する。

1. SameSite=Strict — 外部サイトからの送信を完全禁止

外部サイトからのすべてのリクエストでCookieを送信しない。セキュリティレベルが最も高い設定だ。

たとえば、ユーザーがメールのリンクをクリックしてサービスにアクセスしたとき、Cookieは送信されないためログアウト状態で表示される。利便性よりセキュリティを優先する場面——金融サービス、社内管理画面、決済システムなど——に向く設定だ。

Set-Cookie: sessionid=abc123xyz; SameSite=Strict; HttpOnly; Secure

2. SameSite=Lax — モダンブラウザのデフォルト値

外部サイトからのナビゲーション(リンクのクリックやリダイレクト)ではCookieを送信するが、iframe内の読み込みやfetch()・XMLHttpRequestによるサブリソース取得では送信しない。

Strictより使い勝手が良く、CSRF対策としても十分なケースが多い。Chrome 80以降、SameSite属性を省略した場合のデフォルトはLaxになっている。一般的なWebサービスにはLaxが推奨設定だ。

Set-Cookie: sessionid=abc123xyz; SameSite=Lax; HttpOnly; Secure

3. SameSite=None; Secure — クロスサイト送信を明示的に許可

外部サイトからのリクエストでもCookieを送信する。サードパーティのiframeを埋め込むサービス(外部決済フォーム、チャットウィジェット、広告配信など)で必要になる設定だ。

ただし、SameSite=Noneを使う場合はSecure属性の付与が必須だ。Chrome 80以降、SecureなしのSameSite=Noneは拒否される。

# SameSite=NoneにはSecureが必須(Secureなしはブラウザに拒否される) Set-Cookie: embed_session=xyz789; SameSite=None; Secure; HttpOnly

具体的な設定方法 — 言語・環境別のコード例

1. PHPでの設定

PHPではsession_set_cookie_params()でセッションCookieの属性を一括設定する。PHP 7.3以降は連想配列形式が使える。

0, // セッション終了まで 'path' => '/', 'domain' => '', 'secure' => true, // Secure: HTTPS専用 'httponly' => true, // HttpOnly: JSからアクセス不可 'samesite' => 'Lax', // SameSite: クロスサイト制限 ]); session_start(); // 任意のCookieを設定する場合(PHP 7.3以降の配列形式) setcookie( 'user_pref', 'dark_mode', [ 'expires' => time() + 86400, 'path' => '/', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax', ] );

2. Node.js(Express + express-session)での設定

const session = require('express-session'); app.use(session({ secret: process.env.SESSION_SECRET, // 環境変数から取得 resave: false, saveUninitialized: false, cookie: { httpOnly: true, // HttpOnly secure: true, // Secure(本番環境はtrue) sameSite: 'lax', // SameSite=Lax maxAge: 1000 * 60 * 60, // 1時間(ミリ秒) }, })); // 開発環境でHTTPを使う場合のみsecure: falseに切り替える // cookie: { secure: process.env.NODE_ENV === 'production' }

3. Pythonの設定(Django)

# settings.py SESSION_COOKIE_HTTPONLY = True # HttpOnly SESSION_COOKIE_SECURE = True # Secure SESSION_COOKIE_SAMESITE = 'Lax' # SameSite CSRF_COOKIE_HTTPONLY = False # CSRFトークンはJSが読む必要があるためFalse CSRF_COOKIE_SECURE = True # CSRFトークンもSecureは付ける CSRF_COOKIE_SAMESITE = 'Lax'

4. 設定の確認方法(curl・開発者ツール)

curlでSet-Cookieヘッダーを確認するには次のコマンドを使う。

# ログインエンドポイントのヘッダーを確認(-I でヘッダーのみ取得) curl -I -X POST https://example.com/login -d "user=test&pass=test" # 正しく設定されているときのSet-Cookieレスポンス例 # Set-Cookie: sessionid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

Chromeの開発者ツールで確認する方法も覚えておこう。

・F12でDevToolsを開く
・Applicationタブ → 左メニューのCookies → 対象ドメインを選択
・各Cookieの「HttpOnly」「Secure」列にチェックマークが入っているか目視確認する
・「SameSite」列でLax/Strict/Noneのいずれかが表示されているか確認する

セッションCookieのHttpOnlyとSecureにチェックが入っていない、またはSameSiteが空欄の場合は要修正だ。

中小企業でも今日からできること

Webサービスを外部委託しているケースや、パッケージシステムを使っているケースでも、確認・改善できることがある。

・現状確認を最初に: ブラウザのDevToolsで自社サービスにログインし、発行されるCookieのHttpOnly・Secure・SameSiteを確認する。5分でできる作業だ
・開発ベンダーへの依頼: 受託開発や保守委託先に「セッションCookieにHttpOnly・Secure・SameSite=Laxを設定してほしい」と伝える。具体的な属性名を伝えれば技術者に正確に届く
・WordPressの場合: セキュリティプラグイン(Wordfence等)でCookieのセキュリティ設定を強化できる場合がある。また、nginxやApacheの設定でSet-Cookieヘッダーに属性を後付けする方法も存在する
・HTTPS化を先に: まだHTTP環境が残っている場合はHTTPS化が最優先。Let’s Encryptで無償対応できる
・コミュニケーションのコツ: 「OWASP Top 10のA07(認証の失敗)対策として、セッションCookieのセキュリティ属性を整備したい」と伝えると、技術者・ベンダーに意図が正確に伝わる

OWASP Top 10とは?2021年版の全脆弱性リストと各項目の対策も合わせて読むと、Cookie設定がどの脅威カテゴリに対応しているか把握しやすい。

よくある誤解と注意点

【誤解1】「HttpOnlyがあればXSS対策は完了」
HttpOnlyはCookieの窃取を防ぐが、XSS攻撃そのものを止めるわけではない。スクリプトが動いてしまえば、Cookieを盗まなくてもページの内容改ざん、フォームへの不正入力、ユーザーへの偽表示などができる。HttpOnlyはXSS対策の一要素に過ぎず、入力値エスケープやCSPヘッダーとの組み合わせが必須だ。CSPについてはセキュリティヘッダー完全ガイド(CSP・HSTS・X-Frame-Options)で詳しく解説している。

【誤解2】「SameSite=Laxを設定すればCSRFトークンは不要」
SameSite=LaxはCSRFに対して強力な対策になるが、GET リクエスト経由の攻撃(ナビゲーションではCookieが送られるため)には完全ではない。重要な状態変更(パスワード変更・決済処理など)にはCSRFトークンとの併用が望ましい。

【誤解3】「SameSite=Noneはsecureなしでも使える」
Chrome 80以降、SameSite=NoneにSecureが付いていないCookieは自動的に拒否される。外部iframeや決済連携が突然動かなくなった場合、この設定漏れが原因のことが多い。

【誤解4】「Cookieのセキュリティ設定はHttpOnlyだけで十分」
3つの属性はそれぞれ異なる攻撃ベクトルを防ぐ。HttpOnly(XSS経由窃取)・Secure(通信盗聴)・SameSite(CSRF)は役割が別々であり、3点セットで使って初めて多層的な防御になる。

ログイン後のセッションID再生成を忘れずに
Cookieのセキュリティ属性を適切に設定していても、ログイン成功後にセッションIDを再生成しないとセッション固定化攻撃のリスクが残る。ログイン前のセッションIDを引き継がないよう、認証成功時に必ず新しいセッションIDを発行する設計にしよう。詳細はセッション固定化攻撃(Session Fixation)とは?で解説している。

CookieのHttpOnly・Secure・SameSite属性とは?セッションハイジャックを防ぐ正しい設定ガイド - まとめ

本記事のまとめ

CookieのHttpOnly・Secure・SameSite属性は、Webアプリの認証を守るうえで最も基本的かつ即効性のある設定だ。3点セットで理解しておこう。

属性 目的 防げる主な攻撃 推奨設定
HttpOnly JSからCookieを隠す XSS経由のCookie窃取 セッションCookieに必ず付ける
Secure HTTPS接続のみに限定 平文通信での盗聴・改ざん HTTPS環境で必ず付ける
SameSite=Lax クロスサイトの自動送信を制限 CSRF攻撃 一般的なWebサービスの標準
SameSite=Strict クロスサイト送信を完全禁止 CSRF攻撃(最高強度) 金融・管理画面など高リスク系
SameSite=None クロスサイト送信を明示許可 (許可が必要な場合に限定使用) 必ずSecureと併用すること

セッションCookieには最低でもHttpOnly; Secure; SameSite=Laxの3点セットを設定する。これが現場の標準だ。まだ設定できていないなら、今日中に自社サービスのCookieをDevToolsで確認してみてほしい。

PR

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版(徳丸浩/SBクリエイティブ)

Cookieのセキュリティ属性を含むWebアプリ全般の脆弱性対策を体系的に習得できる一冊。XSS・CSRF・セッション管理など本記事で触れたテーマをコード例付きで詳解しており、開発者・情シスを問わず手元に置いておきたい国内標準テキストです。

関連記事をもっと読む

同じテーマの記事をまとめています。あわせて読みたい記事はこちらからご覧いただけます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次