관리 메뉴

이사작전.com IT Blog

[jsp/java] CSRF를 1초 만에 해결하는 방법 본문

A series of lectures/Secure Coding

[jsp/java] CSRF를 1초 만에 해결하는 방법

말랑고양 플랫폼공작소 2019. 12. 16. 16:23

안녕하세요. 이사작전.com의 플랫폼공작소입니다.

오늘은 CSRF공격의 개념과 해당 공격을 방어하는 방법에 대해서 공유하려합니다.


CSRF공격이란 무엇인가?

CSRF란 "Cross-site request forgery, CSRF, XSRF)의 약어로, 사이트 간 요청 위조로써 일단 사용자가 웹사이트에 로그인한 상태에서 사이트간 요청 위조 공격 코드가 삽입된 페이지를 열면, 공격 대상이 되는 웹사이트는 위조된 공격 명령이 믿을 수 있는 사용자로부터 발송된 것으로 판단하게 되어 공격에 노출된다." 라고 정의가 내려져 있지만, 개인적으로는 [팀킬하도록 만들기] 라고 표현하고 싶습니다. CSRF 공격의 모든 과정을 요약하자면, 권한을 가진 유저가 스스로 시스템에 있는 정보를 탈취하거나 망가뜨리도록 조종하는 것이기 때문입니다. 실제 예시로, 유명 경매 사이트인 옥션에서 발생한 개인정보 유출 사건을 예시로 들 수 있습니다.


CSRF의 파급력?

[권한탈취 작업이 이뤄진 CSRF의 파급력은 상상가능한 모든 것] 이라고 요약할 수 있겠습니다. 옥션처럼 개인정보만 유출되는 것이 아니라, 시스템을 날리는 것도 이론적으로 가능할 것 같습니다. 예를 들어서 제가 oo커뮤니티의 게시판 관리자라고 가정해봅시다. 저는 그저 나쁜 글을 삭제, 즉 delete를 하고 싶었을 뿐인데 게시판의 모든 글이 날아가는 상황이 벌어지는 것이죠. 이번 예시는 게시판의 글만 날아가는 예시였으니 파급력을 한단계 높혀봅시다. 제가 소셜커머스의 시스템을 총괄하는 관리자라고 가정해봅시다. 저는 그저 아침에 출근해서 메일을 하나 읽었을 뿐인데, 소셜커머스에 등록된 모든 상품이 사라져버린 것이죠. 이처럼 CSRF의 파급력은 얼마나 강력한 권한을 가진 유저를 탈취하느냐에 달려있습니다. 아무런 권한이 없는 사람에게 접근된 CSRF는 파급력이 작은 가진 반면에 많은 권한을 가진 유저는 돌이킬 수 없는 큰 파괴력을 가지게 됩니다.



CSRF공격은 어떻게 들어오나요?

CSRF의 공격을 막으려면 우선 CSRF가 어떻게 들어오는지 알아야겠죠. 초반에 CSRF는 탐색전 같은 느낌으로 툴에 의해서 발생됩니다. 툴로써 사이트 이곳저곳 찔러보는 것이죠. 일단은 뭔가가 마구잡이로 찔러대니 웹 방화벽이 "이놈뭐지?" 하고 막지는 곳해도 탐지는 할 것입니다. 아무튼, 툴이 웹사이트의 취약점을 분석해오면 "권한탈취"라는 해커의 사회공학적 작업이 시작되는 것이죠. 



만약에 CSRF로 당신의 사이트가 해킹당했다는 것은?

CSRF로 사이트가 해킹당했다는 것은 여러가지 의미로 자아성찰의 시간이 필요합니다. 혹시 살면서 누군가에게 잘못한 일은 있었는가? 나도 모르는 사이에 나쁜 짓은 하지 않았는가? 고민이 필요해보입니다. 해커가 당신의 사이트에 아주아주 깊은 분노와 관심을 가졌다는 것을 의미하니까요. (....) CSRF로 내 사이트가 뚫렸다는 것은 해커가 작정하고 달려들어서 나를 공격했다는 것입니다. CSRF 공격의 핵심 키포인트는 "권한탈취"입니다. 아무리 보안적 개념이 없는 개발자라고 하더라도 아무런 권한도 사람이 게시물을 지울 수 있도록 코딩을 하지 않았을꺼란 말입니다. 적절한 권한을 가지고 있는 시스템 관리자가 엉뚱한 URL을 실행하도록 만드는 것이 CSRF의 작업인데, 이것은 도저히 툴이 할 수 있는 일이 아닙니다. 즉, 해커가 친히 사회공학적 작업을 했다는 것입니다. 한수원 사건처럼 말이죠.


CSRF공격이 탐지되었어요! 공격을 막고 싶어요.

만일, 당신이 사이트의 관리자이며 사이트에서 비밀번호를 변경하는 주소가 https://test.com/user.do?cmd=user_passwd_change&user=admin&newPwd=1234라고 가정해봅시다. 이러한 링크를 사용자의 메일로 보내고, 피해자가 그 메일을 읽고 링크를 클릭한다면 admin계정의 패스워드가 1234로 초기화되겠죠. 이건 아주아주 기초적인 방법이고요, XSS공격을 헬모드까지 경험해보셨으면 아시겠지만 굳이 메일까지 보낼 필요도 없습니다. 게시판에 비밀번호를 변경하게 만들어버리는 주소를 써버린다던지, img태그에 주소를 써버린다던지 방법은 수천 수만가지 입니다. 즉, CSRF를 운운하기 전에 웹 사이트 내 XSS 취약점이 해결되었는지 체크하는 것이 선행되어야 하겠습니다.


CSRF방어의 핵심은 XSS차단 + 비정상적인 루트를 통한 CUD를 막는데 있습니다.

*CUD : create,update,delete


첫번째 방어 방법 : make token & check

■ 방어개념요약 : JSP에서 랜덤 값을 생성해서 서버로 전송하거나, 로그인시 auth token 값을 생성합니다.

그리고 생성된 그 토큰을 세션에 넣어둡니다. 화면 단에선 해당 토큰을 빼내어 hidden값에 넣어놓습니다.

이런 식으로 가지고 있다가, submit 처리시 세션에 있는 값과 비교하시면 됩니다.


1. token값을 session 생성합니다.

// 로그인 시, 또는 작업화면 요청시 CSRF 토큰을 생성하여 세션에 저장합니다.

1
session.setAttribute("CSRF_TOKEN",UUID.randomUUID().toString()); // 요청 페이지에 CSRF 토큰을 셋팅하여 전송한다.
cs


2. 페이지의 hidden값에 넣습니다.

1
<input type="hidden" name="_csrf" value="${CSRF_TOKEN}" />
cs

3. form이 전송되면, 컨트롤러나 비즈니스 로직에서 해당 토큰을 받아서 검사합니다. 이놈이 form을 통해서 전송된 놈인지 이상하게 넘어온 놈인지를 체크하기 위해서요.
1
2
3
4
5
6
7
// 파라미터로 전달된 csrf 토큰 값 
String param = request.getParameter("_csrf"); // 세션에 저장된 토큰 값과 일치 여부 검증 
if (request.getSession().getAttribute("CSRF_TOKEN").equals(param)) { 
  return true
else { 
  response.sendRedirect("/"); return false
}
cs

우리 사이트는 올드한 사이트여서 적용이 힘들어요. 다른 방법은 없나요?

referer 방법도 있습니다. 같은 도메인에서 요청이 들어오지 않으면 차단하는 방법이 아직 남아있습니다.


두번째 방어 방법 : 레퍼러(CSRF를 1초 만에 해결하는 방법)

■ 방어개념요약 : 예를 들어, 같은 도메인에서 들어오는 접속은 허용하나 갑자기 완전! 엉뚱하고! 다른 곳에서! test.com/usr/을 호출할때는 차단하는 개념입니다. 물론 그런 코드를 적용할 경우, 검색을 통해 들어오는 접속도 차단되지 아래의 코드를 제시해드립니다. 네이버나 검색을 통해서 들어오는 경우는 차단하지 않는 코드입니다.

1
2
3
4
5
6
7
8
//CSRF공격을 referer방식으로 방어
String referer = request.getHeader("REFERER"); // 보안성 검토. 정상적이지 않은 방법으로 접근시 차단
if( referer != null && referer.length() > 0){
  out.println("referer : " + referer);
  out.println("You can enter");
}else{
  out.println("You can not enter");
}
cs

*코드를 자세히보시면, 어떤 도메인에서 들어오든 상관이 없는 코드입니다.

 방어개념요약 : 같은 도메인에서 들어오는 접속만 허용하는 자바스크립트

1
2
3
4
5
6
var hostName = document.referrer;
if(hostName =! 'https://이사작전.com'){
    alert('Hello admin!');
}else{
    alert('Who are you?');
}
cs

referer는 개인적으로는 좀 중요한 페이지에만 적용하면 되지 않을까? 라는 생각이 듭니다. 외부링크를 무식하게 막는 방법이기 때문입니다. 운영하시는 사이트에 관리자페이지에 적용하시거나, CUD가 이뤄지는 곳에서만 적용하는 것이 옳지 않은가? 라는 생각이 듭니다. 


그러니까, 같은 도메인에서 클릭 > 클릭 > 클릭해서 관리자페이지로 들어오는 것은 허용하되, 도메인이 다른 곳에서 갑자기! 띵하고 들어오는 것은 막는 방법입니다. 즉, 메일 URL, SNS공유, 커뮤니티에서 퍼트려진 URL 또는 카카오톡 링크든 뭐든 외부링크 접속은 다 막히는 것입니다.


도움이 되셨기를 바라며, 추가로 궁금하거나 질문사항이 있다면 댓글남겨주세요. 감사합니다

#CSRF #CSRF방어 #CSRF방어방법

0 Comments
댓글쓰기 폼