Webサイトにログインした直後、あなたのアカウントが知らない誰かに操作されていたら——そんな状況を引き起こすのがセッション固定化攻撃(Session Fixation)です。XSSやSQLインジェクションほど有名ではないものの、Webアプリケーションの認証機能を狙う攻撃として今なお報告が続いています。
この記事では、セッション固定化攻撃の仕組みから、現場の開発者・情シス担当者がすぐに実践できる防御手順まで、攻撃者の視点から丁寧に解説します。
セッション固定化攻撃とは?
Webアプリケーションは、ログイン後のユーザーを識別するために「セッションID」と呼ばれる一意の文字列を発行し、CookieやURLのクエリパラメータとしてブラウザとサーバー間でやり取りします。
セッション固定化攻撃(Session Fixation)は、このセッションIDを攻撃者が事前に「仕込んで」おき、ユーザーがログインした後にそのIDを使ってセッションを乗っ取る手法です。
重要なのは「セッションIDを盗む」のではなく、「自分が知っているIDを被害者に使わせる」という点です。ここが、セッションIDを強奪して成立するセッションハイジャックとの本質的な違いです。
攻撃者は事前に有効なセッションIDを知っているため、被害者がログインした瞬間に「認証済みセッション」への扉が自動的に開く仕組みになっています。
攻撃の仕組み(ステップバイステップで理解する)
セッション固定化攻撃は、主に以下の3段階で進みます。
1. 攻撃者がセッションIDを入手する
攻撃者は標的のWebサービスにログイン前の状態でアクセスし、その時点で発行される一時的なセッションIDを取得します。多くのWebアプリケーションはログイン前でも匿名セッションを発行するため、このステップは難しくありません。
2. 被害者に細工したURLを踏ませる
攻撃者は取得したセッションIDを埋め込んだURLを作成し、フィッシングメールやSNSのダイレクトメッセージなどで被害者に送ります。
# 攻撃者が作成する細工URLの例 https://example.com/login?PHPSESSID=attacker_known_session_id_12345 # または URL の特定部分にセッションIDを仕込む https://example.com/login;jsessionid=ATTACKER_KNOWN_ID
被害者が気づかずにこのリンクからアクセスすると、ブラウザは攻撃者の知っているセッションIDを使ってサービスと通信し始めます。
3. 被害者のログイン後にセッションを乗っ取る
脆弱なアプリケーションはログイン成功後もセッションIDを変更しません。被害者がID・パスワードを入力してログインした瞬間、攻撃者の知っているセッションIDが「認証済み」の状態になります。
攻撃者はそのIDを使ってサービスにアクセスするだけで、被害者のアカウントとして操作できます。
被害シナリオ:どんなサービスで起きやすいか
セッション固定化攻撃が起きやすい実装パターンを2つ挙げます。
・URLにセッションIDを含むシステム: 古いフレームワークやレガシーシステムでは、セッションIDをCookieではなく?sessionid=xxx形式でURLに含めていることがあります。URLは外部に共有・ログ保存されやすく、特に攻撃者に悪用されやすい状況です。
・ログイン後にセッションIDが変わらないアプリ: 最も多く見られる脆弱パターンです。認証成功時に新しいセッションIDを発行しないため、攻撃者が事前に用意したIDがそのまま認証済みセッションとして機能します。企業の基幹Webシステムや、古いECサイト、更新が止まったCMSで散見されます。
OWASP Top 10でも「不適切な認証」および「セッション管理の欠陥」は重大リスクとして継続的に取り上げられており、セッション固定化はその代表例の一つです。
具体的な防御手順
1. ログイン後に必ずセッションIDを再発行する
最も重要かつ効果的な対策です。認証成功の直後に古いセッションIDを破棄し、新しいIDを発行します。これだけで攻撃者が事前に仕込んだIDを無効化できます。
PHPの実装例:
# 認証処理の直後に実行する(trueで古いセッションファイルも削除) session_regenerate_id(true); # セッションに認証済みフラグを設定 $_SESSION['authenticated'] = true; $_SESSION['user_id'] = $user_id;
Javaの例(Spring Security):
// Spring Securityはデフォルトでセッション再生成を行う // カスタム設定が必要な場合の例 http.sessionManagement() .sessionFixation().newSession(); // 新規セッションを生成 // または .changeSessionId() で IDのみ変更(属性は引き継ぎ)
この1行の実装漏れが、セッション固定化攻撃の最大の原因です。「動いているから大丈夫」ではなく、実際にログイン前後でIDが変わっているか必ず確認してください。
2. セッションIDをURLに含めない
セッションIDはCookieでのみ管理し、URLパラメータには一切含めないことが原則です。URLはブラウザの履歴・サーバーログ・リファラーヘッダーに残るため、意図せず第三者に漏洩するリスクがあります。
PHPの場合は php.ini または ini_set で設定します:
# php.ini の設定(デフォルト値からの変更点をコメントで明記) session.use_trans_sid = 0 ; デフォルトは1(URLへの埋め込みを無効化) session.use_only_cookies = 1 ; Cookieのみでセッション管理(必須) session.use_cookies = 1 ; Cookieを使用する
3. CookieにHttpOnly・Secure・SameSiteフラグを設定する
セッションCookieには以下のフラグを必ず設定します。
・HttpOnly: JavaScriptからCookieにアクセスできなくなります。XSSによるセッションID窃取のリスクを低減します。
・Secure: HTTPS通信時にのみCookieが送信されます。平文HTTP通信での漏洩を防ぎます。
・SameSite=Strict(またはLax): 外部サイトからのリクエストにCookieが付与されなくなります。CSRF対策にも有効です。
PHPでの設定例:
# session_start() の前に設定する session_set_cookie_params([ 'lifetime' => 0, # ブラウザを閉じるまで有効 'path' => '/', 'domain' => 'example.com', 'secure' => true, # HTTPSのみ送信 'httponly' => true, # JavaScriptからアクセス不可 'samesite' => 'Strict', # 外部サイトからのリクエストでは送信しない ]); session_start();
4. セッションの有効期限を適切に設定する
長時間有効なセッションは、万一乗っ取られた際の被害を拡大させます。業務の性質に合わせた適切なタイムアウト設定が重要です。
・アイドルタイムアウト: 一定時間操作がなければセッションを無効化します(例: 30分)。
・絶対タイムアウト: 操作中でも一定時間を超えたらセッションを切り、再ログインを求めます(例: 8時間)。
・重要操作前の再認証: 決済・パスワード変更・個人情報閲覧などの重要操作前にパスワード確認を再度要求します。
中小企業・情シスが今日からできること
「自社のWebシステムが影響を受けるか判断できない」という方のために、すぐ確認できる手順を整理します。
・ブラウザの開発者ツールで確認する: Chromeであれば「F12→Application→Cookies」を開き、ログイン前後でセッションCookieの値が変わっているか確認します。変わっていなければ開発ベンダーに是正を依頼します。
・外部のWebシステムを利用中であれば提供元に問い合わせる: SaaS・パッケージソフトは提供元のセキュリティ対応状況を確認します。特に更新が止まっているシステムは要注意です。
・定期的な脆弱性診断を実施する: 外部の脆弱性診断サービスを利用することで、セッション管理の実装ミスを専門家の目で早期発見できます。
・多要素認証(MFA)を導入する: セッションが乗っ取られても、重要操作の前に多要素認証を求める設計にしておくと、被害の拡大を抑えられます。
LinuxサーバーでPHPアプリケーションを稼働させている場合、php.iniの設定変更後はWebサーバーの再起動が必要です。設定値の確認は姉妹サイトLinuxMaster.JPのサーバー管理記事も参考にしてください。
よくある誤解と注意点
【誤解1】「HTTPSにすれば大丈夫」
HTTPSは通信経路を暗号化しますが、セッション固定化攻撃はアプリケーション層の実装問題です。HTTPS環境でも、ログイン後にセッションIDを再発行しなければ攻撃は成立します。暗号化と認証処理は別の問題として対処が必要です。
【誤解2】「モダンなフレームワークを使っているから安全」
DjangoやRuby on Rails、Spring Securityなどは標準でセッション再発行を実装していますが、古いバージョンを使用している場合や、設定を意図せず変更している場合は例外です。フレームワークのバージョンとセキュリティ設定は定期的に確認してください。
【注意】ログアウト処理も忘れずに
ログアウト時はサーバー側でセッションデータを確実に削除します。クライアント側でCookieを削除するだけでは不十分で、サーバー上にセッションデータが残ったままになります。
# PHPのログアウト処理の正しい実装 session_start(); $_SESSION = []; # セッションデータを空にする session_destroy(); # サーバー側のセッションファイルを削除 setcookie(session_name(), '', time()-1); # クライアントのCookieも削除
本記事のまとめ
セッション固定化攻撃(Session Fixation)は、攻撃者が事前に「仕込んだ」セッションIDをユーザーに使わせ、ログイン後のアカウントを乗っ取る手法です。古典的な脆弱性でありながら、実装の落とし穴として今なお多くのシステムで発見されています。
| 対策 | 実装内容 | 難易度 |
|---|---|---|
| セッションID再発行 | ログイン直後に session_regenerate_id(true) | 低(1行追加) |
| URLセッションID禁止 | use_only_cookies=1 に設定 | 低(設定変更) |
| Cookieフラグ設定 | HttpOnly・Secure・SameSite を付与 | 低(設定変更) |
| タイムアウト設定 | アイドル30分・絶対タイムアウト8時間 | 中(要テスト) |
| 多要素認証の導入 | ログインおよび重要操作前に2要素認証 | 中(システム連携) |
「うちは大丈夫だろう」と油断せず、ブラウザの開発者ツールで実際にセッションIDが変わっているかを確認する習慣をつけることが、Webセキュリティの第一歩です。定期的な脆弱性診断と実装の見直しを続けることで、攻撃者が狙う隙を着実に減らしていきましょう。
PR
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版(徳丸浩/SBクリエイティブ)
セッション固定化をはじめ、XSS・CSRF・SQLインジェクションなど主要なWeb脆弱性の仕組みと対策コードを体系的に学べる定番書です。開発者だけでなく、仕様レビューを行う情シス担当者にも強くお勧めします。
