由WCTF2020 Thymeleaf分析payload形式
字数 1719 2025-08-18 11:35:46
Thymeleaf模板注入漏洞分析与利用
1. 漏洞背景
Thymeleaf是一种现代服务器端Java模板引擎,当与Spring框架结合使用时,如果处理不当可能导致模板注入漏洞。本文基于WCTF2020比赛中的Thymeleaf题目,分析其漏洞原理及多种payload形式。
2. 环境特性
- Spring+Thymeleaf环境:当web应用基于Spring时,Thymeleaf使用SpEL表达式语言
- 独立Thymeleaf环境:使用OGNL表达式语言
3. Thymeleaf预处理机制
Thymeleaf有一个关键特性叫做表达式预处理(Expression PreProcessing),置于__...__中的内容会被预处理:
#{selection.__${sel.code}__}
预处理结果会作为表达式的一部分继续处理。
4. 请求处理流程分析
4.1 获取View的过程
-
DispatcherServlet处理流程:
- 定位到
org.springframework.web.servlet.DispatcherServlet#doDispatch() - 获取ModelAndView对象的两步关键过程:
ha.handle()applyDefaultViewName()
- 定位到
-
ModelAndView的view值获取:
- 有返回值的方法:返回值作为view值
@GetMapping("/path") public String path(@RequestParam String lang) { return "user/" + lang + "/welcome"; } - void方法:ModelAndView的view值为null
- 有返回值的方法:返回值作为view值
-
默认ViewName处理:
- 当view为null时,会获取DefaultView
transformPath()处理:- 去掉前后
/ - 将
.及之后内容当作扩展名并截掉 - 因此payload后需要增加
.以保证内容完整
- 去掉前后
4.2 表达式解析流程
-
视图渲染:
processDispatchResult()render()ThymeleafView.render()renderFragment()
-
表达式解析关键点:
- 判断viewTemplateName是否包含
:: - 调用
IStandardExpressionParser.parseExpression()解析~{viewTemplateName} - 预处理
__${}__里的内容 - 进行第二次表达式解析
- 判断viewTemplateName是否包含
-
执行特点:
- 第一次处理时,只要
__${}__语法正确,一定会被执行 - 第二次解析失败会显示原viewTemplateName值,但恶意语句已执行
- 第一次处理时,只要
5. 不同场景下的Payload分析
5.1 场景一:有返回值的控制器方法
Payload形式:
__${xxx}____${xxx}__::x
特点:
- 拼接结果为
~{user/welcome} - 第一次解析后为
~{user/xxx::/welcome}(合法语法) - 不需要
.x也能成功
5.2 场景二:void方法
Payload形式:
__${xxx}__::x.
特点:
- 使用path值作为view
- 需要
::后有值且最后有.(防止被截断)
5.3 场景三:无::的情况
Payload形式:
__${xxx}__.
特点:
- 不需要
:: - 结尾需要
.(防止被截断)
5.4 场景四:@ResponseBody注解
特点:
- 不能成功
- Spring会将返回值作为响应内容而非模板
6. 通用Payload建议
-
有回显情况:
__${}__::x.
-
无回显情况:
- 确保
__${}__语法正确 - viewTemplateName中包含
::(位置不限)
- 确保
7. 检测与防御建议
7.1 漏洞检测
- 分析控制器方法是否有返回值
- 检查是否使用@ResponseBody
- 测试不同payload形式
7.2 防御措施
- 避免用户输入直接进入模板解析
- 对用户输入进行严格过滤
- 使用最新版本的Thymeleaf和Spring框架
8. 总结
Thymeleaf模板注入漏洞的利用需要根据具体场景选择适当的payload形式。理解Spring与Thymeleaf的交互流程以及表达式解析机制是分析和利用此类漏洞的关键。在实际应用中,开发者应当注意避免不安全的模板处理方式,以防止此类漏洞的产生。