thymeleaf模板注入学习与研究--1漏洞原理
字数 1891 2025-08-12 11:34:43
Thymeleaf模板注入漏洞原理与利用分析
1. 漏洞背景
Thymeleaf是Java生态中广泛使用的模板引擎,特别是在Spring Boot应用中。模板引擎的主要作用是将参数动态嵌入到HTML中,实现动态页面渲染。然而,当开发者不当使用Thymeleaf时,可能导致模板注入漏洞,攻击者可以利用此漏洞执行任意代码。
2. 环境搭建
2.1 示例控制器代码
package com.thymeleaf.jack.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class demo {
@RequestMapping("/path")
public String path(@RequestParam String lang) {
return lang;
}
}
2.2 Maven依赖配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
3. 漏洞原理
3.1 基本工作机制
当请求/path?lang=jack时,Spring会自动查找模板文件resources/templates/jack.html并返回给用户浏览器。问题在于Thymeleaf支持SpEL(Spring Expression Language)表达式,且默认使用StandardEvaluationContext,这允许执行任意代码。
3.2 漏洞触发流程
-
攻击者构造恶意请求,如:
GET /path?lang=$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d::.x -
Spring MVC处理请求,将参数
lang的值作为视图名称返回 -
Thymeleaf尝试解析视图名称中的表达式
-
由于使用
StandardEvaluationContext,SpEL表达式被执行
3.3 关键点分析
- 表达式解析:Thymeleaf的
Expression类负责解析模板中的表达式 - 评估上下文:默认使用
StandardEvaluationContext而非限制性的SimpleEvaluationContext - 片段表达式:
::语法用于引用模板片段,攻击者利用此特性构造恶意表达式
4. Thymeleaf表达式详解
4.1 表达式类型
- 变量表达式:
${...} - 选择变量表达式:
*{...} - 消息表达式:
#{...} - 链接URL表达式:
@{...} - 片段表达式:
~{...}
4.2 片段表达式语法
片段表达式有三种形式:
~{templatename::selector}- 引用指定模板的特定片段~{templatename}- 引用整个模板~{::selector}或~{this::selector}- 引用当前模板的片段
4.3 表达式预处理
Thymeleaf支持表达式预处理,语法为__${expr}__,预处理结果会作为表达式的一部分继续处理。例如:
~{user/__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("whoami").getInputStream()).next()}__::.x/whoami}
会被预处理为:
~{user/rerce::.x/whoami}
5. Spring MVC处理流程分析
5.1 DispatcherServlet处理流程
doDispatch方法处理请求- 获取
HandlerExecutionChain - 通过
HandlerAdapter执行控制器方法 - 获得
ModelAndView对象 - 进行视图渲染
5.2 关键代码路径
RequestMappingHandlerAdapter#handleInternalinvokeHandlerMethod调用控制器方法invokeAndHandle处理返回值ViewNameMethodReturnValueHandler#handleReturnValue处理视图名称processDispatchResult进行视图渲染
5.3 漏洞触发点
漏洞实际触发点在ThymeleafView#renderFragment方法中:
- 解析片段表达式
- 执行表达式中的SpEL代码
- 由于未限制评估上下文,导致任意代码执行
6. 表达式执行深入分析
6.1 表达式执行栈
1. Expression#execute
2. FragmentExpression#executeFragmentExpression
3. StandardExpressionExecutor#execute
4. SPELVariableExpressionEvaluator#evaluate
5. SpelExpression#getValue
6. CompoundExpression#getValueInternal
7. MethodReference#getValueInternal
8. ReflectiveMethodExecutor#execute
6.2 关键类分析
- SPELVariableExpressionEvaluator:负责评估SpEL表达式
- StandardEvaluationContext:提供完整的SpEL功能,无安全限制
- ReflectiveMethodExecutor:通过反射执行方法调用
7. 防御措施
- 使用SimpleEvaluationContext:替换默认的StandardEvaluationContext
- 输入验证:对用户输入的视图名称进行严格过滤
- Thymeleaf配置:禁用或限制表达式功能
- 升级版本:使用修复了相关漏洞的新版本
8. 总结
Thymeleaf模板注入漏洞的核心在于:
- 用户输入直接作为视图名称
- Thymeleaf默认使用无限制的SpEL评估上下文
- 片段表达式语法提供了注入点
理解这一漏洞需要对Spring MVC处理流程、Thymeleaf模板渲染机制以及SpEL表达式评估有深入认识。开发者应当避免直接将用户输入作为视图名称,并合理配置表达式评估上下文。