【実務・中級編】CSRF対策のテスト自動化と脆弱性スキャン手法 – アプリケーションセキュリティ & 安全な開発防御ガイド

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におけるセキュアな実装コード

「とりあえずセッションに突っ込めばいい」という実装は卒業しましょう。各リクエスト間でトークンを使い回さず、適切に照合する実装例です。

  • 1. トークン生成(リクエストごとにユニークなものを発行)
  • /
    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は「攻撃者から見れば簡単、防御側から見れば面倒」な脆弱性です。しかし、一度突破されれば、ユーザーのパスワード変更や決済操作を勝手に行われる致命的な被害に繋がります。

    「ツールがパスしたから安心」という思考停止は、セキュリティの世界では罪です。「もし自分が攻撃者だったら、どうやってこのトークン検証を回避するか?」という視点を常に持ち続けてください。その疑り深い姿勢こそが、あなたの守るシステムを最強にするのです。

    今日の作業が、明日誰かの大切な情報を守ることになる。その誇りを持ってコードを書いてください。

    コメント

    タイトルとURLをコピーしました