안녕하세요 오늘은 CSRF(Cross-Sirte Request Forgery Attack)
에 대해 알아보겠습니다.
요즘 프로젝트 진행을 하면서 사용자 인증 & 인가 부분을 담당하고 있습니다. 이때 Spring Security
와 Oauth2.0
을 사용하고 있는데요. 이때 Spring Security
설정을 위해 작성하는 코드에서 대부분에 코드에 CSRF
을 비활성화 해놓습니다.
지금까지는 다른 사람의 코드를 참고했기 때문에 당연하게 비활설화 했지만 이유를 알고 사용하자는 생각에 이번 기회에 CSRF
에 대해 자세히 알아보고자 합니다 👨💻
// Security 설정을 위한 SecurityConfig 클래스 내부
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable() // csrf 비활성화
.authorizeRequests()
.antMatchers("/members/**").permitAll()
.antMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
/** JwtAuthenticationFitler 를 먼저 적용 **/
http.headers().frameOptions().disable();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.headers()
.frameOptions()
.sameOrigin();
return http.build();
}
본격적으로 CSRF
에 대해 알아보겠습니다.
CSRF 공격은 웹 어플리케이션 취약점 중 하나로 인터넷 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정,삭제,등록 등) 을 특정 웹사이트에 요청하게 만드는 공격입니다.
즉 악의적으로 인증된 사용자로 가장해 해당 웹 사이트에 서버로 자신이 원하는 요청을 보내는 행위입니다.
CSRF
는 공격 난이도가 높지 않아 흔히 사용되지만 요즘 서버는 해당 공격에 대해 방어책을 잘 마련해놓습니다.
하지만 간혹 보안이 취약한 서버는 CSRF
공격에 노출되기 쉽습니다.
그럼 방식과 원리로 CSRF
공격이 가능한 걸까요?
CSRF
공격 과정에 대해 간단하게 알아보겠습니다.
1. 사용자는 보안이 취약한 서버에 로그인합니다.
2. 로그인 이후에 서버에 저장된 세션 정보를 사용할 수 있는 Session Id
가 사용자 브라우저 쿠키
에 저장됩니다.
3. 공격자는 서버에 인증된 브라우저의 사용자가 악성 스크립트 페이지를 누르도록 유도합니다.
ex) 게시판에 악성 스크립트를 게시글로 작성하여 클릭하도록 유도, 메일을 통해 악성 스크립트 전달 등
4. 사용자가 악성 스크립트가 작성된 페이지 접근 시 쿠키에 저장된 Session Id
는 브라우저에 의해 자동적으로 함께 서버에 요청 -> 이때 공격자는 해당 페이지에 접근시 어떤 방식으로 서버에 요청을 보낼지를 알고 있어야 함.
5. 서버는 쿠키
에 담긴 Session Id
을 통해 해당 요청이 인증된 사용자의 요청이라고 판단 후 처리합니다.
CSRF
공격을 하기 위해서 꼭 필요한 전제조건에 대해 알아보겠습니다.
1. 사용자가 이미 해당 서버로부터 인증을 받은 상태여야 합니다.
2. 쿠키 기반으로 서버 세션 정보를 획득할 수 있어야 합니다.
3. 공격자는 서버를 공격하기 위한 API 요청 방법에 대해 미리 알고 있어야합니다.
위와 같은 전제 조건이 왜 필요한지 구체적으로 알아볼까요? 🤔
CSRF
공격자 입장에서는 해당 서버로 요청을 보내려면 인증 과정을 거친 후여야 합니다.
왠만한 서버는 인증 로직을 가지고 있을 것이며, 사용자가 로그인 과정을 거쳐 인증 상태를 얻지 않는 이상은 공격자는 커녕 실제 해당 웹 사이트의 사용자도 요청을 보내지 못할것입니다.
따라서 CSRF
공격자는 이미 로그인된 즉 인증을 받은 상태인 사용자들을 대상으로 공격을 실행할 수 밖에 없습니다.
결론부터 말하자면 No cookies = No csrf
입니다.
즉 쿠키가 없다면 CSRF
공격도 불가능합니다. 그 이유는 CSRF
공격은 인증된 사용자에게 악성 스크립트를 포함한 웹 페이지를 통해 이루어 지는데 공격이 진행될 때 기존에 사용자가 인증과정에서 얻은 Session Id
이 필요합니다.
Session Id
는 일반적으로 쿠키를 통해 전달되는데 그렇기에 쿠키 기반으로 서버 세션 정보를 획득 할 수 없다면 당연히 공격이 불가능합니다.
CSRF
공격을 하기 위해서 공격자는 사용자가 악성 스크립트가 포함된 페이지에 접근하도록 유도할 것이고 해당 페이지에는 공격자가 원하는 API 요청 코드가 숨겨져 있을 것입니다.
하지만 공격자가 API 요청 방법에 대해 알지 못하면 백날, 사용자의 인증 상태를 획득해서 사용자인 척 서버에 요청을 보내봤자 소용없습니다.
따라서, 공격자는 서버가 받을 수 있는 요청 방식에 대해 알고 있어야 합니다.