CSRF 공격 원리와 웹 애플리케이션 방어 전략

CSRF의 요청 위조 구조와 XSS와의 차이, 토큰·SameSite 쿠키·재인증·헤더 검증을 활용한 웹 보안 대응 방법을 정리한다.

2026-08-14 · 최초 발행 2025-05-29

로그인 상태를 겨냥하는 요청 위조

CSRF(Cross-Site Request Forgery)는 인증을 마친 사용자의 권한을 빌려 공격자가 원하는 작업을 수행하게 만드는 웹 보안 취약점이다. 사용자는 자신의 의사와 무관하게 삭제, 수정, 등록 같은 요청을 실행하게 될 수 있다.

공격은 브라우저가 이미 저장한 인증 정보와 서버의 신뢰 관계를 이용한다. 사용자가 대상 사이트에 로그인해 쿠키나 세션을 보유한 상태에서 악성 링크나 웹페이지를 열면, 브라우저는 요청과 함께 인증 쿠키를 보낼 수 있다. 서버가 이를 정상 요청으로 받아들이면 공격자가 유도한 작업이 처리된다.

대상 웹사이트공격자사용자대상 웹사이트공격자사용자5. 정상 요청으로 간주하고 처리1. 로그인 (인증 성공)2. 인증 쿠키 발급3. 악의적인 링크/사이트 유도4. 공격 요청 전송 (인증 쿠키 포함)6. 의도하지 않은 작업 실행 결과

요청이 위조되는 장면

인터넷 뱅킹에 로그인한 사용자가 공격자가 만든 페이지를 방문했을 때, 공격자의 계좌로 송금하는 요청이 자동 실행될 수 있다.

<img
  src="https://bank.example.com/transfer?amount=1000000&to=attacker"
  width="0"
  height="0"
/>

이 코드는 이미지 로딩으로 보이게 하면서 사용자가 알지 못한 채 송금 요청을 발생시킨다.

계정 정보 변경도 같은 방식으로 유도할 수 있다. 예를 들어 공격자는 사용자의 이메일이나 비밀번호를 바꾸는 요청을 제출하게 만들 수 있다.

<form id="hack-form" action="https://example.com/change-email" method="POST">
  <input type="hidden" name="new_email" value="hacker@evil.com" />
</form>
<script>
  document.getElementById("hack-form").submit();
</script>

CSRF와 XSS가 노리는 지점

CSRF와 XSS는 모두 웹 보안에서 자주 다뤄지지만, 공격이 성립하는 방식과 목적은 다르다.

구분 CSRF XSS
정의 인증된 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 수행하게 하는 공격 웹사이트에 악의적인 스크립트를 삽입하여 사용자 정보를 탈취하는 공격
주 목적 인증된 사용자의 권한 악용 사용자 인증 정보 탈취
공격 방향 인증된 사용자가 서버를 공격 클라이언트에서 인증정보를 공격자에게 전송
핵심 차이 인증 상태를 이용 스크립트 실행을 이용
보안 공격CSRFXSS인증된 사용자 권한 악용서버에 요청 위조악성 스크립트 삽입사용자 정보 탈취

권한이 있는 요청이 만드는 피해

CSRF가 성공하면 민감한 개인정보가 공격자에게 전송될 수 있고, 사용자 데이터가 변경될 수 있다. 같은 요청이 반복 실행되면 시스템 과부하로 이어질 가능성도 있다.

관리자 권한을 가진 사용자가 공격 대상이면 시스템 전체가 위험해질 수 있다. 금융 거래가 조작되는 경우에는 직접적인 금전적 손실도 발생한다.

요청의 출처를 확인하는 방어 수단

CSRF 토큰은 서버가 생성한 고유 토큰을 폼 제출에 포함해 요청 출처를 검증하는 방식이다.

<form action="/transfer" method="post">
  <input type="hidden" name="csrf_token" value="랜덤_생성_토큰" />
  <!-- 기타 폼 필드 -->
  <button type="submit">전송</button>
</form>

서버는 요청에 담긴 CSRF 토큰이 자신이 생성한 토큰과 일치하는지 확인한다.

SameSite 쿠키 속성도 크로스 사이트 요청에서 쿠키 전송을 제한하는 데 사용한다. Strict나 Lax로 설정할 수 있다.

Set-Cookie: sessionid=abc123; SameSite=Strict;

비밀번호 변경이나 송금처럼 중요한 작업에는 비밀번호 재확인 또는 2차 인증을 요구할 수 있다. HTTP Referer 헤더를 검사해 신뢰할 수 있는 출처의 요청인지 확인하는 방법도 있다.

# 백엔드 코드 예시 (Python)
def process_request(request):
    referer = request.headers.get('Referer', '')
    if not referer.startswith('https://trusted-domain.com'):
        return 'CSRF 공격 의심됨', 403
    # 정상 처리 로직

AJAX 요청에서는 커스텀 헤더를 추가해 검증할 수 있다. 브라우저의 same-origin 정책 때문에 외부 사이트에서는 커스텀 헤더를 추가할 수 없다.

// 클라이언트 측 AJAX 요청 예시
fetch("/api/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest", // 커스텀 헤더
  },
  body: JSON.stringify(data),
});

보호 체계를 점검하는 방법

로그인한 뒤 중요 기능을 식별하고, 해당 요청을 다른 도메인에서 트리거할 수 있는지 수동으로 테스트한다. OWASP ZAP, Burp Suite 같은 보안 테스트 도구를 활용하는 방법도 있다.

다양한 CSRF 공격 벡터를 대상으로 보호 메커니즘을 점검하면 방어 체계의 견고성을 평가할 수 있다.

Spring Security 설정 예시

Spring Security는 기본적으로 CSRF 보호 기능을 제공한다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            // 기타 보안 설정
    }
}

CSRF는 사용자의 인증 상태를 악용한다. 웹 애플리케이션에서는 CSRF 토큰, SameSite 쿠키, 사용자 재인증 같은 보호 수단을 적용해야 하며, 금융 거래나 개인정보 변경 기능에는 더 강화된 보안 조치가 요구된다.

CSRF웹 보안보안 취약점인증사이트 간 요청 위조