본문 바로가기

Web Hacking/Dreamhack

[Dreamhack] simple-ssti write up

SSTI 취약점이 발생하는 문제이다. SSTI란 Server Side Template Injection의 약자로 사용자 입력값이 템플릿으로 해석되어 발생하는 오류이다. 

 

코드를 보자.

 

 

코드를 보면 errorhandler가 존재한다. 404에러에 대한 로직을 처리하는 것 같다. 404 에러가 발생한 경로를 가져와 템플릿으로 정의한 변수에 넣고 있다. 이 변수는 render_template_string 함수의 인자로 넘어간다.

 

render_template_string 함수는 템플릿 구문을 해석한다. flask는 기본적으로 Jinja2 템플릿 언어를 제공하기 때문에 그에 맞는 템플릿 인젝션을 해야 한다. 

 

템플릿 언어에 따라 페이로드가 달라질 수 있다. 

 

 

위 사진은 언어를 구분하는 방법을 도식화한 사진이다. 

 

 

{{7*7}}을 넣은 결과 49가 리턴되며 템플릿 인젝션이 발생한 걸 알 수 있다. 이제 app.secret_key에 접근해서 flag를 얻을 수 있다. Flask의 경우 app.에 대한 정보들이 config 클래스에 저장이 된다. 

 

처음 풀어보는 SSTI 문제여서 새롭게 알게 된 것들이 꽤 있다.

 

먼저 SSTI가 발생할 경우 서버 측의 중요 정보들에 접근할 수 있을 뿐만 아니라 RCE까지 연계가 될 수 있다. 

 

일반적으로 os.system 같은 함수의 경우 쉘 명령어의 결과를 출력할 수는 없다. 때문에 subprocess.Popen Class를 찾은 다음 함수를 실행시켜 쉘 명령어 결과를 출력할 수 있다. 페이로드는 아래와 같다.

 

''.__class__.__mro__[1].__subclasses__()[Popen class의 인덱스 번호]

 

위 페이로드 외에도 매우 다양한 페이로드가 존재하는 듯 하다..

 

 

1. ''.__class__ -> 파이썬의 객체의 클래스를 참조하는 속성

 

2. ''.__class__.__mro__ -> 파이썬의 객체의 상속 구조를 튜플로 표현하는 속성

 

3. ''.__class__.__mro__[1].__subclasses__() -> Object 클래스가 가진 모든 하위 클래스, 즉 모든 클래스가 나온다.

 

 

ㄷㄷ! 

 

최종 페이로드는 

 

''.__class__.__mro__[1].__subclasses__()[Popen class의 인덱스 번호]('ls', shell=True, stdout=-1).communicate()