크로스 사이트 리퀘스트 변조는 사이트간 요청위조를 의미 합니다.
피해자의 권한으로 피해자 모르게 해커가 요청을 수행 하도록 만드는 것을 의미 합니다.
웹 취약점에서 자주 언급되면서 반드시 조치가 되어야 합니다.
특히 "결재"와 관련된 웹 어플리케이션에서는 필수이며 가장 강력한 수준의 조치가 요구 됩니다.
* 해커가 악성스크립트를 통하여 원치않는 결재, 결재정보노출 등을 할 수 있기 때문 입니다.
#방법1
가장 첫번째 방지는 크로스 사이트 스크립팅(XS)이 되지 않도록 조치하는 것 입니다.
크로스 사이트 리퀘스트 변조(CSRF)도 결국엔 크로스 사이트 스크립팅(XS)을 통해 실행되는 취약점이기 때문 입니다.
* 참고 : 크로스 사이트 스크립팅(XS) 대비
https://lts0606.tistory.com/545
#방법2
CSRF를 방지하는 방법은 특정 값을 통하여 요청(Request) 값의 상태를 결과여부에 따라 만료시키는 것 입니다.
예를들어 사용자가 결재를 진행한다고 가정 합니다.
사용자가 상품을 결재하기위해 결재 패이지로 이동하면 사용자에게 특정 값을 발행합니다.
아래는 설명을 위한 Spring 인터셉터 메소드의 모습 입니다.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class CSRFInterceptor extends HandlerInterceptorAdapter {
@Override
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
final HttpSession session = request.getSession();
String _random = RandomStringUtils.randomAlphabetic(20); //랜덤한 값을 발행 합니다.
session.setAttribute("내가만든CSRF키값", _random); //세션에 추가합니다.
return true;
}
}
이렇게 추가된 값을 브라우저에서 사용할 파일에 추가하여 줍니다.
아래 코드는 ajax함수에서 헤더에 위 인터셉터가 발행한 키 값을 붙이는 모습 입니다.
이렇게 붙여진 키 값은 이제 다시 결재 요청시 인터셉터에게 발행되게 됩니다.
<script>
function 결제함수(params){
$.ajax({
url: '결제주소',
beforeSend : function(xhr){
xhr.setRequestHeader("내가만든CSRF키값", "${sessionScope.내가만든CSRF키값}") //요렇게 담습니다
},
data: params,
type: 'POST',
success: function (res) {
},
error : function(err){
console.log('error');
}
})
}
</script>
이렇게 한 뒤에 결재요청이 성공 및 실패 여부와 상관없이 결재행동이 이루어지게되면 해당 CSRF키 값을 새로운 값으로 교체를 하게 합니다.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class CSRFInterceptor extends HandlerInterceptorAdapter {
@Override
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
final HttpSession session = request.getSession();
final String REQUEST_URL = request.getRequestURL().toString(); //URL검사
if(REQUEST_URL.equals("결재요청주소")) { //만약 결재요청이면,
String csrf_key = request.getHeader("내가만든CSRF키값"); //해더에 담긴 키
if(!csrf_key.equals(session.getAttribute("내가만든CSRF키값").toString())){ //헤더와 세션의값이 다르면!
_random = RandomStringUtils.randomAlphabetic(20); //랜덤한 값을 발행 합니다.
session.setAttribute("내가만든CSRF키값", _random);
return false; //같지않는 CSRF값으로 요청이 들어왔으므로 거짓을 반환 합니다.
}
//같은 CSRF값으로 요청이 들어왔으므로 값을 초기화합니다.(이해를위해 추가한 부분 입니다)
String random = RandomStringUtils.randomAlphabetic(20);
session.setAttribute("내가만든CSRF키값", random);
return true;
}
String _random = RandomStringUtils.randomAlphabetic(20); //랜덤한 값을 발행 합니다.
session.setAttribute("내가만든CSRF키값", _random); //세션에 추가합니다.
return true;
}
}
이러한 패턴으로 사용자에게 전달한 키 값이 변조가 되었는지를 확인하고, 요청이 완료되었으면 해당 값을 갱신하여 새로운 값을 사용자가 쓰도록 하게 해 주는 것이 크로스 사이트 리퀘스트 변조(CSRF) 방지방법 입니다.
#방법3
프레임워크의 기반의로의 조치가 필요하다면 Spring Security를 통하여 해당 조치를 하는 것 입니다.
Spring security를 활용하면 위 단계를 조금 더 CSRF값을 편리하게 사용할 수 있게 해 줍니다.
하지만 Spring 시큐리티에서도 발행하는 값과 검증을 쉽게 해 주는 것일뿐 결국 클라이언트(jsp, html, js 등)에서 해당 CSRF값을 포함하여 서버로 전송해야되는 기능이 존재 해야됩니다.
이상으로 크로스 사이트 리퀘스트 변조(CSRF) 조치 방법에 대해서 간단하게 살펴보았습니다.
궁금한점 또는 틀린 부분은 언제든 연락주세요! 👻
'웹 취약점(Web vulnerability)' 카테고리의 다른 글
16. 불충분한 인가(IN) (0) | 2021.12.07 |
---|---|
15. 세션 예측(SE) (0) | 2021.12.07 |
13. 취약한 패스워드 복구(PR) (0) | 2021.12.06 |
12. 불충분한 인증(IA) (0) | 2021.12.02 |
11. 크로스 사이트 스크립팅(XS, XSS, Cross Site Scripting) (0) | 2021.12.02 |
댓글