Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Kim Hyeong

CSRF 본문

카테고리 없음

CSRF

김형완 2018. 11. 30. 17:23

CSRF

정의

사이트 간 요청 위조(Cross-site Request Forgery)

웹 애플리케이션 취약점 중 하나로 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 하여 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격방법을 의미한다. 2008년에 발생한 옥션 개인정보 유출사건에서도 관리자 계정을 탈취하는데 이 방법이 사용되었다. 공격의 난이도가 높지 않아 널리 사용되는 방법 중 하나다.


예시

만일, A라는 사이트의 사용자 개인 비밀번호 변경을 하는 주소 패턴이 'abc.com/user.do?cmd=user_passwd_change&user=admin&newPwd=1234'라고 한다면 이러한 링크를 사용자의 메일로 XSS 형태로 보내고 메일을 읽게되면 해당 사용자의 패스워드가 1234로 초기화된다. 이를 관리자에게 보내서 일반계정을 관리자 계정으로 바꾸도록 한다든지, 아니면 관리자 계정 패스워드를 바꾸는데 이용한다면 해당 사이트의 모든 정보가 해킹당하는데는 오랜 시간이 걸리지 않는다. 


참고로, img 태그도 GET 메소드를 사용해서 보내는 것이기 때문에 img를 이용할 수도 있다. 대부분의 사이트는 img를 필터링하지 않으므로, 혹은 필터링하지 못하므로 유용한 방법이 될 수 있다.

예를 들면 나무위키의 경우 <img src="https://namu.wiki/member/logout">와 같은 코드를 넣어주면 해당 문서를 볼 경우 로그아웃이 된다. 이는 나무위키 뿐만이 아닌 대부분의 사이트의 문제.



방어 방법

방어 방법 중 가장 기초적인 방법은 Referer 체크를 하는 방법이 있다. Referer는 HTTP 헤더에 있는 정보로 해당 요청이 요청된 페이지의 정보를 가지고 있는데 해당 정보는 Paros나 Zap, fiddler같은 프로그램으로 조작이 가능하지만 방법이 간단하여 소규모 웹사이트에 주로 이용되는 방법이다.

그 외에는 패스워드 변경 같은 민감한 정보를 다룰 때에는 세션에 임의난수(토큰)를 발급여, 해당 난수가 없는 상황에서 해당 동작들이 이루어지면 요청을 거부하는 방법을 통하여 사용자가 정말로 변경을 의도하는 경우에만 변경을 시켜주는 방법, 변경 시에 CAPTCHA를 이용하여 캡챠 인증코드가 없거나 틀리면 거부하도록 하는 방법 등이 이용되고 있다. 

또한 GET/POST 등을 구분하여 주는 것 역시 유용하다. img 태그 등을 이용할 경우 GET 요청으로 들어오게 될 것이고, 반면 흔히 하듯 form을 이용해 값을 받을 경우 POST를 이용하게 되는 경우가 많기 때문이다. 

위의 방법들을 일일이 적용하기 귀찮다면, 대개 프레임워크에서 위의 방법들을 통합한 플러그인 등을 제공하는 경우들이 많으니 찾아보도록 하자. 또한 form 대신 ajax[3]를 통한 JSON API만 사용하는 방법이 있다. 만약 굳이 다른 도메인간 통신을 하고자 한다면, jsonp를 이용하면 된다.

(출처 : 나무위키 (https://namu.wiki/w/CSRF))


적용 방법

1. taglib를 설정해주어 security 관련 태그를 사용 할 수 있게 해야한다.

<%@ taglib prefix="sec"  uri="http://www.springframework.org/security/tags" %>

위와 같이 태그를 설정을 해주고, 

ajax를 이용하여 데이터의 이동과 처리를 하려고 할 경우


<head>

<sec:csrfMetaTags/>

<meta name="_csrf" content="${_csrf.token}" />

<!-- default header name is X-CSRF-TOKEN -->

<meta name="_csrf_header" content="${_csrf.headerName}" />

</head>


헤더 안에 위와 같은 태그를 사용하여 ajax를 사용하겠다 선언을 하고, csrf공격을 막기위해 같이 메타태그를 적어주어야 한다.


또는 

global js 파일을 하나 만들어서 csrf의 공격을 막을 수 있다.

/*

 *  Cross Site Request Forgery (CSRF)

 *  protected CSRF for ajax Jquery

 */



그리고 ajax를 쓰지 않는 경우엔 아래와 같이 히든을 이용해서 token의 값을 같이 넘겨주어 공격을 방어해야 한다,

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


또한 ajax가 실행 될 때 아래와 같이 token과 header를 같이 묶어서 전송을 해주어야 한다.

(function($) {

var token = $("meta[name='_csrf']").attr("content");

var header = $("meta[name='_csrf_header']").attr("content");

$.ajax({

           beforeSend: function(xhr) {

         xhr.setRequestHeader(header, token);

          }

...

    });

});


아직 위의 문법이나 태그들은 이해가 완벽하게 되진 않았지만 위와 같이 적어주었을 경우 

405 erorr는 나지 않고 데이터가 잘넘어간다


spring security는 어려운듯 하다.

Comments