먼저 ssti 취약점이라는게 기억이 가물가물해서.. 한 문장으로 정리하면

사용자가 입력한 값을 서버가 단순 문자열이 아니라 템플릿 코드로 해석·실행해 의도치 않은 정보 노출이나 원격 코드 실행까지 이어질 수 있는 취약점을 말한다.

그리고 나서 이제 문제 파일 속 app.py를 보면 아래와 같은 코드 한 줄이 있다.

app.secret_key = FLAG

즉 플래그는 app.secret_key에 저장된다는 것이다.

즉, app.secret_key = FLAG를 설정하면 Flask가 자동으로 **app.config['SECRET_KEY']**에 저장한다.

즉, Flask는 내부적으로 이런 식으로 저장한다.

config = {
    'SECRET_KEY': '플래그값',
    'DEBUG': False,
    'TESTING': False,
    # ... 기타 설정들
}

결론적으로, FLAG를 구하기 위해서 app.secret_key는 config.SECRET_KEY로 접근 가능하다.

@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

이제 config.SECRET_KEY로 flag를 구하기 위해서는 위 코드를 이해해야하는데

  1. request.path를 템플릿에 직접 삽입한다. => 사용자 입력을 검사 없이 넣는다.
  1. render_template_string 사용 => {{ }} 안의 내용을 코드로 실행

두 가지가 합쳐지면 사용자가 입력한 코드가 서버에서 실행된다.

이 부분이 SSTI 취약점이 발생하는 지점이다.

즉 문제 서버 url에서 **{{config.SECRET_KEY}}**를 추가하려 로딩하면 flag를 구할 수 있게 된다.

{{ }}: Jinja2 템플릿 엔진에게 일반 텍스트가 아니라 실행할 코드라고 알려주는 표시