Thymeleaf安全研究
文章目录
简介
Thymeleaf 是一个类似Velocity、FreeMarker 的Java模板引擎,而且Spring Boot推荐使用Thymeleaf引擎。它支持 HTML 原型,在 HTML 标签中增加额外的属性来达到模板 + 数据的展示方式。
SpringBoot 提供了 Thymeleaf 的默认配置,并且为 Thymeleaf 设置了视图解析器,我们可以像以前操作 jsp 一样来操作 Thymeleaf。
基本使用
需要在 pom.xml
中引入Thymeleaf 依赖:
|
|
创建模板文件 templates\welcome.html
:
|
|
创建控制器:
|
|
当我们访问 http://127.0.0.1:8090/?msg=p1n93r
,将渲染模板给用户展示:
漏洞演示
漏洞环境:https://github.com/hex0wn/learn-java-bug/tree/master/thymeleaf-ssti
简而言之,Thymeleaf SSTI一般发生在攻击者可以控制视图名的位置,例如如下场景:
|
|
例如如下所示,利用Thymeleaf SSTI成功RCE:
预防方法
主要存在以下几种方式:
- 使用
@ResponseBody
注解; - 模板名称由
redirect:
或forward:
开始(于此不会被ThymeleafView渲染); - 控制器方法的形参中有
HttpServletResponse
,response
已经被处理;
漏洞分析
首先贴出POC:
|
|
使用thymeleaf进行模板渲染,首先会调用 org.thymeleaf.spring5.view.ThymeleafView#renderFragment()
,看到里面的代码片段及解释:
所以这也就解释了为什么POC中会存在 ::
符号。继续跟进,一直到 org.thymeleaf.standard.expression.StandardExpressionPreprocessor#preprocess()
,这个操作叫做 预处理 ,也就是预处理 __(.*?)__
中的表达式,代码的说明和解释如下:
继续跟进,发现底层其实是使用SpEL Evaluator进行执行,于是其实最终是形成一个SpEL表达式注入:
小结一下, Thymeleaf的SSTI其实出现在表达式的预处理 位置,除了前面的场景,预处理是否可以应用在模板中呢?根据官方文档:https://waylau.gitbooks.io/thymeleaf-tutorial/content/docs/standard-expression-syntax.html
可知,模板中也是支持预处理的。我们实验一下:
首先清楚,thymeleaf支持以下几种表达式:
- ${…}: 变量表达式
- *{…}: 选择表达式
- #{…}: 消息表达式
- @{…}: 链接表达式
- ~{…}: 片段表达式
我们可以在上面任意一种表达式内使用表达式预处理,例如下面所示( @{__${link}__}
):
|
|
且表达式 @{__${link}__}
中的 link
可以被攻击者控制:
|
|
可以和前面分析的一样,造成RCE:
这条链中,最终使用 EngineEventUtils.computeAttributeExpression(context, tag, attributeName, attributeValue)
来计算属性表达式:
最终会执行链接表达式内的变量表达式:
总结
使用Thymeleaf进行SSTI,需要关注以下几个地方:
- 可控的视图名。(不能使用
@ResponseBody
、HttpServletResponse
以及redirect:
和forward:
); - 模板内可控的预处理变量,例如上面例子中的
@{__${link}__}
;
参考
- https://waylau.gitbooks.io/thymeleaf-tutorial/content/docs/standard-expression-syntax.html
- https://github.com/veracode-research/spring-view-manipulation/
- https://www.veracode.com/blog/secure-development/spring-view-manipulation-vulnerability
- https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/
- https://paper.seebug.org/1332/
文章作者 P1n93r
上次更新 2021-06-15