Hello there, ('ω')ノ
✅ 脆弱性の概要
CSRFトークンがCookieに依存する形式で運用されているにもかかわらず、
そのトークンがセッションを識別するためのCookie(例:session
)とは別のCookie(例:csrfKey
)に紐づいている場合、
セッションとトークンが一致しているかどうかの検証が行われず、攻撃者がトークンを偽装可能になることがあります。
📚 実際のリクエスト例
POST /email/change HTTP/1.1 Host: vulnerable-website.com Content-Type: application/x-www-form-urlencoded Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&email=wiener@normal-user.com
ここで問題となるのは:
session
はセッション管理用のCookiecsrfKey
はCSRFトークン検証用のCookie → この2つが連携していない
🎯 脆弱な実装のパターン
- フレームワークA:セッション用(例:Express, Flaskなど)
- フレームワークB:CSRFトークン用(例:DjangoのCSRFミドルウェア、AngularのCSRF保護)
→ 別々のCookieを使用し、照合処理も別々に動いている
🧠 攻撃者のバイパス方法
- 攻撃者が自身のセッションでログインし、
csrfKey
とcsrf
トークンの値を取得 - 被害者を攻撃用ページに誘導し、以下のようなHTMLを使ってCSRF攻撃を実行:
<form method="POST" action="https://vulnerable-website.com/email/change"> <input type="hidden" name="email" value="attacker@evil-user.net"> <input type="hidden" name="csrf" value="RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY"> </form> <script> document.cookie = "csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv"; document.forms[0].submit(); </script>
→ 攻撃者のcsrf
とcsrfKey
が送信されるが、
セッションCookie(session
)は被害者のものなので、
攻撃は「被害者の操作」として実行されてしまう
✅ 本来あるべき実装
実装内容 | 理由 |
---|---|
CSRFトークンはセッション情報と1対1で関連づける | 攻撃者が自分のトークンを他人に使わせることを防ぐ |
複数のCookieを使う場合は相互照合を必須にする | csrf がcsrfKey と一致するだけでは不十分 |
フレームワークのCSRF保護を統一する | セッション管理とCSRF保護を別にしない |
⚠️ よくある実装ミスの原因
原因 | 内容 |
---|---|
複数のフレームワークを併用している | バックエンドとフロントエンドで別のCSRF保護を使っている |
CookieベースのCSRF保護に依存しすぎている | JavaScriptで改ざん可能なため防御効果が限定的 |
✅ まとめ
CSRFトークンを「Cookieと一致すればOK」と判断する設計は非常に危険です。
- 攻撃者は自分の
csrfKey
とcsrf
のセットを送りつけることでバイパスが可能 - 必ず「このトークンが現在のセッションのものであるか?」をサーバー側で検証すべきです
Best regards, (^^ゞ