CTF/웹해킹

[Dreamhack] simple-ssti

dDong2 2022. 9. 6. 21:14

문제는 다음과 같다.

 

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

 

문제 정보를 확인한 뒤,

가상환경에 진입하면 다음과 같이 나온다!

 

 

해당 두 개의 링크 중 위로 들어가게 되면

 

 

404 에러를 출력하는 /404Error 페이지가 나오고,

밑에 robots.txt 링크를 클릭하면

 

 

해당 경로와 Page Not Found 페이지가 나오게 된다.

이렇게 두 경로의 페이지만으로는 정확히 알기가 어렵다.

우선, SSTI 취약점이 무엇인지 살펴보자!

 

다음 내용은 이글루 시큐리티를 참고하였다.

(출처: https://www.igloo.co.kr/security-information/%EC%9B%B9-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%97%94%EC%A7%84-%EA%B8%B0%EB%B0%98%EC%9D%98-ssti-%EC%B7%A8%EC%95%BD%EC%A0%90-%EB%B6%84%EC%84%9D/)

 

SSTI 취약점이란?

SSTI(Server Side Template Injection) 취약점은 웹 템플릿 엔진에

공격자의 공격코드가 템플릿에 포함된 상태에서

서버에서 템플릿 인젝션이 발현되는 공격을 의미한다고 설명이 나와있다.

 

위의 내용에서 나오는 웹 템플릿 엔진은

브라우저에서 출력되는 웹 문서를 위한 템플릿 엔진이라고 한다.

예로 들면, 네비게이션 바와 같이 같은 내용을 반복적으로 작업을 수행하여

작업을 최소화할 수 있는 것을 바로 웹 템플릿 엔진이라고 할 수 있다.

즉, 반복되는 요소를 템플릿화하여 동적으로 변경되는 데이터 부분만 결합하여

개발자가 소스코드를 효율적으로 관리하고 직관적인 확인이 가능해진다.

 

출처에 나온 템플릿 엔진이 적용된 소스코드를 살펴보았을 때,

navbar.html을 작성해두고 파이썬 프레임워크(플라스크, 장고)의 템플릿 태그로하여,

{% block content %} {% endblock %} 및 {% block script %} {% endblock %}으로

네비게이션 바를 효율적으로 관리하고 있는 모습을 보여주고 있다.

 

나는 장고를 간단하게 공부해봤기 때문에 수월하게 이해할 수 있었다.

하지만, 이러한 편리함도 잠시 SSTI는 웹 템플릿 엔진을

공격하는 행위이기 때문에 위험하다고 볼 수 있다.

이러한 템플릿 태그 코드에 공격자가 템플릿 구문을 이용한 악성 페이로드를 삽입하게 되면

공격자가 원하는 액션을 수행하도록 할 수 있는 것이 바로 SSTI 취약점이다.

 

또한, SSTI는 XSS, CSRF 뿐만 아니라

RCE, SSRF 공격으로도 연결될 수 있어서 위험도가 높다고 한다.

이러한 SSTI 취약점을 점검하기 위해서는 템플릿 별 문법을 숙지하고 있어야 한다.

해당 취약점 대응방안으로 render_template_string() 함수가 아닌,

render_template() 함수를 사용하여 대처하는 등의 대응방안이 존재한다.

또는, Input Validation 으로 특수문자 구문들을 escape 처리한다.

 

어쩌다보니, SSTI 취약점 공부시간으로 가게 되었는데

이번에는 문제의 코드를 살펴보자!!

 

app = Flask(__name__)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

app.secret_key = FLAG


@app.route('/')
def index():
    return render_template('index.html')

@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

app.run(host='0.0.0.0', port=8000)

 

인덱스 경로에는 볼게 없는것 같고,

Error404 함수에서는 errorhandler404를 핸들링해주고 있는 모습이다.

이때, 위에서 살펴본 SSTI 취약점인 render_template_string 함수를 사용하고 있는 것을

볼 수가 있다. (이걸 위해 공부한것인가..!!!)

또한, 렌더링되고 있는 html에 %s 문자열을 받고 있고 request.path를 받고 있다.

그렇다면 우리는 /flag.txt를 출력해야하고, 현재 /robots.txt가 입력되어있던것처럼

값을 조작하게 된다면..?

바로 행동에 옮겨보자.

 

 

h3 태그로 받고 있는 곳이 request.path이고 해당 내용을 조작하기위해

host.dreamhack.games:port/404Error URL의 파라미터 값을 조작하게 된다면?

 

 

어림도 없다.

왜냐하면, FLAG는 app.secret_key에 저장되어 있기 때문이다.

 

여기서 템플릿 언어를 사용하여 secret_key를 출력하는 방법은 다음과 같다.

해당 app.py는 플라스크로 작성되어있고,

중요 설정 내용들은 config에 들어있기에 {{config}}를 작성해주면 된다!!

 

 

그럼 다음과 같이 config 설정 내용들이 출력되고,

FLAG 값이 출력된다!!

 

 

Clear.