CSRFトークンのない状態変更

CSRFトークンのない状態変更

説明

ブラウザーがCookieなどの認証情報を自動送信する環境で、CSRF対策なしにパスワード変更やデータの削除・更新などを許可すると、攻撃者がユーザーの権限で意図しないリクエストを送る可能性があります。

想定される影響

ユーザーの意思に反するアカウント設定、データ、権限の変更につながるおそれがあります。

対処方法

状態変更をPOST/PUT/DELETEに限定し、サーバーのセッションに結び付いたCSRFトークンを検証してください。HTTPメソッドを変えるだけではCSRFを防げません。

例

認証済みユーザーのパスワード変更処理の抜粋です。$userIdはリクエスト値ではなくサーバーセッションのユーザー識別子で、$hashはサーバーが生成したパスワードハッシュです。セッションの初期化とエラー処理は省略しています。checkToken()は実装を省略したアプリケーション関数であり、トークンがない場合や無効な場合は拒否して処理を中止する必要があります。

変更前

php
<?php
if (isset($_GET['Change'])) {
    $stmt = $db->prepare('UPDATE users SET password = ? WHERE user_id = ?');
    $stmt->bind_param('si', $hash, $userId);
    $stmt->execute();
}

変更後

php
<?php
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit;
}

checkToken($_POST['user_token'] ?? '', $_SESSION['session_token'], 'index.php');
$stmt = $db->prepare('UPDATE users SET password = ? WHERE user_id = ?');
$stmt->bind_param('si', $hash, $userId);
$stmt->execute();

説明:

  • 変更前: GETリクエストでパスワードを変更し、CSRFトークンを検証しません。
  • 変更後: POSTを必須とし、更新前にセッションに結び付いたCSRFトークンを検証します。HTTPメソッドの制限だけではCSRFを防げません。

参考資料