설명
브라우저가 쿠키 같은 인증 정보를 자동으로 전송하는 환경에서, 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를 막을 수 없습니다.