PHP CSRF(Cross-Site Request Forgery) 방지

프리터코더·2025년 5월 25일
0

php 문제 해결

목록 보기
13/79

CSRF 토큰 구현

1. 토큰 생성 및 저장

function generateCSRFToken() {
    $token = bin2hex(random_bytes(32));
    $_SESSION['csrf_token'] = $token;
    return $token;
}

2. 폼에 토큰 추가

<form method="POST" action="/process">
    <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
    <input type="text" name="username">
    <button type="submit">Submit</button>
</form>

3. 토큰 검증

function validateCSRFToken($token) {
    return isset($_SESSION['csrf_token']) && 
           hash_equals($_SESSION['csrf_token'], $token);
}

CSRF 보호 클래스

class CSRFProtection {
    public static function generateToken() {
        $token = bin2hex(random_bytes(32));
        $_SESSION['csrf_token'] = $token;
        return $token;
    }
    
    public static function verifyToken($token) {
        return isset($_SESSION['csrf_token']) && 
               hash_equals($_SESSION['csrf_token'], $token);
    }
    
    public static function getTokenField() {
        $token = self::generateToken();
        return '<input type="hidden" name="csrf_token" value="' . $token . '">';
    }
}

미들웨어 구현

class CSRFMiddleware {
    public function handle($request) {
        if ($this->isPostRequest()) {
            if (!$this->validateToken()) {
                throw new Exception('CSRF token validation failed');
            }
        }
    }
    
    private function isPostRequest() {
        return $_SERVER['REQUEST_METHOD'] === 'POST';
    }
    
    private function validateToken() {
        return isset($_POST['csrf_token']) && 
               validateCSRFToken($_POST['csrf_token']);
    }
}

보안 헤더 설정

header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');

실제 구현 예시

// 폼 처리
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (validateCSRFToken($_POST['csrf_token'])) {
        // 폼 처리 로직
        processForm($_POST);
    } else {
        // 토큰 검증 실패
        throw new Exception('Invalid CSRF token');
    }
}

API 요청 보호

// API 요청에 CSRF 토큰 추가
fetch('/api/data', {
    method: 'POST',
    headers: {
        'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
    },
    body: formData
});

모범 사례

  • 모든 POST 요청에 CSRF 토큰 사용
  • 토큰 유효성 검사
  • 세션별 고유 토큰 생성
  • 안전한 토큰 생성 방식 사용
  • 정기적인 토큰 갱신
profile
일용직 개발자. freetercoder@gmail.com

0개의 댓글