14
6

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をHttpOnlyにしたからXSSされても安全」という最大の誤解。読めないだけで「操作」されて詰んだ

14
Posted at

はじめに:SessionIDを守り切ったはずの男

ユーザーのログイン状態を管理する「セッションID」。
これをCookieに保存する際、セキュリティ意識の高い(つもりの)私は、迷わず一つの属性を付与しました。
Set-Cookie: session_id=abc12345; HttpOnly;
「よし!これで悪意のあるJavaScript(XSS)を食らっても、document.cookie でセッションIDを盗み取られることはない。セッションハイジャックは完全に防げるぞ!」
数日後、私が管理するサイト上で、あるユーザーの掲示板アカウントから「怪しい投資用URL」が大量に自動スパム投稿される事件が起きました。(やばすぎて数分フリーズしたw)
私は混乱しました。
「なんでだ!?CookieはHttpOnlyにしてあるから、攻撃者はセッションIDを盗めないはずなのに!どうやってアイツに『なりすまし』たんだ!?」

技術解説:盗めなくても「操る」ことはできる(Session Riding)

HttpOnly 属性は、XSS対策として非常に強力かつ重要な設定です。これをつけることで、攻撃者はJavaScriptを使ってCookieの「中身を読み取る」ことができなくなります。つまり、あなたの自宅の鍵(セッションID)そのものを盗んで持ち去ることは不可能になります。
しかし、初心者の私は致命的な誤解をしていました。
XSSが存在する環境下では、攻撃者は「鍵を盗む」必要すらないのです。「あなたが鍵を開けた後の家に入り込み、あなたの代わりにボタンを押させる」ことができるからです。

恐怖の「リモートコントロール」

XSS(クロスサイトスクリプティング)によって、ユーザーのブラウザ上で不正なJavaScriptが実行されたとします。
攻撃者はセッションIDを盗めませんが、代わりにこのようなスクリプトを仕込みます。

// 【攻撃者のスクリプト】
fetch('/api/post_message', {
  method: 'POST',
  body: '変な投資のURL!登録してね!',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});

このコードがユーザーのブラウザ上で実行された瞬間、何が起きるか。
ブラウザは親切にも、「あ、同じドメイン宛ての通信だな!じゃあHttpOnlyのCookie(鍵)も一緒にくっつけて送信しといたるわ!」と気を利かせます。
結果、バックエンドサーバーは「お、正規のセッションIDを持ったユーザー本人からの書き込みリクエストだな。ヨシ!」と判断し、スパム投稿を許可してしまうのです。これを Session Riding(セッションへの相乗り)と呼びます。

HttpOnlyは「致命傷を避ける防具」にすぎない

私は「HttpOnlyを付ければ、XSS攻撃を無効化できる」と本気で信じていました。
しかし現実は、「鍵自体は盗まれないから、明日以降に他のPCからログインされる完全な乗っ取り(クローン作成)は防げる。しかし、『今その瞬間』にあなたのフリをして好き勝手に操られることまでは防げない」という絶望のルールでした。
HttpOnly は素晴らしい防具ですが、それは「即死を避けるためのヘルメット」であり、飛んでくる矢(XSS)そのものを防ぐ盾ではありません。
最も重要なのは、大前提として**「XSSを絶対に許さない(エスケープの徹底)」**という当たり前の基礎だったのです。
プロパティを1つ叩いただけで「完全にセキュアだ」と錯覚してしまった私の慢心は、こうして見事に打ち砕かれました。

14
6
4

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
14
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?