사용자가 자신의 의지와 상관없이 공격자(해커)가 의도한 대로 수정,등록,삭제 등의 행위를 웹사이트에 요청하게 하는 공격
CSRF 취약점은 공격자가 사용자가 의도하지 않는 요청을 수행하게 하는 취약점이다.
예를 들어, 공격자는 로그인한 사용자의 권한을 사용하여 다른 페이지에서도 패스워드를 변경할 수 있다.
즉, 공격자는 사용자가 가지고 있는 권한 범위 내에서 악의적인 행위를 할 수 있다.
csrf 공격을 막기 위해 csrf 토큰을 사용해야 한다.
Spring Security 사용 시 별다른 설정을 하지 않더라도 기본적으로 csrf 기능이 활성화되어 있다.
- CSRF Token을 발급 후, 클라이언트로부터 요청을 받을 때마다 해당 토큰을 검증하는 방식
- CSRF protection 기능은 디폴트로 Enable 상태이며, 원한다면 해당 기능을 Disable 할 수 있음
단, REST API 서버는 stateless 하게 개발하기 때문에 사용자의 정보를 세션에 저장하지 않는다. CSRF 취약점에 대해서는 어느 정도 안전하다고 말할 수 있으므로 disable해준다.
따라서 SecurityConfig
에서 REST API 에 매칭되는 url에 csrf 예외 처리를 적용해줬다.
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().ignoringAntMatchers("/rest/**") /* REST API 사용 시 csrf 예외 처리 */
타임리프로 form 데이터 생성 시 타임리프, 스프링 MVC, 스프링 시큐리티가 조합이 되어 자동으로 csrf 토큰 기능을 지원해준다.
이 토큰 값을 통해 신뢰할 수 있는 form 데이터인지 아닌지 확인한다.
<input type="hidden" th:name="_csrf" th:value="${_csrf.token}"/>
hidden 타입으로 csrf 토큰을 넣어준다.
Spring Security에서는 form 전송 시 csrf 토큰을 함께 전송해주어야 한다. csrf 토큰 없이 요청하면 해당 요청을 막아버린다.
또한 ajax를 통한 post요청을 보낼 때에도 csrf 토큰을 같이 보내줘야한다.
header에 포함시켜서 보내야 하므로 자바스크립트를 사용한다.
넣어줬었는데도 계속해서 오류가 나는 이유는 action, name, value 앞에 th: 를 안붙여줘서 나는 문제
아래와 같이 html의 head 태그 내에 csrf meta tag를 추가해준다
<meta name="_csrf_header" th:content="${_csrf.headerName}">
<meta name="_csrf" th:content="${_csrf.token}">
jQuery ajax 요청시 csrf 값을 요청 전에 헤더에 담아서 보내면 된다.
var header = $("meta[name='_csrf_header']").attr('content');
var token = $("meta[name='_csrf']").attr('content');
$.ajax({
url: url,
beforeSend: function(xhr){
xhr.setRequestHeader(header, token);
},
success: function(res) {
console.log(res);
}
});
https://velog.io/@jyleedev/514-ajax-post-%ED%86%B5%EC%8B%A0-403-error
참고
https://velog.io/@max9106/Spring-Security-csrf
https://bepoz-study-diary.tistory.com/247
https://wave1994.tistory.com/150
https://cjw-awdsd.tistory.com/48