0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cookieのセキュリティ属性 SameSite / Secure / HttpOnly の正しい付け方(PHP / nginx / Apache / WordPress対応・コピペOK)

0
Last updated at Posted at 2026-06-08

はじめに

ログイン機能やカートなど「セッション」を持つサイトでは、Cookieの守りが甘いとセッション乗っ取り(セッションハイジャック)やCSRFの被害に直結します。逆に言えば、Secure / HttpOnly / SameSite の3つの属性を正しく付けるだけで、これらの典型的なリスクを大きく下げられます。

この記事では、3属性それぞれの役割と間違えやすいポイント、PHP / nginx / Apache / WordPress での設定方法、そして設定後に「本当に付いているか」を確認する方法までをまとめます。対象は、自社サイトやアプリを運用・制作する初〜中級エンジニア/Web担当者です。

値はサイトの認証フロー(SSO・外部リダイレクト・サブドメイン構成など)によって最適解が変わります。本番反映前に必ず検証環境で動作確認してください。


まず全体像:3つの属性の役割

属性 役割(何を防ぐか) 付けないと起きること
Secure HTTPS接続のときだけCookieを送信する HTTP通信で平文のまま盗聴され、Cookieを盗まれる
HttpOnly JavaScriptからCookieを読めなくする XSSが起きた際にdocument.cookieでセッションを抜かれる
SameSite 別サイト起点のリクエストでの送信を制御する クロスサイトでCookieが送られCSRFの起点になる

3つは役割が重なりません。3つセットで初めて「盗聴・XSS経由の窃取・クロスサイト送信」をそれぞれ塞げると考えてください。


各属性の詳細と推奨

Secure

CookieをHTTPS接続のときだけブラウザが送信するようにします。常時HTTPSが前提の今、セッション系Cookieには必須です。

  • 注意: HTTP(平文)では送られません。ローカル開発を http://localhost で行っていると、Secure付きCookieが送られずログインできない、という形でハマりがちです(開発環境だけ条件分岐する等の対応が必要)。

HttpOnly

JavaScriptの document.cookie からそのCookieを読めなくします。XSSが混入しても、セッションCookieの値を盗み出す経路を一つ塞げます。セッション・認証系Cookieには付けるのが基本です。

  • 注意: HttpOnlyはCSRF対策ではありません(ブラウザはCookieを自動送信するため)。CSRF対策は後述のSameSiteやCSRFトークンで別途行います。
  • JavaScriptから読む必要があるCookie(例: 古い設計でCSRFトークンをJSから参照している等)はHttpOnlyにできません。その場合は「セッション本体は別Cookieにして、それだけHttpOnly」など設計を分けるのが安全です。

SameSite

別サイトを起点とするリクエストにCookieを付けるかどうかを制御します。値は3種類です。

挙動 主な用途
Strict 別サイトからのリクエストでは一切送らない 最も堅い。ただし副作用に注意(下記)
Lax 別サイトからの**トップレベル遷移(GET)**でのみ送る 多くのサイトの実用的な既定
None クロスサイトでも常に送る。Secure必須 埋め込みや別ドメインAPIなどクロスサイト前提の用途
  • 主要ブラウザは、SameSiteを指定しない場合に Lax 相当として扱います(Chromeはバージョン80以降この挙動)。とはいえ挙動を明示するため、意図する値を必ず付けるのが推奨です。
  • SameSite=NoneSecure がないとブラウザに拒否されます。 Noneを使うならHTTPS+Secureがセットです。
  • Strict の落とし穴: 外部サイトのリンクから自サイトに遷移した「直後」はCookieが送られないため、ログイン状態に見えない、という挙動になります。SSO・OAuth・決済リダイレクトのように外部から戻ってくるフローがあるサイトでは、Lax のほうが無難です。

補足:Cookieプレフィックス __Host- / __Secure-

Cookie名の先頭に特定の接頭辞を付けると、ブラウザ側が属性の要件を強制してくれます。

  • __Secure-Secure 必須。
  • __Host-Secure + Path=/ + Domain属性なし(=発行元ホストに限定)。最も堅い。

要件を満たさないとブラウザがそのCookieを無視するため、誤設定の検出にも役立ちます。対応ブラウザは広いですが、既存Cookie名の変更はアプリ改修を伴うため計画的に。


環境別 設定方法(コピペ用)

Cookieは基本的にアプリケーションが発行するものなので、まずはアプリ側で付けるのが最も確実です。サーバ側(nginx/Apache)での一括付与は、アプリを直せない場合の補完と考えてください。

アプリ側:PHP(最も確実)

任意のCookieを発行する場合(PHP 7.3以降のオプション配列):

setcookie('token', $value, [
    'expires'  => time() + 3600,
    'path'     => '/',
    'secure'   => true,      // HTTPSのみ
    'httponly' => true,      // JSから不可視
    'samesite' => 'Lax',     // 'Strict' / 'Lax' / 'None'(NoneはSecure必須)
]);

PHPのセッションCookieは、設定で一括指定できます(php.ini):

session.cookie_secure   = 1
session.cookie_httponly = 1
session.cookie_samesite = "Lax"

実行時に指定する場合(session_start() の前に):

session_set_cookie_params([
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
session_start();

samesite オプションはPHP 7.3以降で利用可能です。それ以前のバージョンでは別途ヘッダ操作が必要になります。

nginx(リバースプロキシ構成)

バックエンドが返すCookieに属性を付与するには proxy_cookie_flags(nginx 1.19.3以降)が使えます。

location / {
    proxy_pass http://backend;
    proxy_cookie_flags ~ secure httponly samesite=lax;
}
  • 重要な制約: proxy_cookie_flagsproxy_pass で受けた応答に対する機能です。PHP-FPMを fastcgi_pass で動かす一般的なWordPress構成には適用されません(fastcgi向けの同等ディレクティブが無い)。その場合はアプリ側(PHP)で設定するのが確実です。

Apache(.htaccess / mod_headers)

mod_headersedit で、レスポンスの Set-Cookie に属性を追記できます(Apache 2.4.11以降)。

<IfModule mod_headers.c>
    Header always edit Set-Cookie ^(.*)$ "$1; Secure; HttpOnly; SameSite=Lax"
</IfModule>
  • 注意1: この書き方はすべての Set-Cookie に無条件で追記します。既に SameSite 等が付いているCookieには属性が二重になり得ます。対象を絞るなら、特定Cookie名にマッチする正規表現にしてください。
  • 注意2: HTTPでアクセスするとSecure付きCookieはブラウザに無視されます。開発環境などHTTPで触る場面でログインできなくなることがあります。
  • 事前に a2enmod headers && systemctl restart apache2(Debian/Ubuntu系の例)。.htaccess で効かせるには AllowOverride の許可が必要です。

WordPress

  • WordPressの認証Cookieは既定で HttpOnly が付いています。
  • Secure にするには、常時HTTPS化したうえで wp-config.php に次を追加します。
define('FORCE_SSL_ADMIN', true);
  • SameSite はWordPressコアに「これ一つで指定できる定数」が用意されていません。PHPの session.cookie_samesite はPHPセッションには効きますが、WP独自の認証Cookieには別途の対応が要ります。手早く全Cookieに付けたい場合は、上のApache Header edit でまとめて付与する方法が現実的です(副作用に注意)。
  • いずれの方法でも、後述の方法で実際に付与されているかを必ず確認してください。キャッシュやプラグインの挙動で意図通りにならないことがあります。

設定時の注意点・副作用(重要)

  • SameSite=Strict は外部サイトからのリンク遷移直後にログイン状態が引き継がれない。SSO・OAuth・決済リダイレクトを使うサイトは Lax を基本に。
  • SameSite=NoneSecure 必須。HTTPS前提でしか使えない。
  • Secure はHTTPでは送信されない。ローカル開発(http)で詰まりやすい典型ポイント。
  • HttpOnly はCSRF対策ではない。CSRFは SameSite やCSRFトークンで別途対策する。
  • Domain 属性を広く付け過ぎると意図しないサブドメインへCookieが送られる。限定したいなら __Host- プレフィックスが有効。
  • ブラウザではクロスサイト(サードパーティ)Cookieの制限が段階的に進んでいる。クロスサイト前提の実装は将来の挙動変更の影響を受ける可能性があるため、依存度は環境により見直しが必要。

設定後の確認方法

まずは curl で生の Set-Cookie を確認するのが確実です。

curl -sI https://example.com/login | grep -i set-cookie

ブラウザのDevToolsでも確認できます。

  • DevTools → Application(またはStorage)→ Cookies:各Cookieの Secure / HttpOnly / SameSite 列を一覧で確認。
  • DevTools → Issues/コンソール:SameSite未指定などの警告が出ることがある。

外形チェックには無料ツールも便利です。評価軸が異なるので、複数併用すると把握しやすくなります。

  • Mozilla Observatory:ヘッダに加えてCookie属性も採点し、改善提案を出してくれる。
  • OWASP ZAP:ローカルで動かせるOSSスキャナ。Cookie属性の欠落を受動的に検出できる。
  • サイトドック(sitedock.jp):URLを入れると登録不要で、Cookie属性やヘッダ・SPF/DMARCなどをパッシブに健診してスコア化する無料サービス。設定後の抜け漏れを第三者視点でまとめて確認したいときの手段の一つとして。

ツールごとに判定基準が微妙に違うため、「あるツールで満点でない=即危険」とは限りません。指摘内容を自サイトの認証フローに照らして取捨選択するのが現実的です。


まとめ

  • Secure(盗聴)・HttpOnly(XSS経由の窃取)・SameSite(クロスサイト送信)は役割が別。3つセットで考える
  • セッション・認証系Cookieは原則 Secure; HttpOnly; SameSite=Lax から。
  • SameSite=Strict は外部リダイレクト系フローで副作用が出やすい。SSO/決済があるなら Lax
  • SameSite=NoneSecure 必須(なければブラウザが拒否)。
  • Cookieはアプリ側で付けるのが最も確実。nginx proxy_cookie_flags はproxy構成限定、Apache Header edit は全Cookieに無条件追記する点に注意。
  • WordPressの認証Cookieは HttpOnly 既定。Secureは FORCE_SSL_ADMIN、SameSiteはサーバ/PHP側の補完が必要。
  • 反映後は curl -I とDevTools(Application > Cookies)、Mozilla Observatory / OWASP ZAP などで実際に付いているかを必ず確認する。

想定タグ: Security Cookie SameSite PHP WordPress

想定読了時間: 約7〜9分

難易度: 初〜中級


関連記事

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?