07. Webアプリケーションの脆弱性

【Webセキュリティ】乗っ取りを防げ!セッションハイジャックと固定化攻撃の脅威と対策を徹底解説

2026年1月20日

Kenta Banno

元CIOの窓際サラリーマン(50代) 。プライム上場企業の片隅で、情報処理安全確保支援士の合格を目指し奮闘中。 最新AI(Gemini/Claude)を相棒に、記事を作成しています。

Webサービスを利用しているとき、私たちは普段意識することなく「ログイン状態」を維持しています。しかし、この「つながっている状態」こそが、攻撃者にとって格好の標的であることをご存じでしょうか。

もし、あなたになりすました誰かが、勝手にショッピングをしたり、重要なデータを盗み出したりしたら……。考えただけでも背筋が凍る事態ですが、これは決して他人事ではありません。Webアプリケーションの脆弱性を突く攻撃の中でも、特に影響度が大きく、かつ仕組みを理解していないと防ぎにくいのが「セッション」に関連する攻撃です。

本記事では、Webセキュリティの根幹に関わる「セッションハイジャック」と「セッション固定化(フィクセーション)攻撃」について、その仕組みから具体的な手口、そしてエンジニアとして知っておくべき防御策までを網羅的に解説します。単なる用語の暗記ではなく、攻撃者がどこを狙ってくるのか、その思考プロセスを理解することで、堅牢なシステム設計への第一歩を踏み出しましょう。

そもそも「セッション」とは何か?Webの仕組みを理解する

セッション攻撃を理解するためには、まず「セッション」という概念がなぜ必要なのか、Webの基本的な仕組みに立ち返る必要があります。ここをおろそかにすると、攻撃の本質が見えてきません。

ステートレスなHTTPとステートフルなWeb体験

私たちが普段利用しているWebサイトは、主にHTTP(Hypertext Transfer Protocol)という通信手順を使ってやり取りをしています。このHTTPには、非常に重要な特徴があります。それは「ステートレス(Stateless)」であるということです。

ステートレスとは、直訳すれば「状態を持たない」という意味です。クライアント(あなたのブラウザ)がサーバーにリクエストを送り、サーバーがレスポンスを返す。この一往復が終われば、サーバーは「誰と通信していたか」を忘れてしまいます。

もしWebがそのままの状態だったら、Amazonで買い物をする際に、ページを移動するたびにログインIDとパスワードを入力しなければなりません。カートに商品を入れても、決済ページに移動した瞬間にカートの中身は空っぽになってしまいます。これでは不便極まりありません。そこで登場するのが「セッション管理」です。サーバー側で「今アクセスしてきているのは、さっきログインしたAさんだ」という状態(ステート)を記憶しておく仕組みです。

識別の鍵となる「セッションID」

セッション管理を実現するために最も一般的に使われるのが「セッションID」です。これは、テーマパークの「再入場スタンプ」や、クロークの「引換券」のようなものだと考えてください。具体的な流れは以下の通りです。

  1. ユーザーがIDとパスワードでログインする
  2. サーバーは認証に成功すると、ランダムで長い文字列(セッションID)を発行する
  3. サーバーは「このセッションIDはAさんのもの」とメモリやデータベースに記録する
  4. サーバーはユーザーのブラウザに対して「このセッションIDをCookie(クッキー)に保存しておいてね」と指示(Set-Cookieヘッダ)を出す
  5. 以降、ブラウザはサーバーにアクセスするたびに、自動的にそのセッションIDを提示する
  6. サーバーは提示されたIDを見て「ああ、これはAさんからのアクセスだな」と判断する

この一連の流れによって、私たちはページ遷移してもログイン状態を維持できるのです。しかし、ここに重大なセキュリティリスクが潜んでいます。もし、この「引換券(セッションID)」を誰かに盗まれたらどうなるでしょうか?

ログイン認証後にサーバーからセッションIDが発行され、以降の通信でそのIDを使ってユーザー識別を行う流れの図解

セッションハイジャック:なりすましの恐怖

セッションハイジャックとは、正規のユーザーが使用している有効なセッションIDを、攻撃者が何らかの方法で窃取し、そのユーザーになりすましてWebサイトにアクセスする攻撃の総称です。

パスワードを知らなくても、セッションIDさえあれば、サーバーは攻撃者を「正規のユーザー」と誤認してしまいます。これにより、個人情報の閲覧、不正送金、SNSへの勝手な投稿、パスワードの変更など、ユーザーができることは全て攻撃者もできるようになってしまいます。

セッションIDが盗まれる主要な3つのルート

では、攻撃者はどのようにしてセッションIDを盗み出すのでしょうか。主な手口は以下の3つに大別されます。

1. ネットワーク盗聴(スニフィング)

公衆無線LAN(フリーWi-Fi)などでよく発生するリスクです。Webサイトが通信を暗号化していない(HTTP接続の)場合、ネットワーク上を流れるデータは平文(そのままの文字)で送受信されます。攻撃者が同じWi-Fiネットワーク内にいて、パケットキャプチャツールなどを使っていれば、通信の中身を覗き見ることができます。

Cookieに含まれるセッションIDが平文で流れていれば、それをコピーするだけで簡単になりすましが完了してしまいます。現在では常時SSL/TLS化(HTTPS)が普及したため、この手口は減少しつつありますが、古いシステムや設定ミスがあるサイトでは依然として脅威です。

2. クロスサイトスクリプティング(XSS)による窃取

Webアプリケーションに脆弱性があり、攻撃者が作成した悪意あるJavaScriptを被害者のブラウザ上で実行できる場合、セッションIDが盗まれる危険性が非常に高まります。JavaScriptには document.cookie というプロパティがあり、これにアクセスすることでCookieの内容(セッションIDを含む)を参照できます。

攻撃者は、XSSの脆弱性を利用して「Cookieの内容を攻撃者のサーバーに送信する」というスクリプトを被害者に実行させ、セッションIDを搾取します。このようなスクリプトは、掲示板のコメント欄や検索ボックスなど、ユーザーの入力を表示する機能に仕込まれることが多く、被害者は何も気づかないまま情報を抜き取られてしまいます。

3. セッションIDの推測

もし、セッションIDの生成規則が単純だったらどうなるでしょうか。例えば、連番(Session001, Session002...)であったり、ユーザーIDと時刻を単純に組み合わせただけであったりする場合、攻撃者は自分のセッションIDから他人のセッションIDを容易に推測できます。これを「推測攻撃」と呼びます。

現在の主要なフレームワークや言語(Java, PHP, Rubyなど)が提供するセッション管理機能を使っていれば、暗号論的に安全な乱数が使われるため推測は困難ですが、独自に実装したセッション管理機能を使っている場合は注意が必要です。特に、開発当時のセキュリティ基準が古いレガシーシステムでは、この脆弱性が残存している可能性があります。

正規ユーザーのセッションIDを攻撃者が盗み出し、サーバーに対してユーザーになりすまして接続するセッションハイジャックのイメージ図

セッション固定化攻撃(Session Fixation):罠を仕掛ける手口

セッションハイジャックが「既存の有効なIDを盗む」攻撃であるのに対し、「セッション固定化攻撃(Session Fixation)」はアプローチが逆です。「攻撃者が用意したIDを被害者に使わせる」という、より巧妙な罠を仕掛ける攻撃手法です。

この攻撃の恐ろしい点は、被害者がログインする前に攻撃が始まっていることです。攻撃の流れを詳しく見ていきましょう。

攻撃のステップ:待ち伏せ型の罠

ステップ1:セッションIDの取得

攻撃者はまず、ターゲットとなるWebサイトにアクセスし、攻撃者自身のための有効なセッションIDをサーバーから取得します。この時点ではまだログインしていなくても、サーバーは「ゲストユーザー」としてセッションIDを発行することが一般的です。例えば、セッションID = ABC12345 が発行されたとします。

ステップ2:罠の設置(送り込み)

攻撃者は、取得したセッションID ABC12345 を被害者に強制的に使わせるためのリンクを作成します。例えば、URLパラメータにセッションIDを含めることができる脆弱なサイトの場合、以下のようなURLをメールやSNSで被害者に送りつけます。

http://example.com/login?PHPSESSID=ABC12345

また、悪意あるJavaScriptを仕込んだページに誘導し、そこで document.cookie を使って被害者のブラウザに直接Cookieをセットする方法もあります。この場合、被害者は何も気づかないまま攻撃者が指定したセッションIDを持たされてしまいます。

ステップ3:被害者の誘導とログイン

被害者が何も知らずにこのリンクをクリックすると、ブラウザは ABC12345 というセッションIDを持った状態でWebサイトにアクセスします。サイト側が「外部から指定されたセッションIDを受け入れる」仕様になっている場合、被害者のブラウザのCookieには ABC12345 がセットされます。この状態で、被害者が自分のIDとパスワードを入力してログインに成功したとします。

ステップ4:なりすましの完了(固定化の成立)

ここが最大のポイントです。もしシステムが「ログイン成功後も、ログイン前と同じセッションIDを使い続ける」仕様だった場合、被害者の正規のアカウント情報(権限)が、攻撃者が知っているセッションID ABC12345 に紐づいてしまいます。

攻撃者はすでに ABC12345 というIDを知っています。あとは自分のブラウザでこのIDを使ってアクセスするだけで、パスワードを知ることなく、被害者としてログイン済みの画面に入ることができます。これが「セッション固定化(Fixation)」と呼ばれる所以です。セッションIDを攻撃者が決めた値に「固定」させてしまうのです。

この攻撃の巧妙な点は、被害者が正しくログインしているため、異常に気づきにくいことです。また、攻撃者は被害者のパスワードを知る必要がなく、技術的なハードルが比較的低いため、実行されやすい攻撃手法とも言えます。

攻撃者が取得したセッションIDを被害者に強制し、ログイン後にそのIDを使ってなりすますセッション固定化攻撃の4段階フロー図

現場で役立つ防御策:攻撃を無効化する技術

脅威の仕組みを理解したところで、ここからは具体的な対策について解説します。これらの対策は単独で行うものではなく、多層防御(Defense in Depth)の考え方に基づいて組み合わせることが重要です。

1. セッションIDの再生成(Regenerate Session ID)

これはセッション固定化攻撃に対する最も有効な対策です。ログイン認証が成功したタイミングで、それまで使っていたセッションIDを破棄し、全く新しいセッションIDを発行してブラウザに送ります。

これにより、もし攻撃者が事前にセッションID(例:ABC12345)を送り込んでいたとしても、被害者がログインした瞬間にセッションIDは新しい値(例:XYZ98765)に変わります。攻撃者が知っている ABC12345 は無効になるため、なりすましを防ぐことができます。

多くのWebフレームワークには、このためのメソッド(例:PHPの session_regenerate_id(true) など)が用意されています。開発時には必ずログイン処理の中でこの関数を呼び出すように実装する必要があります。また、権限レベルが変化する場面(一般ユーザーから管理者への昇格など)でもセッションIDを再生成することが推奨されます。

2. HTTPS(常時SSL/TLS)の利用

ネットワーク盗聴に対する必須の対策です。ログインページだけでなく、セッションIDをやり取りする全てのページ(実質的にサイト全体)をHTTPS化します。これにより、通信経路上のデータが暗号化されるため、カフェのWi-Fiなどでパケットを傍受されても、セッションIDを知られることはありません。

現在では、Let's Encryptなどの無料SSL証明書サービスが普及しており、HTTPS化のコストは大幅に低下しています。常時SSL化は、もはやセキュリティの「オプション」ではなく「必須要件」と考えるべきです。また、HTTPSへのリダイレクトを適切に設定し、ユーザーが誤ってHTTPでアクセスしてしまうことを防ぐことも重要です。

3. Cookieの属性設定(Secure / HttpOnly)

Cookieを発行する際(Set-Cookieヘッダ)に、セキュリティ属性を適切に設定することで、ブラウザ側の挙動を制御し、リスクを低減できます。

Secure属性

この属性をつけると、ブラウザはHTTPS通信の時だけCookieをサーバーに送信します。暗号化されていないHTTP通信ではCookieを送らないため、平文での漏洩を防げます。全てのセッション関連のCookieには、この属性を必ず設定すべきです。

HttpOnly属性

この属性をつけると、JavaScript(document.cookie)からCookieへのアクセスが禁止されます。これにより、万が一WebサイトにXSSの脆弱性があったとしても、攻撃者がスクリプトを使ってセッションIDを盗み出すことが困難になります。この属性は、XSS攻撃に対する「最後の砦」として機能します。

SameSite属性

近年のブラウザで対応が進んでいる SameSite 属性も重要です。この属性を Strict または Lax に設定することで、クロスサイトでのCookie送信を制限し、CSRF攻撃やクリックジャッキングのリスクを低減できます。特に、SameSite=Strict を設定すると、外部サイトからのリンク経由でのアクセス時にはCookieが送信されなくなるため、セッション固定化攻撃の一部の手法を防ぐことができます。

4. セッションタイムアウトの実装

有効なセッションIDが永遠に使えてしまうと、一度盗まれた際のリスクが無限に続きます。「最終アクセスから30分経過したらログアウトさせる(無効にする)」といったタイムアウト設定を導入しましょう。

また、ブラウザを閉じた際にCookieが消えるような設定(セッションCookie)にすることも基本ですが、最近のブラウザはタブ復元機能などがあるため、サーバー側での明示的な無効化処理が重要です。さらに、「絶対タイムアウト」(ログインから一定時間経過で強制ログアウト)も併用することで、より強固な防御が実現できます。

5. URLリライティングの無効化

過去の携帯電話向けサイトなどで使われていた、URLのパラメータにセッションIDを含める方式(例:?jsessionid=...)は、URLをSNSでシェアしたり、Webサーバーのアクセスログに残ったりすることで漏洩するリスクが高いため、絶対に使用してはいけません。Cookieのみでセッション管理を行うように設定します。

特に、JavaのServlet環境などでは、デフォルトでURL rewritingが有効になっている場合があるため、明示的に無効化する設定が必要です。また、リファラーヘッダーを通じて外部サイトにセッションIDが漏洩する可能性もあるため、URLにセッション情報を含めることは避けるべきです。

6. XSS対策の徹底

HttpOnly属性を設定していても、XSS脆弱性が存在すること自体が大きなリスクです。ユーザーからの入力を表示する際には、必ず適切なエスケープ処理(サニタイゼーション)を行いましょう。フレームワークが提供するテンプレートエンジンの自動エスケープ機能を活用し、生のHTMLを直接出力することは避けるべきです。

また、Content Security Policy(CSP)ヘッダーを設定することで、インラインスクリプトの実行を制限し、XSS攻撃の影響を軽減できます。CSPは設定が複雑ですが、一度適切に設定すれば強力な防御層となります。

HTTPS、HttpOnly、ID再生成、タイムアウトという4つの主要なセッション保護策を示したインフォグラフィック

さらに深掘り:モダンなWeb開発における考慮事項

ここまでは従来のサーバーサイドセッション(Cookieとサーバーメモリ/DBを使用)を前提に話しましたが、近年のSPA(Single Page Application)やAPI中心の開発では、少し事情が異なる場合があります。

JWT(JSON Web Token)とステートレス認証

最近では、サーバー側で状態を持たない「トークンベース認証(主にJWT)」が流行しています。JWTは、認証情報を署名付きのトークンとしてクライアント側に持たせる仕組みです。この場合、サーバーはセッションIDを保存しませんが、トークン自体が「セッションIDの代わり」となります。

したがって、このトークンが盗まれれば(Local Storageへの保存によるXSSリスクなど)、セッションハイジャックと同じ被害が発生します。「JWTだから安全」ということはなく、保管場所(Cookie vs Local Storage)や有効期限の管理、HTTPSの徹底といった本質的な対策は変わりません。

むしろ、一度発行したJWTはサーバー側で即座に無効化することが難しい(ブラックリスト管理が必要になる)ため、従来のセッション管理よりもセキュリティ設計の難易度が高い側面もあります。JWTを使用する場合は、短い有効期限を設定し、リフレッシュトークンの仕組みを併用することが推奨されます。

JWT保存場所の選択:CookieかLocal Storageか

JWTの保存場所は、セキュリティ上の重要な選択です。Local StorageはJavaScriptから自由にアクセスできるため、XSS攻撃に対して脆弱です。一方、HttpOnly属性を持つCookieに保存すれば、JavaScriptからのアクセスを防げます。

ただし、Cookieを使用する場合はCSRF対策が必要になります。多くの専門家は、「HttpOnly + Secure + SameSite属性を持つCookieにJWTを保存し、別途CSRF対策を行う」アプローチを推奨しています。トレードオフを理解した上で、プロジェクトの要件に応じた適切な選択をすることが重要です。

CSRF(クロスサイトリクエストフォージェリ)との違い

セッションハイジャックとよく混同されるのがCSRFです。両者の違いを明確に理解しておきましょう。

  • セッションハイジャック: IDを盗んで「なりすます」。攻撃者が直接操作する。
  • CSRF: IDは盗まず、ユーザーのブラウザに勝手に「操作させる」。ユーザーが意図しないリクエスト(送金や設定変更など)を送信させる。

これらは攻撃のメカニズムが異なります。CSRF対策には、ワンタイムトークン(CSRFトークン)の埋め込みや、Cookieの SameSite 属性の設定が有効です。どちらもWebアプリケーションには必須の対策ですので、セットで覚えておきましょう。

マイクロサービス・API環境での課題

マイクロサービスアーキテクチャやAPIゲートウェイを使用する環境では、セッション管理がより複雑になります。複数のサービス間でセッション情報を共有する必要がある場合、RedisなどのインメモリDBを使った集中管理や、JWTによるステートレスな認証が選択されることが多いです。

この場合、各サービス間の通信もHTTPSで暗号化し、トークンの検証ロジックを各サービスに実装する必要があります。また、APIゲートウェイでの一元的な認証・認可処理を行うことで、セキュリティポリシーの統一と管理の簡素化が図れます。

実際の被害事例から学ぶ

理論だけでなく、実際にどのような被害が発生しているのかを知ることも重要です。

大規模なセッション固定化攻撃の事例

2000年代中盤、大手SNSサイトでセッション固定化の脆弱性が発見されました。攻撃者は、ログイン前のセッションIDを含むURLを大量にばらまき、そのリンクを踏んだユーザーがログインした瞬間、攻撃者がアカウントを乗っ取れる状態になっていました。この脆弱性により、数千アカウントが危険にさらされる事態となりました。

この事例では、サービス側がログイン後にセッションIDを再生成していなかったことが原因でした。その後、セキュリティパッチが適用され、ログイン時のID再生成が実装されることで問題は解決しました。

フリーWi-Fiでのセッション盗聴

カフェや空港のフリーWi-Fiを狙った攻撃も実際に多発しています。攻撃者は「Firesheep」などのツールを使い、同じネットワーク内の通信を監視します。HTTPSを使用していないサイトにアクセスしているユーザーがいれば、その通信からセッションCookieを抽出し、即座になりすましが可能になります。

この手法は技術的なハードルが低く、ツールをダウンロードするだけで誰でも実行できてしまうため、常時SSL化の重要性が広く認識されるきっかけとなりました。

セキュリティ監査とペネトレーションテスト

開発段階でどれだけ対策を施しても、実際の運用環境で脆弱性が存在しないかを確認することが重要です。

脆弱性診断ツールの活用

OWASP ZAPやBurp Suiteなどのセキュリティテストツールを使用することで、セッション管理の脆弱性を自動的に検出できます。これらのツールは、セッション固定化やセッションIDの予測可能性、Cookie属性の不備などをチェックしてくれます。

定期的な脆弱性診断を実施し、発見された問題を迅速に修正するサイクルを確立することが、継続的なセキュリティ向上につながります。

ペネトレーションテストの実施

より本格的な検証として、専門のセキュリティ企業によるペネトレーションテスト(侵入テスト)を実施することも検討すべきです。実際の攻撃者の手法を模擬し、システムの弱点を徹底的に洗い出すことで、自動ツールでは発見できない複合的な脆弱性も明らかになります。

特に、金融サービスや個人情報を多く扱うシステムでは、定期的なペネトレーションテストが業界標準となっています。

開発チームでのセキュリティ文化の醸成

技術的な対策だけでなく、組織全体でセキュリティ意識を高めることも重要です。

セキュアコーディングの教育

開発者全員が、セッション管理をはじめとするWebセキュリティの基礎知識を持つことが理想です。社内勉強会やハンズオンワークショップを定期的に開催し、最新の脅威や対策手法について学ぶ機会を設けましょう。

また、コードレビューの際にセキュリティ観点のチェックリストを用意し、セッションID再生成の実装漏れやCookie属性の設定ミスなどを早期に発見できる体制を整えることが効果的です。

セキュリティチャンピオンの配置

各開発チームに「セキュリティチャンピオン」と呼ばれる、セキュリティに詳しいメンバーを配置する企業が増えています。この担当者が、チーム内でのセキュリティ相談窓口となり、設計レビューやコードレビューでセキュリティ観点のアドバイスを提供します。

セキュリティ専門チームとの橋渡し役として機能することで、開発スピードを落とさずにセキュリティ品質を向上させることができます。

【理解度チェック】セッションハイジャック・固定化攻撃の脅威と対策(全10問)

本記事で解説した「セッションハイジャック」と「セッション固定化攻撃」。仕組みと対策を正しく理解できていますか? 攻撃者の手口は年々巧妙化しており、開発者が「知らなかった」では済まされない重大なセキュリティ事故につながる恐れがあります。

以下のクイズでは、記事の重要ポイントである「攻撃のメカニズム」から「具体的な防御策(Cookie属性やID再生成)」までを網羅的に出題します。全問正解を目指して、現在の知識レベルを確認してみましょう。

【演習】セッションハイジャックと固定化攻撃 理解度チェック(全10問)

まとめ:運用フェーズでの継続的な対策が鍵

セッションハイジャックと固定化攻撃は、Webの根幹である「信頼」を揺るがす重大な脅威です。しかし、これらは魔法のような攻撃ではなく、プロトコルの仕組みや実装の不備を突いた論理的な攻撃です。したがって、論理的に正しい対策を行えば必ず防ぐことができます。

最後に、今回のポイントを振り返ります。

  1. セッションIDは「身分証」。盗まれたら終わりと心得る
  2. ハイジャック(盗難)とフィクセーション(固定化)の違いを理解する
  3. ログイン成功時の「セッションID再生成」は必須の実装要件
  4. HTTPS、HttpOnly、Secure、SameSite属性で多層的に守る
  5. フレームワークの標準機能を使い、独自のセッション管理ロジックは避ける
  6. 定期的なセキュリティ診断とチーム全体のセキュリティ教育を怠らない

セキュリティ対策に「銀の弾丸(これさえやればOK)」はありませんが、セッション周りに関しては「定石」が存在します。この定石を確実に実装し、運用し続けること。それがエンジニアとしての信頼、そしてユーザーの安全を守る唯一の道です。

技術は日々進化し、新しい攻撃手法も次々と生まれます。しかし、セッション管理という基礎をしっかりと理解し、適切な対策を講じることができれば、多くの脅威から大切なシステムとユーザーを守ることができます。今日学んだ知識を、明日からの開発・運用に活かしていきましょう。

【次のアクション】

ご自身の管理・開発しているWebアプリケーションで、ログイン処理の前後にChromeの検証ツール(DevTools)の「Application」タブを開いてみてください。ログインボタンを押した瞬間に、Cookie内のセッションID(PHPSESSIDJSESSIONIDなど)の値が変わっているか確認してみましょう。もし変わっていなければ、セッション固定化の脆弱性があるかもしれません。今すぐチェックを!

また、Cookie属性(Secure、HttpOnly、SameSite)が適切に設定されているかも併せて確認し、不足があれば早急に対応することをお勧めします。セキュリティは「後回し」にできない、最優先の課題です。

  • この記事を書いた人

Kenta Banno

元CIOの窓際サラリーマン(50代) 。プライム上場企業の片隅で、情報処理安全確保支援士の合格を目指し奮闘中。 最新AI(Gemini/Claude)を相棒に、記事を作成しています。

-07. Webアプリケーションの脆弱性