绕过限制:若依模板注入在高版本 Thymeleaf 中的绕过分析
字数 1717 2025-08-30 06:50:35

若依CMS高版本Thymeleaf模板注入绕过分析

前言

本文详细分析若依CMS系统中存在的Thymeleaf模板注入漏洞及其在高版本中的绕过技术。该漏洞允许攻击者在特定条件下执行任意代码,危害性极高。

技术背景

若依CMS简介

若依CMS是一款基于Java开发的开源内容管理系统,主要特点包括:

  • 开源免费
  • 模块化设计
  • 用户友好的界面
  • 强大的文章管理功能
  • 完善的权限管理
  • SEO友好
  • 活跃的社区支持

Thymeleaf模板引擎

Thymeleaf是Java生态中广泛使用的模板引擎,主要特性:

  • 自然模板:直接使用标准HTML
  • 表达式语言(OGNL)
  • 支持多种视图解析(HTML/XML/JS/CSS)
  • 丰富的标签和属性
  • 与Spring框架深度集成
  • 国际化支持

漏洞原理分析

漏洞触发流程

  1. Handler封装ModelAndView对象

    • 请求经过DispatcherServlet#doDispatch方法
    • 调用invokeHandlerMethod方法初始化ModelAndViewContainer
    • 通过反射为returnValue赋值
    • 设置viewName
  2. 处理ModelAndView对象获取view

    • processDispatchResult方法处理返回结果
    • render方法准备渲染视图
    • resolveViewName解析视图名称
  3. 渲染view

    • ThymeleafView#render方法完成实际渲染
    • 通过renderFragment处理模板片段
    • TemplateName不包含::时,直接使用viewTemplateName
    • 包含::时解析为templateNamemarkupSelectors

关键注入点

漏洞核心在于Thymeleaf对SpEL表达式的处理:

  1. 输入被preprocess方法预处理
  2. 符合正则匹配的表达式被提取
  3. StandardExpressionParser.parseExpression解析表达式
  4. expression.execute执行表达式

测试过程

漏洞特征

  • 返回值或路径可控的路由
  • 参数型注入点(如String类型参数)

限制条件

  • Thymeleaf 3.0.12及以上版本
  • 默认payload无法直接使用

绕过技术分析

版本差异

高版本Thymeleaf新增了两个关键防护机制:

  1. checkViewNameNotInRequest

    • 新版本会将输入转为小写
    • 检查requestURI.contains(vn)
    • 若匹配则抛出异常
  2. containsSpELInstantiationOrStatic

    • 防止使用T字符实例化对象
    • 检测以下模式:
      • 对象实例化(如new SomeClass
      • 静态方法调用(如T(SomeClass)

绕过checkViewNameNotInRequest

利用viewNamerequest.getRequestURI()解析差异:

  1. 双斜杠绕过

    • 原始payload: /doc/__${payload}__::.x
    • 绕过payload: doc//__${payload}__::.x
    • 原理:标准化处理会删除一个/,导致requestURI不匹配
  2. 分号绕过

    • payload: doc;/__${payload}__::.x
    • 原理:getCachedPathValue处理URL时的差异

绕过containsSpELInstantiationOrStatic

  1. 添加空格

    • 在表达式关键部分添加不影响执行的空格
    • 如:T (java.lang.Runtime)而非T(java.lang.Runtime)
  2. 其他干扰字符

    • 可尝试添加不影响表达式执行的字符

最终利用

结合两种绕过技术,构造有效payload:

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

或:

doc;/__${T (java.lang.Runtime).getRuntime().exec("calc")}__::.x

防御建议

  1. 升级到最新Thymeleaf版本
  2. 对用户输入进行严格过滤
  3. 禁用不必要的SpEL表达式功能
  4. 实施严格的输入验证机制

参考

若依CMS高版本Thymeleaf模板注入绕过分析 前言 本文详细分析若依CMS系统中存在的Thymeleaf模板注入漏洞及其在高版本中的绕过技术。该漏洞允许攻击者在特定条件下执行任意代码,危害性极高。 技术背景 若依CMS简介 若依CMS是一款基于Java开发的开源内容管理系统,主要特点包括: 开源免费 模块化设计 用户友好的界面 强大的文章管理功能 完善的权限管理 SEO友好 活跃的社区支持 Thymeleaf模板引擎 Thymeleaf是Java生态中广泛使用的模板引擎,主要特性: 自然模板:直接使用标准HTML 表达式语言(OGNL) 支持多种视图解析(HTML/XML/JS/CSS) 丰富的标签和属性 与Spring框架深度集成 国际化支持 漏洞原理分析 漏洞触发流程 Handler封装ModelAndView对象 请求经过 DispatcherServlet#doDispatch 方法 调用 invokeHandlerMethod 方法初始化 ModelAndViewContainer 通过反射为 returnValue 赋值 设置 viewName 值 处理ModelAndView对象获取view processDispatchResult 方法处理返回结果 render 方法准备渲染视图 resolveViewName 解析视图名称 渲染view ThymeleafView#render 方法完成实际渲染 通过 renderFragment 处理模板片段 当 TemplateName 不包含 :: 时,直接使用 viewTemplateName 包含 :: 时解析为 templateName 和 markupSelectors 关键注入点 漏洞核心在于Thymeleaf对SpEL表达式的处理: 输入被 preprocess 方法预处理 符合正则匹配的表达式被提取 StandardExpressionParser.parseExpression 解析表达式 expression.execute 执行表达式 测试过程 漏洞特征 返回值或路径可控的路由 参数型注入点(如 String 类型参数) 限制条件 Thymeleaf 3.0.12及以上版本 默认payload无法直接使用 绕过技术分析 版本差异 高版本Thymeleaf新增了两个关键防护机制: checkViewNameNotInRequest 新版本会将输入转为小写 检查 requestURI.contains(vn) 若匹配则抛出异常 containsSpELInstantiationOrStatic 防止使用 T 字符实例化对象 检测以下模式: 对象实例化(如 new SomeClass ) 静态方法调用(如 T(SomeClass) ) 绕过checkViewNameNotInRequest 利用 viewName 和 request.getRequestURI() 解析差异: 双斜杠绕过 原始payload: /doc/__${payload}__::.x 绕过payload: doc//__${payload}__::.x 原理:标准化处理会删除一个 / ,导致 requestURI 不匹配 分号绕过 payload: doc;/__${payload}__::.x 原理: getCachedPathValue 处理URL时的差异 绕过containsSpELInstantiationOrStatic 添加空格 在表达式关键部分添加不影响执行的空格 如: T (java.lang.Runtime) 而非 T(java.lang.Runtime) 其他干扰字符 可尝试添加不影响表达式执行的字符 最终利用 结合两种绕过技术,构造有效payload: 或: 防御建议 升级到最新Thymeleaf版本 对用户输入进行严格过滤 禁用不必要的SpEL表达式功能 实施严格的输入验证机制 参考 Thymeleaf Spring Issue #256 若依CMS官方文档 Thymeleaf官方安全公告