-
[A03:2021 – Injection] picoCTF WebShell SSTI1Hacking/CTF 문제 풀이 2025. 5. 22. 10:25728x90반응형
평소 궁금했던 해킹을 공부하기 위해 OverTheWire Bandit 문제들을 끝내고, “그럼 이제 진짜 CTF를 한번 풀어보자” 싶어서 맨땅에 헤딩하듯 도전했습니다.
1. 시작
일단 문제를 열었더니 무슨 폼이 하나 있고 버튼이 있다.
습관적으로 일단 폼에 아무거나 적고 버튼을 누르니깐 그냥 큰 글씨로 내가 적은 그대로 보여주는 기능인가 보다.
overthewire bandit 풀던 습관인지 모르나 ls 먼저 적어봤다.
2. 분석 ( 1 )
숫자든 영어든 한글이든 특수문자든 다 똑같다.
뭐 아는 게 없으니 일단 소스코드에 뭐라도 있을까 싶어 F12로 확인해 봤지만 아무것도 없다.
뭐 POST 요청이다라는 거 빼곤 알 수 있는 게 없다.
일단 머리를 굴려보자.
DB 들락거리는 건 아닌 거 같고 내가 작성한 글자를 가지고 뭐 H1 요소로 만들어주는 건가?
근데 이게 진짜라면 이걸 풀 수는 있는 걸까?
그래도 이건 정답이 있는 문제니 깐 좀 더 생각해 보자.
입력 한 글자를 POST 방식으로 보내고 똑같은 글자를 H1 태그로 보여준다.
일단 Controller로 가고 body값을 가지고 다시 html한테 전달한다.
- Java의 Model 같은 걸로 동작하나?
그러면 JSP 같은 템플릿을 쓴다고 생각하면 되나?
3. 분석 ( 2 )
F12 누르고 네트워크를 보니까 이건 파이썬이고 Werkzeug?라는 서버란다.
Werkzeug는 Flask와 같은 Python 웹 프레임워크에서 HTTP 요청을 처리하고 WSGI 표준을 구현하는 도구라고 구글이 알려줬다.
Pyhon 웹 프레임워크를 잘 모르지만 뭐 디장고, 플라스크? 정도 있는 건 알고 있다.
구글에서 Flask는 Werkzeug를 사용한다고 한다.
구글에서 Flask는 기본적으로 Jinja2라는 템플릿 엔진을 사용한다고 한다.
근데 Werkzeug라면 Flask가 거의 확정이지만 Jinja2를 사용하는지는 확실하지 않다고 한다.
이런 건 알 방법이 없나?
하지만 여전히 모르겠다.
일단 뭐 해당 웹사이트에서 얻은 힌트를 정리하면
1. Python으로 만들어졌다.
2. 서버는 Werkzeug이 거고 Flask는 이를 기반으로 동작한다.
3. Flask의 기본 템플릿은 Jinja2이다.
구글에서 Jinja2 사용법을 알아보니 뭐 화면에 {{어쩌고}} 이런식으로 작성한다고 한다.
오? 뭐가 찾았다.
{{a}} 이렇게 적었는데 빈 화면이 나왔다.
그리고 새로운 건 리다이렉트 시키고 있다는 사실이다.
근데 {{어쩌구}} 어쩌고라는 변수를 보여주는 건가?
모르겠어서 막치다가 {{=-0}} 이런 걸 적었는데 500 에러가 나왔다.
{{-=0}}이거도 500 에러가 났다.
변수가 없으면 그냥 빈화면이 나오는 거 같은데 500 에러가 나온다는 건 이걸 변수가 아니라 뭔가 수식으로 인식하나?
{{1+1=2}} 이건 500 에러이고 {{1+1}}은 2가 출력된다.
이거 수식으로 인식한다.
4. 풀이
다시 이제 구글에 검색해 봐야겠다.
jinja2 {{}} 취약점으로 검색하니 지금 {{1+1}} 이게 2가 출력되는 게 SSTI (Server Side Template Injection)이라고 한다.
취약점을 이용하는 방법에 대해서도 상세하고 자세히 나오는 걸 보니 정말 기초적인 공격인 거 같다.
Jinja2 SSTI Research - HackMD
# Jinja2 SSTI Research This research was originally developed for [OnSecurity](https://www.onsecuri
hackmd.io
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
이걸 입력하니깐 overthewire bandit에서 본 그리웠던 사용자 정보를 볼 수 있다.
linux는 역시 {{request.application.__globals__.__builtins__.__import__('os').popen('ls -al').read()}} 해줘야지
뭐 이런 식으로 나오길래 이걸 GPT한테 정리하라고 했다.
이제 정말 끝이다.
{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}를 해주면 Flag 값을 얻을 수 있다.
5. 결론
솔직히 이번에 우연히 "=-0"이 걸 쳐서 실마리를 찾게 되었는데 이게 아니었다면 끝까지 풀지 못했을 거 같다.
그리고 해킹이라는 게 이렇게 하는 게 맞는지도 잘 모르겠다.
다른 사람들은 이걸 다 미리 알고 하는 걸까? 아니면 그냥 정말 하나하나 해보는 걸까?
"id"로 사용자 계정 확인하는 순간 진짜 도파민 미쳤다.
728x90반응형'Hacking > CTF 문제 풀이' 카테고리의 다른 글
[A03:2021 - Injection] SQL Injection을 이용한 사용자 계정 정보 탈취 - Blind SQL Injection, General SQL Injection (0) 2025.06.17 [A03:2021 - Injection] Command Injection (Low~High) - PHP (0) 2025.06.15 [Heap Dump Exposure] picoCTF WebShell head-dump (0) 2025.05.23 [Web Hacking] picoCTF WebShell n0s4n1ty 1 (0) 2025.05.23 [Buffer Overflow] picoCTF WebShell PIE TIME (0) 2025.05.22