Oh! JUN

[WebGoat] Cross Site Request Forgeries - 3 본문

웹 해킹/Request Forgeries(CSRF)

[WebGoat] Cross Site Request Forgeries - 3

Kwon Oh! JUN 2023. 12. 23. 17:14

1. 문제설명


CSRF 및 Content-Type

이전 섹션에서 우리는 Content-Type 에 의존하는 것이 CSRF에 대한 보호가 아니라는 것을 보았습니다. 이 섹션에서는 CSRF로부터 보호되지 않는 API에 대해 CSRF 공격을 수행할 수 있는 또 다른 방법을 살펴보겠습니다.

이 과제에서는 다음 JSON 메시지를 엔드포인트에 게시해야 합니다.


2. 문제풀이

name, email, subject, message에 dummy값 넣어서 burp로 요청을 캡쳐해서 살펴봤습니다.

Content-Type : application/Json로 되어있는걸로 봐서 Content-Type을 변경해서 CSRF공격을 수행하는것 같습니다.


Content-Type을 enctype="text/plain"로 변경해주고

JSON 형태의 데이터를 name='{"name":"asd","email":"asd@asd","subject":"service","message":"asd"}'

로 지정해주고 burp를 다시 잡아줬습니다.


Content-Type : text/plain는 정상적으로 변경되었는데 JSON 형태의 끝에 '='이 있는것을 확인할 수 있습니다.

그래서 이를 제거하기 위해서는 다음과 같은 방법을 사용해야합니다.


dummy 키를 만들고 키에 해당하는 value 값에 '='이 들어가도록 설정하였습니다.

다시 burp를 잡고 확인해보겠습니다.


정상적으로 JSON 형태의 데이터가 만들어진것과 응답값을 확인할 수 있습니다.


3. 코드분석

//CSRFFeedback.java

boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().contains(MediaType.TEXT_PLAIN_VALUE);
correctCSRF &= hostOrRefererDifferentHost(request);
if (correctCSRF) {
	String flag = UUID.randomUUID().toString();
	userSessionData.setValue("csrf-feedback", flag);
	return success(this).feedback("csrf-feedback-success").feedbackArgs(flag).build();
}
return failed(this).build();

requestContainsWebGoatCookie(request.getCookies())는 요청헤더에서

WebGoat 쿠기값이 포함되는지 확인합니다.

 

request.getContentType().contains(MediaType.TEXT_PLAIN_VALUE)는 요청헤더에서

Content-Type인 text/plain이 포함되어 있는지 확인합니다.

 

그리고 hostOrRefererDifferentHost 함수를 참고하는데 아래에서 설명하겠습니다.


//CSRFFeedback.java
	
    private boolean hostOrRefererDifferentHost(HttpServletRequest request) {// 원래의 호스트인지 타호스트 인지 확인하는 함수
        String referer = request.getHeader("Referer");
        String host = request.getHeader("Host");
        if (referer != null) {
            return !referer.contains(host);// referer가 null이 아니면 referer에 host가 포함되어 있으면 return false 출력 (원래 호스트)
        } else {
            return true; //referer = null 이면 return true 출력 (타 호스트)
        }
    }

hostOrRefererDifferentHost 함수는 서버에 요청하는 호스트가 원래 호스트인지 타 호스트인지 확인하는 함수입니다.


//CSRFFeedback.java

boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().contains(MediaType.TEXT_PLAIN_VALUE);
correctCSRF &= hostOrRefererDifferentHost(request);
if (correctCSRF) {
	String flag = UUID.randomUUID().toString();
	userSessionData.setValue("csrf-feedback", flag);
	return success(this).feedback("csrf-feedback-success").feedbackArgs(flag).build();
}
return failed(this).build();

그래서 결과적으로 요청헤더에서 WebGoat 쿠기값과 Content-Type인 text/plain이 포함되면서 referer가 null이면 flag값이 랜덤으로 지정되면서 문제를 해결할 수 있습니다.