CTF & Wargame(WEB)

dreamhack insane python

KWAKBUMJUN 2025. 5. 20. 15:14

소스코드 분석

CONFIG = {
 "SECRET": "DH{fake-fake-fake}"
}

class DataConfig(object):
    def __init__(self, name):
        self.name = name

def print_data(format_string, config_data):
    return format_string.format(config_data=config_data)

config_data = DataConfig("How can I get the flag?")

@app.route('/',methods=['GET'])
def page1():    
    payload = request.args.get('body')
    sys.stdin = io.StringIO(payload)
    result = print_data(sys.stdin.readline(), config_data)
    return render_template('index.html', value=result)

<print_data 함수>

format_string, config_data를 파라미터로 받는다. 그리고 만약 format_string의 값이 {config_data}라면 

{config_data.__format__("")}를 내부적으로 호출한다. 클래스의 별도 정의가 없다면 object의 기본 구현이 동작한다. 

 

하지만 만약 {config_data.name}이라면 DataConfig의 name이 호출된다.

 

<page1() 함수>

body라는 사용자 요청을 받고 payload라는 변수에 저장한다. 그리고 sys.stdin = io.StringIO(payload)를 실행하는데, 여기서 사용자 입력인 payload가 검증 없이 들어간다 -> 취약함

다음으로는 result = print_data(sys.stdin.readline(), config_data)를 통해 sys.stdin.readline()에는 사용자의 요청이 들어가고 config_data를 print_data의 config_data 인자값으로 들어간다. 

 

익스플로잇

사용자 입력에 아무런 검증을 하지 않기 때문에

{config_data.__init__.__globals__}

를 입력하게 되면 flag를 얻을 수 있다.

 

그 이유는 config_data.__init__.__globals__는 DataConfig가 정의된 모듈의 전역 변수 사전이기 때문에 해당 웹 서비스의 모든 전역 변수를 출력해준다.

우리는 CONFIG의 값을 알아내야하기 때문에 해당 페이로드를 전송해주면

 

위와 같이 모든 전역 변수를 출력해주기 때문에

{'SECRET': 'DH{Ilovepythonandformat}'} 처럼 CONFIG의 값도 알 수 있다.

 

'CTF & Wargame(WEB)' 카테고리의 다른 글

Dreamhack Movie time table  (0) 2025.06.01
Dreamhack Switching Command  (0) 2025.05.30
dreamhack username:password@ 풀이  (0) 2025.05.20
Black-Hacker-Company  (0) 2025.05.14
SSTI 관련 문제 풀이  (0) 2025.05.04