Oh! JUN
[WebGoat] Cross-Site Request Forgeries - 1 본문
[WebGoat] Cross-Site Request Forgeries - 1
Kwon Oh! JUN 2023. 12. 23. 00:191. 문제설명
기본 CSRF 가져오기 연습
로그인한 동안 외부 소스에서 아래 양식을 트리거합니다. 응답에는 '플래그'(숫자 값)가 포함됩니다.
플래그 확인
아래 이전 페이지에서 획득했어야 하는 플래그를 확인하세요.
2. 풀이
제출 버튼을 클릭하면 [그림 - 1]와 같은 응답값을 확인할 수 있습니다.
메시지를 살펴보면, "요청이 원래 호스트로 부터 온것으로 나타난다" 문구를 확인할 수 있고
결과적으로 실패한것을 확인할 수 있습니다.
그렇다면, 해당 문제를 해결하기 위해서는 요청이 원래의 호스트가 아닌 타 호스트로 부터 오도록 설정해줘야 합니다.
제출 버튼을 누르면 요청을 보내는 주소와 요청방식을 동일하게
"http://127.0.0.1:5555/WebGoat/csrf/basic-get-flag"와 POST로 설정해줍니다.
csrf와 submit 파라미터도 동일하게 설정을 해주는데 요청 보내는 호스트의 주소만 확인하기 때문에
value값은 어떤 값을 넣든 상관없습니다.
코드 완성하고 실행시키면 [그림 - 4]와 같이 페이지가 뜹니다.
제출 버튼을 클릭하면 성공한것을 확인할 수 있습니다.
3. 코드 분석
'csrf' 파라미터 찾으면서 코드 확인해보니까 CSRFGetFlag.java 파일에서 문제의 코드를 확인할 수 있습니다.
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
String[] refererArr = referer.split("/");
요청헤더에서 host, referer 값이 있다면 그대로 변수에 담아주고 없으면 NULL 처리합니다.
referer값은 '/' 기준으로 문자를 잘라서 refererArr 배열에 저장합니다.
if (referer.equals("NULL")) {
if ("true".equals(req.getParameter("csrf"))) {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-null-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
} else {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
}
} else if (refererArr[2].equals(host)) {
response.put("success", false);
response.put("message", "Appears the request came from the original host");
response.put("flag", null);
} else {
Random random = new Random();
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
response.put("success", true);
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
response.put("flag", userSessionData.getValue("csrf-get-success"));
}
return response;
위의 코드에서 referer가 NULL이면 내부 조건문과 상관없이 'success'가 뜨게됩니다. referer는 제출 버튼을 클릭하기 이전 URL인데 referer가 없으면 원래의 호스트가 아니라고 판단해서 그렇습니다.
referer가 있으면 http://127.0.0.1:5555/WebGoat/start.mvc을 '/'을 기준으로 나누어서 refererArr[] 배열에 저장을 하게됩니다. 그리고 refererArr[2]는 [http:/공백/127.0.0.1:5555]에서 3번째인 ' 127.0.0.1:5555 '을 요청 헤더의 host와 비교를 해서 일치하면 원래의 호스트라고 판단해 'false'가 뜨고 일치하지 않으면 타 호스트라 판단해 'success'가 뜨게됩니다.
'웹 해킹 > Request Forgeries(CSRF)' 카테고리의 다른 글
[개인 공부] JSESSIONID와 CSRF 토큰 (0) | 2024.01.17 |
---|---|
[WebGoat] Cross Site Request Forgeries - 3 (0) | 2023.12.23 |
[WebGoat] Cross Site Request Forgeries - 2 (0) | 2023.12.23 |