java安全开发之spring boot Thymeleaf模板注入
字数 1941 2025-08-15 21:31:56

Spring Boot Thymeleaf模板注入安全开发指南

1. Thymeleaf简介

Thymeleaf是一个用于Web和独立环境的现代服务器端Java模板引擎,类似于Python Web开发中的Jinja模板引擎。它是Spring Boot官方推荐的模板引擎。

2. Spring Boot基础知识

2.1 Spring MVC与Spring Boot关系

  • Spring Boot是Spring MVC的简化版本,在Spring MVC基础上实现了自动配置
  • 通过DispatcherServlet前端控制器拦截请求
  • 请求处理流程:
    1. DispatcherServlet拦截请求(如/users)
    2. Servlet决定使用哪个handler处理
    3. Spring检测哪个控制器匹配请求路径
    4. @RequestMapping中查找需要的信息
    5. 执行匹配的Controller方法
    6. 返回处理结果(对象列表)
    7. 根据需求返回Json或Xml格式数据

2.2 常用注解

  • @Controller:处理HTTP请求
  • @RestController@Controller的衍生注解
  • @RequestMapping:路由请求,可设置各种操作方法
  • @GetMapping:GET方法的路由
  • @PostMapping:POST方法的路由
  • @PutMapping:PUT方法的路由
  • @DeleteMapping:DELETE方法的路由
  • @PathVariable:处理请求URL路径中的参数(如/user/{id})
  • @RequestParam:处理问号后面的参数
  • @RequestBody:请求参数以json格式提交
  • @ResponseBody:返回json格式

3. 漏洞环境配置

示例项目:https://github.com/veracode-research/spring-view-manipulation/

核心漏洞代码:

@GetMapping("/path")
public String path(@RequestParam String lang) {
    return lang; //template path is tainted
}

代码含义:用户请求URL为/path,参数名称为lang,服务器通过Thymeleaf模板查找相关模板文件。例如请求/path?lang=en,服务器会查找resources/templates/en.html并返回。

4. 模板注入分析

4.1 请求处理流程

  1. DispatcherServletorg.springframework.web.servlet.ModelAndView方法中开始处理请求
  2. org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle中:
    • 通过invokeForRequest函数调用相关controller
    • 将返回值作为待查找的模板文件名
  3. org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler#handleReturnValue中:
    • 将controller返回值作为视图名称
  4. org.springframework.web.servlet.DispatcherServlet#processDispatchResult中:
    • 调用Thymeleaf模板引擎的表达式解析
    • 将视图名称解析为模板名称并加载

4.2 漏洞点

Thymeleaf允许在模板名称中使用表达式,导致当用户输入被直接作为模板名称时,可能执行任意代码。

5. 不安全的代码示例

5.1 直接返回用户输入

@GetMapping("/path")
public String path(@RequestParam String lang) {
    return lang; //template path is tainted
}

攻击Payload:

GET /path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22whoami%22).getInputStream()).next()%7d__::.x HTTP/1.1
Host: 127.0.0.1:8090
Connection: close

5.2 无返回值的Controller

根据Spring Boot定义,如果controller无返回值,则以GetMapping的路由为视图名称。

@GetMapping("/doc/{document}")
public void getDocument(@PathVariable String document) {
    log.info("Retrieving " + document);
}

攻击Payload:

GET /doc/__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

6. 修复方案

6.1 设置@ResponseBody注解

@GetMapping("/safe/path")
@ResponseBody
public String safePath(@RequestParam String lang) {
    return lang; //不再调用模板解析
}

6.2 设置redirect重定向

@GetMapping("/safe/redirect")
public String redirect(@RequestParam String url) {
    return "redirect:" + url; //调用RedirectView而非ThymeleafView
}

注意:此方案可能导致CWE-601漏洞(开放重定向),需验证重定向URL

6.3 使用HttpServletResponse

@GetMapping("/safe/doc/{document}")
public void getDocument(@PathVariable String document, HttpServletResponse response) {
    log.info("Retrieving " + document);
    //Spring认为已处理HTTP Response,不会进行视图名称解析
}

7. 最佳实践

  1. 永远不要直接将用户输入作为模板名称
  2. 对需要动态选择模板的场景,使用白名单验证用户输入
  3. 优先使用@ResponseBody注解返回数据
  4. 对于视图返回,明确指定模板路径而非使用用户输入
  5. 定期进行安全审计,检查潜在的模板注入漏洞

8. 参考资源

  1. Spring View Manipulation项目
  2. Spring Boot REST Controller教程
  3. Spring官方文档
Spring Boot Thymeleaf模板注入安全开发指南 1. Thymeleaf简介 Thymeleaf是一个用于Web和独立环境的现代服务器端Java模板引擎,类似于Python Web开发中的Jinja模板引擎。它是Spring Boot官方推荐的模板引擎。 2. Spring Boot基础知识 2.1 Spring MVC与Spring Boot关系 Spring Boot是Spring MVC的简化版本,在Spring MVC基础上实现了自动配置 通过 DispatcherServlet 前端控制器拦截请求 请求处理流程: DispatcherServlet 拦截请求(如 /users ) Servlet决定使用哪个handler处理 Spring检测哪个控制器匹配请求路径 从 @RequestMapping 中查找需要的信息 执行匹配的Controller方法 返回处理结果(对象列表) 根据需求返回Json或Xml格式数据 2.2 常用注解 @Controller :处理HTTP请求 @RestController : @Controller 的衍生注解 @RequestMapping :路由请求,可设置各种操作方法 @GetMapping :GET方法的路由 @PostMapping :POST方法的路由 @PutMapping :PUT方法的路由 @DeleteMapping :DELETE方法的路由 @PathVariable :处理请求URL路径中的参数(如 /user/{id} ) @RequestParam :处理问号后面的参数 @RequestBody :请求参数以json格式提交 @ResponseBody :返回json格式 3. 漏洞环境配置 示例项目:https://github.com/veracode-research/spring-view-manipulation/ 核心漏洞代码: 代码含义:用户请求URL为 /path ,参数名称为 lang ,服务器通过Thymeleaf模板查找相关模板文件。例如请求 /path?lang=en ,服务器会查找 resources/templates/en.html 并返回。 4. 模板注入分析 4.1 请求处理流程 DispatcherServlet 在 org.springframework.web.servlet.ModelAndView 方法中开始处理请求 在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle 中: 通过 invokeForRequest 函数调用相关controller 将返回值作为待查找的模板文件名 在 org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler#handleReturnValue 中: 将controller返回值作为视图名称 在 org.springframework.web.servlet.DispatcherServlet#processDispatchResult 中: 调用Thymeleaf模板引擎的表达式解析 将视图名称解析为模板名称并加载 4.2 漏洞点 Thymeleaf允许在模板名称中使用表达式,导致当用户输入被直接作为模板名称时,可能执行任意代码。 5. 不安全的代码示例 5.1 直接返回用户输入 攻击Payload: 5.2 无返回值的Controller 根据Spring Boot定义,如果controller无返回值,则以 GetMapping 的路由为视图名称。 攻击Payload: 6. 修复方案 6.1 设置 @ResponseBody 注解 6.2 设置redirect重定向 注意:此方案可能导致CWE-601漏洞(开放重定向),需验证重定向URL 6.3 使用HttpServletResponse 7. 最佳实践 永远不要直接将用户输入作为模板名称 对需要动态选择模板的场景,使用白名单验证用户输入 优先使用 @ResponseBody 注解返回数据 对于视图返回,明确指定模板路径而非使用用户输入 定期进行安全审计,检查潜在的模板注入漏洞 8. 参考资源 Spring View Manipulation项目 Spring Boot REST Controller教程 Spring官方文档