CSRF란 무엇인가?
CSRF(Cross-Site Request Forgery, 크로스 사이트 요청 위조)
웹 애플리케이션의 보안 취약점을 악용하여, 사용자가 원하지 않는 동작을 수행하게 만드는 공격 기법 중 하나이다.
사용자가 웹사이트에 로그인한 상태에서 사용자의 권한을 악용해 공격자가 의도한 요청을 실행하도록 유도한다.
ex)
특정 페이지에 방문할 때 저절로 로그아웃 or 게시글이 써지는 현상
은행과 같은 사이트에서 다른 사람에게 송금하는 행동을 넣는 등 상황에 따라 크게 악용될 수 있는 심각한 공격이다.
CSRF 공격의 작동 원리
1. 인증된 세션
사용자가 웹 애플리케이션에 로그인하면, 서버는 사용자에게 세션을 유지하기 위한 쿠키를 발급한다.
해당 쿠키는 사용자의 브라우저에 저장, 사용자가 해당 애플리케이션에 요청을 보낼 때마다 자동으로 포함되어 전송
2. 악의적인 사이트 방문
사용자가 웹 애플리케이션에 로그인한 상태에서 악의적인 사이트(공격자가 조작한 사이트)를 방문
3. 악의적인 요청
공격자는 악의적인 사이트에 사용자가 악의적인 사이트를 방문했을 때 사용자가 방문 중인 웹 애플리케이션에 요청을 보내는 코드를 포함시킨다.
요청에는 사용자의 세션 쿠키가 자동으로 포함되기 때문에, 요청은 정상적인 사용자 요청처럼 보인다.
4. 서버의 오인
웹 애플리케이션 서버는 이 요청이 악의적인 사이트에서 보내진 것임을 알지 못하고, 인증된 사용자 요청으로 간주
그 결과, 서버는 요청을 처리하고, 사용자가 의도하지 않은 동작이 수행
가상 시나리오
사용자가 jeubank.com(은행)에 로그인한 상태에서 공격자가 만든 attacker.com 방문 했다고 가정
attacker.com 에는 다음과 같은 숨겨진 폼이나 이미지가 있을 수 있다.
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="toAccount" value="attackerAccount">
<input type="hidden" name="amount" value="100000">
<input type="submit" value="Submit">
</form>
<script>
document.forms[0].submit();
</script>
위 코드가 실행되면, 사용자는 자신도 모르게 jeubank.com에서 공격자의 계좌로 돈을 송금하는 요청을 보내게 된다.
이 요청에는 사용자의 인증 쿠키가 포함되어, 서버는 이를 정상적인 요청으로 처리한다.
CSRF 방어 방법
CSRF 토큰 사용
가장 널리 사용되는 방어 기법으로, 서버는 사용자가 요청을 보낼 때마다 고유한 CSRF 토큰을 발급하여 HTML 폼이나 AJAX 요청에 포함
서버는 요청이 들어올 때마다 이 토큰이 유효한지 확인
Referer 검증
요청의 Referer 헤더를 확인하여 요청이 같은 사이트에서 온 것인지 검증
SameSite 쿠키 속성 사용
SameSite 쿠키 속성을 Strict 또는 Lax로 설정하여, 다른 사이트에서의 요청에 쿠키가 자동으로 포함되지 않도록 한다.
이를 통해 다른 도메인에서 오는 요청을 차단할 수 있다.
스프링 시큐리티 기본 설정
@Configuration
@EnableWebSecurity(debug = true) // todo: 운영 환경에서는 사용 금지
public class SecurityConfig {
@Bean // 함수형 인터페이스
public WebSecurityCustomizer webSecurityCustomizer(){
return web -> {
web.ignoring()
.requestMatchers("/favicon.ico")
.requestMatchers("/error")
.requestMatchers(toH2Console()); // static import 필요
//.requestMatchers(new AntPathRequestMatcher("/h2-console/**"));
};
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
return http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/auth/login").permitAll()
.anyRequest().authenticated())
.csrf(AbstractHttpConfigurer::disable) // (csrf -> csrf.disable())
.build();
}
}
@EnableWebSecurity(debug = true)
Spring Security를 활성화하는 어노테이션
debug = true 설정은 디버그 모드를 활성화하여 보안 관련 요청 및 필터 체인의 동작을 자세히 로그로 출력
보안상 중요한 정보들이 노출될 수 있기 때문에 운영환경에서는 해당 옵션을 사용하지 말자
WebSecurityCustomizer Bean
WebSecurityCustomizer
Spring Security에서 정적 자원이나 특정 요청 경로에 대해 보안 필터를 적용하지 않도록 설정
/favicon.ico, /error, 그리고 H2 콘솔 관련 요청들은 보안 필터를 무시
web.ignoring()
지정된 URL 패턴에 대해서 보안 필터를 무시하겠다는 의미
/favicon.ico와 /error 는 인증 없이도 접근할 수 있다.
toH2Console()
H2 데이터베이스 콘솔에 대한 URL
new AntPathRequestMatcher("/h2-console/**")로 대체 가능
SecurityFilterChain Bean
SecurityFilterChain
이 Bean은 보안 필터 체인을 정의
HttpSecurity 객체를 사용하여 다양한 보안 정책을 설정
authorizeHttpRequests
요청에 대한 보안 규칙을 정의
/auth/login 경로에 대한 요청은 모든 사용자가 접근할 수 있도록 허용(permitAll())하고, 그 외의 모든 요청은 인증이 필요하도록(authenticated()) 설정
csrf(AbstractHttpConfigurer::disable)
CSRF(Cross-Site Request Forgery) 보호를 비활성화
운영 환경에서 필요에 따라 설정을 변경
스프링 시큐리티 CSRF 방어
CSRF 토큰 매커니즘 사용
폼 태크를 사용하는 경우: Spring Security는 JSP나 Thymeleaf 같은 템플릿 엔진에서 CSRF 토큰을 자동으로 추가하는 기능을 제공
참고 자료
[Inpa Dev 👨💻:티스토리] [NODE / 보안] 📚 csurf 모듈 사용법 - CSRF 공격 방지
'Spring > Spring Security' 카테고리의 다른 글
[Spring Security] Remember Me (0) | 2024.09.02 |
---|---|
[Spring Security] Spring Session JDBC (2) | 2024.09.02 |
[Spring Security] 시큐리티 폼 로그인 커스텀 설정 (0) | 2024.09.02 |
비밀번호 암호화 적용하기(Spring Security Crypto) (0) | 2024.08.29 |
JWT를 이용한 인증 (0) | 2024.08.26 |