Shikata Ga Nai

Private? There is no such things.

CSRFトークン検証のよくある実装ミスとバイパス可能なパターン

Hello there, ('ω')ノ

✅ CSRF脆弱性は「トークンがない」だけが原因ではない

最近のWebアプリではCSRFトークンが導入されていることが多いですが、 正しく実装・検証されていないことによって、トークンがあってもバイパスされるケースが頻出します。


🎯 よくあるCSRFトークン検証の実装ミス


1️⃣ トークンがHTMLに存在しているが、サーバー側で検証されていない

  • 見た目には<input type="hidden" name="csrf" value="abc123">などが存在するが、 サーバーがその値を使って照合処理をしていない

フォームに入ってるだけで安心してしまう実装ミス


2️⃣ トークンが固定(セッションごと or サイト全体で共通)

  • トークンがユーザーセッションごとに生成されていない、あるいは全ユーザー共通である
<input type="hidden" name="csrf" value="static-csrf-token">

→ 攻撃者が一度取得すればどのユーザーにも使い回し可能になる


3️⃣ トークンがCookieとフォームの両方に存在するが、突合せしていない

  • 例えば:
Cookie: csrf=abc123
Form body: csrf=xyz999

→ サーバーがどちらかの値だけを検証し、整合性を確認していない → 攻撃者が任意の値をPOSTに入れても通ってしまう


4️⃣ GETリクエストでのCSRFトークンチェックを省略している

  • 「GETだから安全」と判断して検証をスキップしてしまう実装 → 実際にはGETでもデータ更新が可能なアプリは存在する

5️⃣ トークンをURLパラメータで送っている

<form action="/change-password?csrf=abc123" method="POST">

→ URLはログやRefererで漏洩しやすく、攻撃者に値が知られるリスクが高い


✅ 攻撃者視点:このようなミスを突いてCSRFを成立させる

チェックポイント 攻撃者が調べる内容
トークンの生成頻度 固定 or 再生成されるか
値の一貫性 Cookieとフォームの値が一致しているか
GET/POSTでトークン必須か GET操作に対しても保護されているか
トークン無しで送信したときの挙動 403が返るか、それとも無視されているか

✅ まとめ:CSRFトークン実装の質=セキュリティの成否

実装チェック 安全な構成
毎回異なるトークン ✔️ セッションごとに一意なトークンを使用
トークンの突合せ ✔️ CookieとPOST本文の一致を検証
全メソッド保護 ✔️ GETでも状態変更にはトークンを要求
サーバー側検証 ✔️ トークンの有無と一致をサーバーで厳密チェック

Best regards, (^^ゞ