https://dreamhack.io/wargame/challenges/39
존재하지 않는 페이지 방문시 404 에러를 출력하는 서비스입니다.
SSTI 취약점을 이용해 플래그를 흭득하는 문제입니다. 플래그는 flag.txt, FLAG 변수에 있습니 다.
SSTI 취약점
Server-Side Template Injection의 약자로, 템플릿 엔진을 사용하는 웹 애플리케이션에서 사용자의 입력을 필터링 없이 템플릿에 반영하며 발생하는 취약점입니다.
이 취약점이 존재할 경우, 공격자가 서버에서 실행되는 코드나 명령어를 삽입할 수 있어, 서버 장악까지 이어질 수 있는 중요한 취약점 중 하나입니다.
템플릿 엔진
웹사이트의 구조는 대부분, 서버에서 데이터를 HTML에 넣어서 사용자에게 보여주는 형식입니다.
이때, 데이터를 정해진 형식(=템플릿) 에 넣는 과정을 도와주는 도구가 템플릿 엔진입니다.
app.py에서 Error404를 확인해 보았습니다.
@app.errorhandler(404)
def Error404(e):
template = '''
<div class="center">
<h1>Page Not Found.</h1>
<h3>%s</h3>
</div>
''' % (request.path)
return render_template_string(template), 404
request.path 를 %s 자리에 넣어 문자열을 만들고, 그 문자열을 render_template_string() 랜더링 하고 있는 것을 확인할 수 있습니다.
이때, 별 다른 보안 없이 문자열 안에있는 내용을 그대로 렌더링 하고 있습니다. 즉, 문자열 안에 {{...}} 같은 표현이 있다면 코드처럼 해석하여 실행하는 것입니다. 이 취약점을 이용하여 문제를 해결할 수 있음을 확인할 수 있습니다.
/404Error 페이지에 접속해 보았습니다.

위 코드에서 확인했듯 Page Not Found.란 문구가 뜨며, 아래에는 %s 내용인 /404Error가 표시되고 있습니다.
SSTI 공격이 가능한지 확인해보기 위해, URL 칸에 /{{7*7}} 을 입력해 보았습니다. 그랬더니 %s 에 7*7 계산 결과인 49가 나타나고 있음을 확인할 수 있습니다.

코드의 app.secret_key = FLAG 를 보면 app.secret_key 에 접속을 하면 FLAG 값을 얻어낼 수 있음을 확인할 수 있습니다.
/{{ config['SECRET_KEY'] }} 로 공격을 시도합니다.
{{ app.secret_key }} 형식으로 접근해도, flask에서는 app 객체에 직접 접근할 수 없습니다. app은 템플릿에서 사용할 수 있는 기본 변수에 포함되지 않습니다.config를 사용합니다. config는 Flask 탬플릿 내에서 접근 가능한 설정값을 담고 있는 객체입니다. 이 안에는 애플리케이션이 작동하는 데 필요한 정보들이 들어있습니다.config에 들어가는 설정값들의 이름은 대문자로 다루는게 규칙입니다. 따라서 app.secret_key의 키 이름인 secret_key를 대문자로 바꿔준 후, config에 넣어줍니다.최종적으로 플래그를 획득할 수 있었습니다.

{{ ... }})으로 공격이 가능한지 실습해볼 수 있었습니다.config 등 다양한 방법을 통해 사용할 수 있음을 배웠습니다.config는 민감 정보들이 담겨있을 수 있어, 공격자 입장에서는 주요 타깃이기에 주의해야 합니다.render_template_string() with request.path directly injected into the template, making it vulnerable to SSTI./{{7*7}} confirmed code execution, as it rendered 49 on the page.app.secret_key is set to the flag, it cannot be accessed directly in templates. Instead, Flask’s config['SECRET_KEY'] is accessible and holds the same value./{{ config['SECRET_KEY'] }} successfully revealed the flag.{{ ... }}.app object by default.SECRET_KEY can often be accessed through config in SSTI exploits.render_template_string() with unfiltered user input is dangerous and should be avoided in secure applications.