Skill/기반기술

CSRF 방어

진열사랑 2021. 4. 21. 14:58

출처 : doctorson0309.tistory.com/605

 

CSRF공격이란 무엇인가?

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

 

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

*CUD : create,update,delete

 

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

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

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

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

 

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

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

session.setAttribute("CSRF_TOKEN",UUID.randomUUID().toString());

 

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

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

 

3. form이 전송되면, 컨트롤러나 비즈니스 로직에서 해당 토큰을 받아서 검사합니다. 이놈이 form을 통해서 전송된 놈인지 이상하게 넘어온 놈인지를 체크하기 위해서요.

// 파라미터로 전달된 csrf 토큰 값 
String param = request.getParameter("_csrf"); // 세션에 저장된 토큰 값과 일치 여부 검증 
if (request.getSession().getAttribute("CSRF_TOKEN").equals(param)) { 
  return true; 
} else { 
  response.sendRedirect("/"); return false; 
}

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

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

 

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

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

//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");
}

 

//같은 도메인에서 들어오는 접속만 허용하는 자바스크립트
var hostName = document.referrer;
if(hostName =! 'https://이사작전.com'){
    alert('Hello admin!');
}else{
    alert('Who are you?');
}