Dreamhack - simple-ssti (SSTI 취약점)

·2025년 7월 21일

Dreamhack-Writeups

목록 보기
25/52

simple-ssti

문제 링크

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

문제 설명

존재하지 않는 페이지 방문시 404 에러를 출력하는 서비스입니다.
SSTI 취약점을 이용해 플래그를 흭득하는 문제입니다. 플래그는 flag.txt, FLAG 변수에 있습니 다.

SSTI 취약점

Server-Side Template Injection의 약자로, 템플릿 엔진을 사용하는 웹 애플리케이션에서 사용자의 입력을 필터링 없이 템플릿에 반영하며 발생하는 취약점입니다.

이 취약점이 존재할 경우, 공격자가 서버에서 실행되는 코드나 명령어를 삽입할 수 있어, 서버 장악까지 이어질 수 있는 중요한 취약점 중 하나입니다.

템플릿 엔진

웹사이트의 구조는 대부분, 서버에서 데이터를 HTML에 넣어서 사용자에게 보여주는 형식입니다.
이때, 데이터를 정해진 형식(=템플릿) 에 넣는 과정을 도와주는 도구가 템플릿 엔진입니다.

풀이과정

  1. 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() 랜더링 하고 있는 것을 확인할 수 있습니다.
    이때, 별 다른 보안 없이 문자열 안에있는 내용을 그대로 렌더링 하고 있습니다. 즉, 문자열 안에 {{...}} 같은 표현이 있다면 코드처럼 해석하여 실행하는 것입니다. 이 취약점을 이용하여 문제를 해결할 수 있음을 확인할 수 있습니다.

  2. /404Error 페이지에 접속해 보았습니다.

    위 코드에서 확인했듯 Page Not Found.란 문구가 뜨며, 아래에는 %s 내용인 /404Error가 표시되고 있습니다.

  3. SSTI 공격이 가능한지 확인해보기 위해, URL 칸에 /{{7*7}} 을 입력해 보았습니다. 그랬더니 %s7*7 계산 결과인 49가 나타나고 있음을 확인할 수 있습니다.

  4. 코드의 app.secret_key = FLAG 를 보면 app.secret_key 에 접속을 하면 FLAG 값을 얻어낼 수 있음을 확인할 수 있습니다.

  5. /{{ config['SECRET_KEY'] }} 로 공격을 시도합니다.

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


배운점

  • SSTI 취약점을 처음으로 배우고, 어떤 방식(예 : {{ ... }})으로 공격이 가능한지 실습해볼 수 있었습니다.
  • SSTI 취약점을 방지하기 위해, 실무에서는 최대한 템플렛 렌더링 방법은 상요하지 않는 등의 주의가 필요함을 느꼈습니다.
  • 템플렛에서 바로 사용할 수 없는 변수들도 config 등 다양한 방법을 통해 사용할 수 있음을 배웠습니다.
  • config는 민감 정보들이 담겨있을 수 있어, 공격자 입장에서는 주요 타깃이기에 주의해야 합니다.
  • Flask 템플릿에서는 기본적으로 app 객체가 포함되지 않는다는걸 배웠습니다.

Summary (English)

  • The challenge involves exploiting an SSTI (Server-Side Template Injection) vulnerability in a Flask web application that returns a custom 404 error page.
  • The 404 handler uses render_template_string() with request.path directly injected into the template, making it vulnerable to SSTI.
  • Accessing /{{7*7}} confirmed code execution, as it rendered 49 on the page.
  • Although 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.
  • Exploiting /{{ config['SECRET_KEY'] }} successfully revealed the flag.
  • Key takeaways:
    • SSTI allows code injection via template expressions like {{ ... }}.
    • Flask template context does not include the app object by default.
    • Sensitive values like SECRET_KEY can often be accessed through config in SSTI exploits.
    • Use of render_template_string() with unfiltered user input is dangerous and should be avoided in secure applications.
profile
CTF 풀이 및 실습 중심 학습을 기록합니다.

0개의 댓글