[Dreamhack] Hangul

https://dreamhack.io/wargame/challenges/1847

 

Hangul

Description플래그 파일은 플래그의 형식은 WaRP{...}입니다.

dreamhack.io

 

from flask import Flask, request, render_template_string
import re
import unicodedata

app = Flask(__name__)

# 페이지에서 사용자 입력을 출력하는 부분
@app.route("/", methods=["GET", "POST"])
def index():
    message = ""
    if request.method == "POST":
        message = request.form["message"]
        if re.search("[a-zA-Z]", message):
            message = "한글을 사용합시다!"
        message = unicodedata.normalize("NFKC", message)    # for normalize Windows and Mac Hangul implementation
    return render_template_string('''
        <form method="POST">
            Message: <input type="text" name="message">
            <input type="submit">
        </form>
        <p>Repeat your message:</p>
        <div>%s</div>
    ''' % message)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

 

플래그 파일은 /home/hangul/flag에 있다고 한다.

re.search("[a-zA-Z]", message) 입력에 ASCII 영문자가 하나라도 있으면 지정 문자열로 바꾸어 버린다.

% message 문자열 포매팅으로 템플릿 문자열 안에 그대로 끼워 넣어 렌더링한다.

 

서버에 접속하면 이렇게 문자열을 입력할 수 있는 칸이 주어진다.

 

코드로 보아, 한글을 입력하면 그대로 출력하는 것 같고, 영어를 입력하면 지정된 문자열이 출력된다.

사용자가 준 값을 템플릿에 그대로 삽입하고 있기 때문에, jinja 표현식을 넣으면 최종 html에 그대로 들어간다.

영문자 필터가 정규화보다 먼저 일어나서, 풀와이드 영문으로 필터를 우회할 수 있다.

필터 우회 -> 정규화로 ASCII 변환 -> SSTI 실행

 

전각은 영문이나 숫자 같은 문자를 한글, 한자와 같은 2바이트 폭으로 표시하는 형태이다.

보통 ASCII 알파벳/숫자는 반각으로 표시되는데, 전각은 각 글자가 더 넓어서 모양이 다르다.

정규식은 반각 알파벳만 잡아내고 있기 때문에 이 점을 이용했다.

 

도커 파일을 살펴보면,

chmod 755 /home/$user/flag 모두 읽기가 가능한 상태이다.

USER $user hangul 권한으로 Flask가 뜨고 당연히 /home/hangul/flag도 읽을 수 있다.

SSTI + 전각 우회 페이로드로 그대로 파일 읽기를 시도할 수 있다.

 

{{ config.__class__.__init__.__globals__['__builtins__']['open']('/home/hangul/flag').read() }}

 

이렇게 플래그가 출력되는 것을 볼 수 있다.

 

'해킹 스터디' 카테고리의 다른 글

[Dreamhack] Grand Theft Auto  (0) 2025.08.24
[Dreamhack] Not-only  (0) 2025.08.15
[Dreamhack] I LOVE XSS!  (0) 2025.08.10
[Dreamhack] node-serialize  (0) 2025.08.10
[Dreamhack] Secure Secret  (3) 2025.08.03