경주장

[Form 인증 API] CSRF, CsrfFilter 본문

스프링/스프링 시큐리티

[Form 인증 API] CSRF, CsrfFilter

달리는치타 2022. 2. 7. 14:14

사이트 간 요청 위조 Cross Site Request Forgery(CSRF)는 사용자가 인증받은 웹 어플리케이션에서 원하지 않는 action을 하도록 하는 공격입니다. 

 

공격 시나리오

1. 사용자는 웹 사이트(vulnerable.com)에 접속하여 정삭적인 쿠키를 발급받습니다.

2. 공격자는 악성 html 페이지가 장성된 페이지의 링크(vulnerable.com/post/my-bad-post)를
이메일, 게시판 등의 경로를 이용해 전달합니다.


3. 공격용 HTML 페이지는 사용자가 인증한 웹 사이트의 요청정보를 이미지 태그로 전달합니다.
<img src= "https://vulnerable.com/delete-my-account">


4. 이용자가 공격용 웹 페이지를 열면, 브라우저는 이미지 파일을 받아오기 위해 공격용 url을 엽니다.

5. 이미 웹 사이트(vulnerable.com)의 인증을 받은 사용자이므로 브라우저는 인증 쿠키를 가지고 있습니다.
 vulnerable.com의 api정책에 따라 사용자의 계정이 삭제 됩니다!!

 

대표적인 방법으로는 CSRF-token이 있습니다.

사용자의 세션에 램덤한 수를 저장하여 사용자의 모든 요청에 대하여 서버단에서 검증하는 방식입니다.

 

서버에서는 정상적인 요청 페이지 (뷰페이지)를 발행할때 램덤한 토큰을 함께 발행하여 해당 페이지에서 들어올 수 있는 요청의 폼의 액션태그로 요청이 들어오는 경우 토큰에 대한 동일성을 검증합니다.

그렇게 되면 공격자가 img에 src태그로 임의로 심어놓은 주소에대한 요청은 csrf 토큰 검증에 막혀 요청이 거부됩니다.

 

 

 


스프링 시큐리티는 csrf 토큰기능을 기본적으로 제공합니다.

CSRF protection is enabled by default
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf();
}

 

csrf토큰을 활용하기 위해서는 뷰페이지의 모든 폼에 아래와 같은 input을 hidden으로 넣어 주어야합니다.

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

 

 

CsrfFilter는 csrf토큰을 관리하는 CsrfTokenRepository를 가지며 요청에대한 csrf토큰 발행과 검증을 담당합니다. 검증에 실패하면 accessDeniedHandler를 통해 AccessDeniedException을 전달합니다.

 

Spring MVC에서 제공하는 <form:form> 태그를 사용하거나 Thymeleaf 2.1이상이면서 @EnableWebSecurity를 사용한 경우에는 CsrfRequestDataValueProcessor가 적용되어 필요한 form에 자동으로 CSRF 토큰이 포함되게 됩니다.