스프링/Spring Security
CSRF(Cross-Site Request Forgery) 공격이란?
PSW
2025. 2. 13. 16:32
CSRF(사이트 간 요청위조)는 공격자가 사용자를 속여서 사용자가 의도하지 않은 요청을 특정 웹 애플리케이션으로 전송하도록 만드는 웹 보안 공격이다.즉, 사용자가 웹사이트에 로그인한 상태에서, 공격자가 사용자 모르게 요청을 보내도록 유도하여 피해를 입히는 방식이다.
1. CSRF 공격의 원리
CSRF 공격은 인증된 사용자의 세션을 악용하여 원하지 않는 요청을 서버로 보내는 것이 핵심이다.
CSRF 공격 과정
- 사용자 A웹사이트(https://bank.com)에 로그인하고 세션을 유지한 상태.
- 공격자가 악성 웹사이트(B 사이트)를 운영하며, 해당 사이트에 CSRF 공격을 수행할 코드가 포함됨.
- 사용자가 B 사이트를 방문하면, https:/bank.com으로 자동으로 특정 요청을 보내는 스크립트가 실행됨.
- https://bank.com은 사용자가 로그인한 상태이므로 요청을 정상적인 사용자 요청으로 인식하고 처리.
- 사용자의 동의 없이 송금, 비밀번호 변경 등의 위험한 작업이 수행됨
CSRF 공격 예시
(1) CSRF 공격이 가능한 요청
CSRF 공격은 세션 쿠키 기반 인증이 활성화된 상태에서 발생한다.
POST /transfer HTTP/1.1
Host: bank.com
Cookie: sessionid=ABC123456
Content-Type: application/x-www-form-urlencoded
amount=1000&to=attacker_account
- 사용자가 로그인된 상태에서 이 요청이 자동으로 실행되면 CSRF 공격이 성공한다.
(2)CSRF 공격을 수행하는 악성 HTML
공격자가 다음과 같은 HTML을 만든 후, 피해자가 방문하도록 유도한다.
<html>
<body>
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="to" value="attacker_account">
</form>
<script>
document.forms[0].submit(); // 자동으로 폼을 제출하여 공격 실행
</script>
</body>
</html>
- 사용자가 로그인된 사애에서 이 페이지를 방문하면 자동으로 돈이 이체됨
(3)CSRF 공격을 수행하는 악성 이미지
공격자는 이미지 태그를 악용할 수도 있다.
<img src="https://bank.com/transfer?amount=1000&to=attacker_account">
- 사용자가 이 이미지가 포함된 페이지를 포함하면 자동으로 GET요청이 실행됨
CSRF 공격 방어 방법
(1) CSRF 토큰 사용(Spring Security 기본 방어)
- CSRF 공격을 방지한느 가장 효과적인 방법은 CSRF 토큰을 사용하는 것
- CSRF 토큰을 요청에 포함해야만 서버가 요청을 처리하도록 설정
Spring security에서 CSRF 토큰 활성화
Spring Security는 기본적으로 CSRF 방어 기능이 활성화되어 있다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // CSRF 토큰을 쿠키에 저장
)
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin(withDefaults());
return http.build();
}
}
- Spring Security는 기본적으로 CSRF 공격을 방어하며, 각 요청에서 CSRF 토큰을 확인하여 검증한다.
CSRF 토큰은 HTML 폼에 포함하기
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="CSRF_TOKEN_VALUE">
<input type="text" name="amount" placeholder="송금할 금액">
<input type="text" name="to" placeholder="받는 사람">
<button type="submit">송금</button>
</form>
- CSRF 토큰이 없으면 요청이 차단됨