상세 컨텐츠

본문 제목

[SPRING SECURITY] CSRF

JAVA/SPRING

by ranlan 2021. 4. 16. 01:22

본문

728x90

CSRF(Cross Site Request Forgery) 공격

사용자 의지와 무관하게 공격자의 의도대로 서버에 특정 요청을 하도록 함

예를 들어 한 사용자가 서비스를 사용중이다. 공격자는 이와 비슷한 도메인을 가진 가짜 사이트를 하나 만들어 사용자가 접속하도록 유도한다. 동일한 화면의 가짜 사이트에 사용자는 정보를 입력하고 서버에 요청을 보낸다. 하지만 실제로 서버에 요청되는 내용은 사용자의 요청이 아닌 공격자가 심어둔 내용이다. 이렇게 사용자 권한을 이용해 서버에 변조된 요청을 보내는 공격방법을 CSRF라 한다.

 

 

CSRF Token

서버에 들어온 요청이 실제 서버에서 허용한 요청인지 확인하기 위한 토큰

서버에서 뷰 페이지를 발행할 때 마다 랜덤으로 생성된 Token을 같이 준 뒤 사용자 세션에 저장한다. 그리고 사용자가 서버에 요청을 보낼 때마다 숨겨진 Token값이 서버로 같이 전송되는데, 서버에서는 이 Token값이 세션에 저장된 값과 일치하는지 확인하여 해당 요청의 위조 여부를 판단한다. 일치 여부를 확인한 Token은 바로 폐기되고 새로운 뷰 페이지를 발행할 때 마다 새로 생성된다.

 

 

Spring Security CSRF

Spring Security 3.2.0 이후부터 지원

 

config 설정

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
        http.csrf()
        ...
    }
}

스프링 시큐리티 활성화 시 자동으로 포함됨으로 생략 가능

 

JSP 메타태그

<sec:csrfMetaTags />

메타태그를 이용한 ajax 호출

// csrf 메타태그
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");

$.ajax({
    url: baseurl + 'url',
    type: 'POST',
    dataType: 'application/json',
    data : {
        // data
    },
    beforeSend : function(xhr) {   
        xhr.setRequestHeader(header, token);
    },
    success: function () {
        // success 처리
    }, error: function () {
        // error 처리
    }
});

메타태그 없이 바로 사용

$.ajax({
    url: baseurl + 'url',
    type: 'POST',
    dataType: 'application/json',
    data : {
        // data
    },
    beforeSend: function (xhr) {
        xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");
    },
    success: function () {
        // success 처리
    }, error: function () {
        // error 처리
    }
});

Form 전송

<form action="/login" method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <input type="text" name="userame" />
    <input type="password" name="password">
    <button type="submit">로그인</button>
</form>
728x90

관련글 더보기

댓글 영역