セッションハイジャック — パスワードを変えても、止まらない

セッションハイジャックは、ログイン状態(Cookie・トークン)を盗まれ、パスワードを知らない攻撃者が「あなたとして」入られること。2段階認証も通り抜ける。NordVPN の分析では1年で524億件超、日本関連だけで約1.89億件の Cookie が盗まれた。ログインは合鍵を渡す行為。盗まれる前提で、①盗まれにくく ②短時間しか使えず ③気づいたら無効化できる設計に。AIが作るのは①の半分だけ。

動画で見る

結論から

セッションハイジャックは、ログイン状態そのもの(Cookie やトークン)を盗まれ、パスワードを知らない攻撃者が「あなたとして」入られることです。パスワードを変えても止まりません。2段階認証も通り抜けます。すでに「ログイン済みの証明書」を持っているからです。NordVPN の調査では、2025年6月〜2026年6月の1年間で、情報窃取型マルウェアに盗まれた Cookie は世界で 524億件超、日本関連だけで約 1億8,900万件でした。

この記事で伝えたいのは、この一点だけです。ログインは「合鍵」を渡す行為。合鍵は盗まれる前提で、①盗まれにくくし、②盗まれても短時間しか使えず、③気づいたら無効にできる設計にする。 この3つのうち、AI が作るアプリに最初から入っているのは、だいたい①の半分だけです。

  • 何が起きるか:ユーザーのパソコンに入ったマルウェア(インフォスティーラー)や、XSS、公衆 Wi-Fi の盗聴で Cookie が盗まれる。攻撃者はそれを自分のブラウザに貼るだけで、ログイン画面を通らずに本人になる
  • なぜ:サーバーは「この Cookie を持っている人=本人」としか判断できない。Cookie が長期間有効で、どこからでも使えて、本人が無効化する手段が無いと、盗まれた瞬間に終わり
  • 直す:Cookie に HttpOnly Secure SameSite。セッションの有効期限を短く(数時間〜数日)。「全端末からログアウト」機能。重要な操作(パスワード変更・支払い)の前に再認証
  • 確かめる:開発者ツールで Cookie の属性と有効期限を見る。別のブラウザに Cookie を貼って入れるか試す。1週間後もログインしたままなら、有効期限が長すぎる

動画版(約2分半)は本文の上に埋め込んであります。

① 何が起きるのか:パスワードを知らずに、本人になる

例として、AIで作った予約アプリにログインしたとします。サーバーは「ログイン成功」の印として、ブラウザに小さな文字列(セッション Cookie)を渡します。以後、ブラウザはページを開くたびにその文字列を付けて送り、サーバーはそれを見て「佐藤さんだ」と判断します。パスワードを毎回打たなくて済むのは、この仕組みのおかげです。

では、その文字列を、誰かがコピーしたら。

攻撃者は自分のブラウザの Cookie 欄にそれを貼り、あなたのアプリを開きます。ログイン画面は出ません。そのまま佐藤さんの画面です。予約も、住所も、支払い情報も見える。パスワードは知らない。2段階認証も、すでに通過した扱いです。

これがセッションハイジャックです。盗む方法は主に3つ。インフォスティーラー(パソコンに入り、ブラウザに保存された Cookie を丸ごと送るマルウェア。現在もっとも多い)。XSS(→ XSS の記事。スクリプトで document.cookie を送る)。盗聴(HTTPS でない通信を公衆 Wi-Fi などで覗く。→ HTTPS の記事)。

規模は小さくありません。NordVPN が2026年8月に公開した分析では、1年間で盗まれた Cookie は524億件超、1秒あたり約1,600件。日本に関連する Cookie だけで約1億8,900万件でした。盗まれた Cookie の件数は、パスワードやカード情報など他の盗難データを合計した数の4.6倍です。攻撃者にとって、パスワードより Cookie の方が価値がある、ということです。

セッションハイジャック:合鍵は盗まれる前提で、盗まれにくく・短時間・無効化できる

② なぜ起きるのか:サーバーは「合鍵を持つ人=本人」としか見られない

サーバーには、Cookie を送ってきたのが本人のブラウザか、攻撃者のブラウザかを見分ける手段が、基本的にありません。合鍵を持っている人を家に入れるのと同じです。だから、合鍵の扱い方が安全性を決めます。3つの観点で見ます。

① 盗まれにくいか。 Cookie に HttpOnly(JavaScript から読めない=XSS で盗みにくい)、Secure(HTTPS でしか送らない=盗聴されない)、SameSite(他サイトから使われない)が付いているか。AI はここまでは、だいたい付けます。 ただし、インフォスティーラーはブラウザの保存領域から直接読むので、この3つでは防げません。

② 盗まれても、短時間しか使えないか。 セッションの有効期限が「30日」「無期限」だと、盗まれた合鍵が1か月使えます。有効期限を短くし(数時間〜数日)、使うたびに延長する(スライド式)のが基本です。AI は「ログインし直すのが面倒」を避けて、長く設定しがちです。

③ 気づいたら、無効にできるか。 「全端末からログアウト」「ログイン中の端末一覧」「パスワード変更時に全セッション破棄」。これが無いと、本人が異変に気づいてパスワードを変えても、盗まれた Cookie はそのまま使い続けられます。Google や銀行が「ログイン履歴」画面を持っているのは、このためです。AI は頼まれない限り、作りません。

Supabase Auth や Firebase Auth、NextAuth などの認証サービスは、①と②の初期値が比較的まともで、③の API(refresh token の失効、signOut({ scope: 'global' }) など)も用意されています。自前でセッションを作っている場合は、3つとも確認が要ります。

③ どう直すのか:AIに「3つの観点」で頼む

以下をそのまま AI ツールに貼ってください。

「このプロジェクトのセッション管理を確認してください。①セッション Cookie(またはトークンの保存場所)に HttpOnly Secure SameSite=Lax が付いているか。トークンを localStorage に保存している場合は、その理由と XSS 時のリスクを説明してください。②セッションの有効期限は何日ですか。長期間(7日超)なら、短い有効期限+利用時の自動延長に変更してください。③パスワード変更時に既存の全セッションを無効化していますか。していなければ追加してください。あわせて、ユーザーが「全端末からログアウト」できる機能を追加してください。認証サービス(Supabase / Firebase / NextAuth)を使っている場合は、その設定値を具体的に示してください。」

ポイントは、「localStorage の理由を説明して」。AI はトークンを localStorage に置くことがあり、これは XSS ひとつで丸ごと盗まれます。Cookie(HttpOnly)の方が安全です。

④ 直ったかを確かめる:Cookie を「貼って」みる

  • 開発者ツール → Application → Cookies で、セッション Cookie の HttpOnly Secure にチェック、SameSite が Lax 以上、Expires が数日以内か見る
  • 同じ画面の Local Storage に token jwt session のような名前のものが無いか。あれば要注意
  • 別のブラウザ(またはシークレットウィンドウ)に、その Cookie の値を貼って、アプリを開く。ログイン画面を通らずに入れるのは仕様どおり(それがセッション)。ここでパスワードを変更し、貼った側のブラウザが追い出されるかを見る。追い出されなければ ✗(③が無い)
  • 1週間ログインしっぱなしにして、まだ入れるなら有効期限を見直す
  • 分からなければ、AIに「パスワード変更後に古いセッション Cookie でアクセスすると 401 になることを確認するテストを書いて」

自分で直せないとき:エンジニアに送る一文

「セッション Cookie の属性・有効期限と、パスワード変更時のセッション無効化を確認してください。全端末からログアウトできる機能も追加をお願いします。トークンが localStorage に入っていれば HttpOnly Cookie への移行も検討してください。」

よくある質問

2段階認証を付ければ防げますか。

ログイン時の本人確認は強くなりますが、ログイン後に盗まれた Cookie には効きません。2段階認証は「入口」、セッション管理は「入った後」の話です。両方要ります。

ユーザーのパソコンにマルウェアが入るのは、こちらの責任ではないのでは。

盗まれること自体は防げません。でも「盗まれた合鍵が1か月使える」「本人が無効化できない」のは、アプリ側の設計です。②と③があれば、被害は「数時間・本人が気づくまで」に縮みます。

JWT を使っています。サーバーにセッションを持たない設計なので、無効化できないと言われました。

その通りで、JWT は「発行したら期限まで有効」が基本です。だから JWT を使うなら、有効期限を短く(15分など)し、refresh token 側で失効管理するのが定石です。認証サービスはそうなっています。自前の JWT で有効期限が「30日」なら、それが穴です。

この穴が塞がれば、ログインは安全ですか。

「盗まれた後」の被害は小さくなります。「そもそも盗ませない」には XSS(→ XSS の記事)と HTTPS(→ HTTPS の記事)が効きます。「パスワードを当てられる」は別の話です(→ ブルートフォースの記事)。