获取payload_由WCTF2020 Thymeleaf分析payload形式

本文详细分析了WCTF2020比赛中Thymeleaf模版注入的payload形式,探讨了Thymeleaf的预处理和解析过程,包括视图获取、表达式解析等关键步骤,并列举了不同场景下的payload应用,强调了在Spring+Thymeleaf环境中评估模板注入漏洞的复杂性。
摘要由CSDN通过智能技术生成

更多全球网络安全资讯尽在邑安全

前段时间参加了WCTF2020比赛,当时主要是通过盲测的方式找到了正确的payload,但是对于网上出现的多种payload形式并不了解其原因,因此有了这篇文章。根据网上出现的payload以及比赛中用到的payload,主要有以下3种。

__${xxx}__::.x__${xxx}__::__${xxx}__::x.

Thymeleaf这道题采用的环境是Spring+Thymeleaf,当web应用基于spring,Thymeleaf使用SpEL,否则使用OGNL。

Thymeleaf 预处理

Thymeleaf模版引擎有一个特性叫做表达式预处理(Expression PreProcessing),置于__...__之中会被预处理,预处理的结果再作为表达式的一部分继续处理。举例如下:

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

解析过程分析

01. 获取view

当访问一个api时,spring与Thymeleaf是如何配合的呢?首先定位到org.springframework.web.servlet.DispatcherServlet#doDispatch(),这是都会经过的一个点。

fb3d86a72ddc4cdb3661489ef0de9a41.png

在该函数中获取ModelAndView对象,看图中的两行代码,会经过2个过程。
  1. ha.handle()

  2. applyDefaultViewName()

首先来看第一个过程,跟进handle()方法,直接跟进到org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal()

7a4a34e4a0a6ced9d49e2325a340e762.png

这里可以看到mav的获取方法,跟进invokeHandlerMethod(),直接跟进到invokeAndHandle()。

fa45431b360624f58077695eacadbdf5.png

这里的 returnValue是否有值,决定了2种类型的payload。returnValue的获取会invoke此Request对应的函数获取返回值,例如下面这个例子访问 /path时,获取return的值为 user/{lang}/welcome作为ModelAndView的view值。
@GetMapping("/path")public String path(@RequestParam String lang) {return "user/" + lang + "/welcome"; }

但如果例子是下面这样的呢?此时ModelAndView的view值为null。

@DeleteMapping(value = "/{username}")public void deleteUser(@PathVariable(name = "username") String username) {}}

接着往下来到第二个过程,跟进applyDefaultViewName()。

2f07b083f26ac8e4d382eaa7e6b4f2ee.png

在这里,若ModelAndView对象中的view不为空,则啥也不做,否则会获取DefaultView作为View。来看看defaultview是如何获取的。跟进getDefaultViewName(),继续跟进viewNameTranslator.getViewName()。

fcab70bad2ab97cccede91cf919496a9.png

在该方法中首先获取uri的path值,然后进入transformPath()方法,最后和prefix以及suffix进行拼接,即为ViewName。跟进transformPath()。

24c746f80ef957d68d4d0d1a9692b22d.png

在这里会去掉前后的/,它会将.及之后的内容当作扩展名,会截掉.以及之后的内容。因此,这种情况下需要在payload后增加一个.以保证payload内容完整。

02. 解析表达式

d006786606e1c9847329fa797e2fbe6a.png

获取到view后,接着往下跟进processDispatchResult()。

3a28077bbf6b8ee038e63974a3f3730a.png

继续跟进render()。

2996fd8be98221b7ccdc115199d558b6.png

首先获取viewName,然后调用resolveViewName(),选择bestView,这里的往往会返回ThymeleafView,保持了和view一样的值。然后接着往下,调用了view.render(),即ThymeleafView.render()。跟进。 4551f25e219cf743eb3235a999e6997b.png继续跟进renderFragment()。 eb64a21f4bdb7698964ddc2344efc1e0.png在这里会判断viewTemplateName是否包含 ::,然后调用IStandardExpressionParser.parseExpression()解析 ~{viewTemplateName}表达式。 c87f60390f3516cc7321b7c59d8eb89e.png继续调用parseExpression()。

d78caeb4e48ccae537036a345609eba7.png

这里首先调用preprocess对 __${}__里的内容进行预处理,结果存入 preprocessedInput,然后调用Expression.parse()进行第二次解析表达式。
在第一次处理时,只要 __${}__里面的语法正确,是一定会被执行的。执行完的第二次表达式解析是否正确就不一定了。如果第二次执行失败,则会显示原来的viewTemplateName值,而没有回显,但事实上已经执行了恶意语句。影响第二次执行失败与否与 ~{}里的语法格式有关。

7517e58957ee1d67621ea86bc4408200.png

~{}中出现::,其后面需要有值。

场景分析

01. 场景一

__${}__:: 在使用veracode-research的环境时,这种类型的payload确实能够成功。这和它一开始获取到的view有着很大的关系。

95046e53f6f70aa2938f6adfa6670203.png

像上图的这种,拼接后的结果为~{user/__${}__::/welcome},第一次解析后的结果为~{user/xxx::/welcome}这样的完全是合法的语法。

__${}__::.x 是veracode-research在其github中展现的payload,能成功,但是不需要.x也能成功。

02. 场景二

__${}__::x. 是在wctf中用到的payload,由于是void类型,在获取view时,是使用了path值,并截掉了.及之后的内容。因此需要在::后面有值且在最后有一个.

eed40def2a42eef9d95eee6571517f3e.png

03. 场景三

e0d887536a528be0a75bf07b30f2f12c.png

显而易见,这种情况下不需要::,但是结尾需要.

04. 场景四

e765cf551ff3f219c7abc6d32048702b.png

这种情况下,不能成功。因为它设置了@ResponseBody,在这种情况下,sring会将return的值作为响应内容,而不是模版。

05. 更多场景

还有多种场景可自行分析......

小结

综上,在一个spring+thymeleaf的应用中,进行模版注入需要分析当前的场景,然后才能判断是否有漏洞,在做检测时比较难。比较通用的payload形式为__${}__::x.,有回显。在无回显的情况下,只要保证__${}__里的语法正确,以及整个viewTemplateName中包含::即可,无论::的位置在哪儿都行。

原文来自:先知社区

原文链接:https://xz.aliyun.com/t/8568

欢迎收藏并分享朋友圈,让五邑人网络更安全

2f950a9c3e30cb36cadea86339227075.png

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!

推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值