[SECURITY] SSTI란

SSTI(Server Side Template Injection)

목차

  1. 정의
    1. 웹 템플릿 엔진
  2. 동작 원리
  3. 탐지 방법론: Detect → Identify → Exploit
    1. Detect(탐지)
    2. Identify(식별)
      1. 에러 메시지로 식별한다
      2. probing payload로 소거한다
      3. 단일 결과로 단정하지 않는다
  4. 보안 대책
  5. 참고

1. 정의

SSTI(Server Side Template Injection)란 서버에서 HTML을 생성할 때 사용하는 템플릿 엔진(Jinja2, Twig, FreeMarker 등)에 공격자가 의도적으로 템플릿 문법을 주입해 서버 측에서 템플릿이 해석/실행되게 만드는 취약점이다.

단순한 화면 변조를 넘어서 상황에 따라 민감정보 노출, 내부 로직 우회, 원격 코드 실행(RCE)까지 이어질 수 있다.

1.1. 웹 템플릿 엔진

템플릿 엔진(Template engine)은 템플릿 양식과 특정 데이터 모델에 따른 입력 자료를 합성하여 결과 문서를 출력하는 소프트웨어 또는 소프트웨어 컴포넌트를 말한다. 특히 웹 템플릿 엔진은 웹 문서가 출력되는 템플릿 엔진을 말한다.

HTML을 문자열로 직접 이어 붙이는 대신, 템플릿과 데이터를 분리해서 유지보수, 재사용, 가독성을 크게 높일 수 있다.

2. 동작 원리

서버 사이드 템플릿의 렌더링은 아래와 같은 흐름으로 동작한다.

410x204

출처: Tistory: /SSTI-공격-이론-및-실습-Server-Side-Template-Injection

  1. 템플릿과 컨텍스트(변수 값들)를 합쳐서
  2. 템플릿 엔진이 코드({{...}}, {%...%} 등)를 해석해
  3. 최종 HTML을 만들어서 응답한다.

SSTI는 공격자의 입력이 컨텍스트 값이 아니라, 템플릿 코드로 들어가면서 발생한다.

3. 탐지 방법론: Detect → Identify → Exploit

410x430

출처: PortSwigger: Server-side template injection

3.1. Detect(탐지)

SSTI는 명시적으로 찾지 않으면 쉽게 보이지 않기 때문에 템플릿 문법에서 흔한 특수문자 시퀀스(${{<%['"}}%>\)를 넣어 에러 또는 이상징후가 나는지로 접근한다.

컨텍스트를 구분해서 재검증한다.

  1. Plaintext Context: 사용자 입력이 결과 HTML로 그냥 출력되는 자리에 들어갈 경우이다.
    1. 산술 연산 같은 무해한 표현식을 넣은 결과가 서버에서 계산되어서 바뀌는 지 본다.
    2. 예: 7*749로 출력
    3. 계산 결과가 출력되면 서버에서 템플릿이 평가된다는 PoC가 된다.
  2. Code Context: 사용자 입력이 템플릿 표현식 내부(예: {{ ... }} 안의 변수명 자리 등)에 들어가는 경우이다.
    1. HTML 태그 등을 넣어 직접 XSS가 되는지 확인한다. 안 될 경우 빈 출력, 인코딩, 에러로 끝나는 경우가 많다.
    2. 템플릿 구문을 닫고(break out) 뒤에 임의 HTML을 붙여, 문장 밖으로 탈출되면서 임의의 출력이 가능한지를 PoC로 본다.

3.2. Identify(식별)

탐지 신호 발견 후 템플릿 엔진을 식별한다.

3.2.1. 에러 메시지로 식별한다

일부러 잘못된 문법을 넣어 에러를 유도하면, 에러 메시지에 엔진 이름, 버전이 그대로 드러나는 경우가 있다.

예: <%=foobar%>

결과 - ERB Engine:

(erb):1:in `<main>': undefined local variable or method `foobar' for main:Object (NameError)
from /usr/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:4:in `<main>'

3.2.2. probing payload로 소거한다

에러가 안 나오면, 엔진별로 문법이 비슷하다는 점을 이용해 수학 연산 probing 등을 여러 문법으로 넣고 평가되는지, 어떻게 평가되는지를 관찰해 후보를 좁혀간다.

|398x240

출처: PortSwigger: Server-side template injection

3.2.3. 단일 결과로 단정하지 않는다

같은 payload가 둘 이상의 엔진에서 성공할 수 있으니, 한 번의 성공만 보고 결론을 내리지 않는다.

4. 보안 대책

기본적으로 Injection 보안 대책을 따른다. 데이터를 명령/쿼리와 분리해야 한다. 사용자가 템플릿을 수정/제출할 수 없게 하는 것이 제일 좋다.

  • 템플릿과 데이터를 섞지 않는다.
    • 사용자 입력을 문자열 포맷팅으로 템플릿과 합치지 말고, 항상 컨텍스트 변수로만 전달한다.
  • 템플릿 컨텍스트에 위험한 객체를 넘기지 않는다.
    • 템플릿에 os, sys, 설정 객체, DB connection, request 전체 객체 등 강한 권한과 광범위한 접근 객체를 넘기지 않도록 한다.

참고

Comments

Newest Posts