CSRFの「自動テスト」に頼るな。防御の要は、トークンの「不変性」と「粒度」にある
こんにちは。現場で泥をすすりながらインシデント対応をしていると、よく「DASTツール(動的スキャン)を入れたからCSRF対策は完璧ですよね?」という甘い期待を耳にします。
はっきり言います。ツールは「お行儀の良い攻撃」しか試しません。 アプリケーションのビジネスロジックを理解していないツールにとって、CSRFの脆弱性は「トークンがあるかどうか」のチェックに過ぎず、トークンが「正しくバリデーションされているか」までは見てくれないことが多いのです。
今日は、教科書的な説明は抜きにして、なぜあなたのサイトがツールをすり抜けて攻撃されるのか、そしてどう実装を追い込むべきかを解説します。
—
1. なぜDASTツールだけでは不十分なのか
DAST(Dynamic Application Security Testing)ツールは、Webフォームに隠しフィールドがあるか、ヘッダーにトークンが含まれているかをスキャンします。しかし、実戦で狙われるのは以下のような「盲点」です。
- トークンの使い回し: ログイン後のセッション全域で同一のトークンを使っていませんか? 攻撃者が別アカウントで取得したトークンを、被害者のリクエストに流し込むだけで突破されます。
- 検証の欠如: トークンを生成してHTMLに埋め込んでいるだけで、サーバー側で「そのトークンが本当にそのユーザーのものか」を照合していないケース。
- PUT/PATCH/DELETEへの無頓着: POSTメソッドの対策は完璧でも、APIのPUTメソッドにはトークンチェックが漏れていることがよくあります。
—
2. 手動テストで絶対に見るべき「3つのポイント」
ツールを回した後、必ず以下の手順で手動テストを行ってください。これをやらないと、脆弱性の「死角」を見逃します。
1. トークンの「固定性」を確認:
ログインし直し、ページをリロードし、別ブラウザでトークンを比較してください。毎回変わっていなければ、それはただの「静的文字列」であり、攻撃者にとっての格好の餌食です。
2. トークンの「入れ替え」テスト:
Burp Suiteなどでリクエストをインターセプトし、他人のトークンや、あえて無効な文字列に書き換えて送信します。「200 OK」が返ってきたらアウトです。
3. HTTPメソッドのバイパス:
POSTで送るべきリクエストを、GETやPUTに書き換えて送信してみてください。多くのフレームワークはデフォルトで特定のメソッドしかトークン検証をしません。
—
3. 実践:PHPにおけるセキュアな実装コード
「とりあえずセッションに突っ込めばいい」という実装は卒業しましょう。各リクエスト間でトークンを使い回さず、適切に照合する実装例です。
/
function generate_csrf_token() {
if (empty($_SESSION[‘csrf_token’])) {
$_SESSION[‘csrf_token’] = bin2hex(random_bytes(32));
}
return $_SESSION[‘csrf_token’];
}
/
- 2. 検証ロジック(厳密に比較する)
/
function validate_csrf_token($token) {
if (!isset($_SESSION[‘csrf_token’]) || !hash_equals($_SESSION[‘csrf_token’], $token)) {
// ログを残して即座にセッションを破棄し、拒否する
error_log(“CSRF攻撃の疑い: セッションID ” . session_id());
header(‘HTTP/1.1 403 Forbidden’);
exit(‘CSRF攻撃が検知されました。’);
}
}
// フォーム側の実装では 4. インフラ側(Nginx)での最後の防波堤
アプリ側の改修が追いつかない場合や、多層防御を敷く場合は、Cookieの SameSite 属性が最強の味方になります。
Nginx設定ファイルの一部:
全てのレスポンスに対してSameSite属性を強制する
これにより、別ドメインからのリクエストでCookieが送信されなくなる
fastcgi_hide_header Set-Cookie;
add_header Set-Cookie “SameSite=Strict; Secure; HttpOnly”;
※ SameSite=Lax も有効ですが、機密性の高い操作(送金や設定変更)を行うページには Strict を強く推奨します。
—
最後に:エンジニアの心得
CSRFは「攻撃者から見れば簡単、防御側から見れば面倒」な脆弱性です。しかし、一度突破されれば、ユーザーのパスワード変更や決済操作を勝手に行われる致命的な被害に繋がります。
「ツールがパスしたから安心」という思考停止は、セキュリティの世界では罪です。「もし自分が攻撃者だったら、どうやってこのトークン検証を回避するか?」という視点を常に持ち続けてください。その疑り深い姿勢こそが、あなたの守るシステムを最強にするのです。
今日の作業が、明日誰かの大切な情報を守ることになる。その誇りを持ってコードを書いてください。
コメント