概要

Session の脅威のひとつが Session Hijacking (セッション乗っ取り)PHPSESSID を盗まれると、攻撃者は自分のブラウザに Cookie をセットするだけで「ログイン済みの被害者」になりすませる。特に怖いのが Session Fixation (固定化攻撃) で、攻撃者が事前に取得した Session ID を細工した URL 等で 被害者に使わせて、ログイン後の Session を共有してしまう手口。

これを防ぐ標準対策が session_regenerate_id(true)。ログイン成功の 直後に必ず呼ぶ ことで、新しい Session ID を発行して古い ID を破棄する (true が古い Session ファイルを消す指定)。事前に使わせた ID はログインの瞬間に無効化され、盗んでも意味がなくなる。ドリルでは regenerate 前後の ID を比較して目視確認する。

上乗せ防御として、Session Cookie には Secure 属性 (HTTPS でしか送らない) と HttpOnly 属性 (JavaScript から読めない) を必ず付ける。session.cookie_secure = 1 / session.cookie_httponly = 1 を php.ini か ini_set で設定するのが定石。本番運用なら 「regenerate_id + Secure + HttpOnly」の 3 点セット が常識ライン。

学習目標

ドリル

no 内容
01 ログイン時に session_regenerate_id(true) を呼び、新旧 ID が違うことを "changed: yes" の形で出力
02 固定化攻撃のシナリオを擬似化 — 既知の ID で開始 → ログイン → ID が変わったか検証

本物のセッション動作で確認したい場合

cd topics/session-cookie/ch06-session-security/drill/01-regenerate-id/
php -S localhost:8000 answer.php

ブラウザの開発者ツール (Application → Cookies → PHPSESSID) を見ながらリロードし、ログイン処理を呼んだ瞬間に Session ID が変わることを確認。

演習: ドリル 01 — `session_regenerate_id(true)` で ID を作り直す

問題

ログイン時の Session ID 再生成を再現してください。

期待される出力:

changed: yes

ヒント

$oldId = session_id();
@session_regenerate_id(true);
$newId = session_id();

echo ($oldId !== $newId ? "changed: yes" : "changed: no") . "\n";

本物のセッション動作で確認したい場合

cd topics/session-cookie/ch06-session-security/drill/01-regenerate-id/
php -S localhost:8000 answer.php

ブラウザの開発者ツールで PHPSESSID を見ながらリロード、再生成のタイミングで Cookie 値が変わることを確認。

演習: ドリル 02 — Session Fixation シナリオ — ログイン時に ID 再生成で防ぐ

問題

固定化攻撃のシナリオを 1 スクリプトで擬似化します。

シナリオ:

  1. 攻撃者から渡された ID ATTACKERFIXEDID で Session を開始 (採点用スタブで session_id() をこの値にセット)
  2. ユーザーがログイン処理を実行
  3. ログイン直後に session_regenerate_id(true) を呼ぶ
  4. ログイン後の Session ID が攻撃者の渡した固定 ID と 異なる ことを確認

出力仕様:

期待される出力:

safe: regenerated

(session_regenerate_id(true) を呼ばないと vulnerable: fixation になる)

ヒント

// スタブで session_id('ATTACKERFIXEDID') がセットされている前提
$oldId = session_id();                    // ATTACKERFIXEDID
$_SESSION['user'] = ['name' => '太郎'];   // ログイン
@session_regenerate_id(true);             // ★ ここがポイント
$newId = session_id();

echo ($oldId !== $newId ? "safe: regenerated" : "vulnerable: fixation") . "\n";

ポイント

この章を AI に聞く

  1. 「ch06 — Session セキュリティ (regenerate_id / 固定化)」のつまずきやすいポイントを、初学者向けに3つ教えてください

    💬 ChatGPT 📘 Claude ✨ Gemini

  2. 「ch06 — Session セキュリティ (regenerate_id / 固定化)」について、自分の手で試せる練習問題を3つ出してください (難易度を上げながら)

    💬 ChatGPT 📘 Claude ✨ Gemini

  3. 「ch06 — Session セキュリティ (regenerate_id / 固定化)」を学んだ後、次に学ぶと良いトピックは何ですか?理由も教えてください

    💬 ChatGPT 📘 Claude ✨ Gemini

🎉 受講お疲れさまでした!

ch06 — Session セキュリティ (regenerate_id / 固定化)」を読み終えました。
学んだことを誰かに教えると、もっと記憶に残ります。

X で共有 Hatena LINE