CSRF 토큰 없는 상태 변경

CSRF 토큰 없는 상태 변경

설명

브라우저가 쿠키 같은 인증 정보를 자동으로 전송하는 환경에서, 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/PUT/DELETE로 제한하고, 서버 세션에 묶인 CSRF 토큰을 검증하세요. HTTP 메서드를 바꾸는 것만으로는 CSRF를 막을 수 없습니다.

참조