Thymeleaf模板漏洞分析

百家 作者:斗鱼安全应急响应中心 2020-10-29 17:46:11
前言

Thymeleaf 是一个类似Velocity、FreeMarker 的模板引擎,而且Spring Boot推荐使用Thymeleaf引擎。Michael Stepankin和Aleksei Tiurin发表了两篇文章Spring View Manipulation Vulnerability Exploiting SSTI in Thymeleaf 来讲Thymeleaf模板的安全问题,在此对相关技术进行深入分析。本文相关代码已整合到 thymeleaf-ssti

 

视图名可控导致SSTI


漏洞代码见HelloController,漏洞特征主要表现为Spring所使用的视图名称中包含攻击者可控的部分。严格意义上来说这个问题不算SSTI,因为漏洞触发时还没有运行到渲染模板的阶段。



根据Michael Stepankin的总结,即使视图名称可控,使用了如下几种方式的代码不受影响

1. 使用@ResponseBody注解

2. 模板名称由redirect:或forward:开始(不走ThymeleafView渲染)

3. 参数中有HttpServletResponse,response已经被处理

 

漏洞原理分析

使用demo进行调试分析,最开始断点打在控制器的return语句处,尝试从这里开始找Thymeleaf处理视图的入口。但是Spring代码复杂,没能定位到相关逻辑。后从官方文档 Views and View Resolvers in Thymeleaf 中看到 ThymeleafView 和 ThymeleafViewResolver,在其中成功打断。

 

Controller中执行return后,Spring会自动调度Thymeleaf引擎寻找并渲染模板。简化的流程如下:

org.thymeleaf.spring5.view.ThymeleafViewResolver.createView()  //根据视图名创建对应的View。对redirect:和forward:有特殊处理,其他情况则使用ThymeleafView进行渲染展示

org.thymeleaf.spring5.view.ThymeleafView.render()

org.thymeleaf.spring5.view.ThymeleafView.renderFragment() //根据视图名解析模板名称

org.thymeleaf.TemplateEngine.process()  //渲染模板

......

看看renderFragment中如何解析模板名称。这里将模板名称进行拼接 "~{" + viewTemplateName + "}" ,然后使用parseExpression进行解析



org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression()  首先会对表达式进行preprocess预处理



org.thymeleaf.standard.expression.StandardExpressionPreprocessor.preprocess(),解析出__xx__中间的部分作为表达式执行。



然后在org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression()中使用SpEL执行表达式,触发RCE



危险的预处理

我们已经知道上文漏洞的触发点是Thymeleaf的预处理功能。那预处理在模板中是否也能工作,是否也会存在SSTI漏洞?

先抛开疑问看下Thymeleaf模板的语法,模板中有以下几种常用的表达式:

    ${...}: 变量表达式

    *{...}: 选择表达式

    #{...}: 消息表达式

    @{...}: 链接表达式

    ~{...}: 片段表达式

以上任意一种表达式内嵌使用预处理,只要预处理的数据可控,均能造成SSTI漏洞。以变量表达式为例,对应的模板url.html

<!doctype html>

<html xmlns:th="http://www.thymeleaf.org">

<body>

<a th:href="@{__${link}__}">test</a>

</body>

</html>

在控制器中获取参数link并传递给模板

    //GET /url?link=($%7bT(java.lang.Runtime).getRuntime().exec('calc')%7d)

    @GetMapping("/url")

    public String url(@RequestParam(name="link") String link, Model model) {

        model.addAttribute("link", link);

        return "url";

    }

 

渲染模板时引擎会解析标签处理属性,简化的调用流程如下

org.thymeleaf.util.ProcessorConfigurationUtils.ElementTagProcessorWrapper.process()

org.thymeleaf.processor.element.AbstractElementTagProcessor.process()

org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess()

org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess() //解析属性,执行表达式

此时会通过EngineEventUtils.computeAttributeExpression将属性计算成表达式,经过预处理后表达式如下,执行时将触发恶意SpEL表达式



总结 

Thymeleaf模板安全问题主要依赖预处理功能,根据执行入口的不同分为两种情况:

1. 视图名称可控,即 return 'xxx' + var

2. 模板预处理变量可控,即 @{/xx/__${var}__}

 


参考链接

https://raledong.gitbooks.io/using-thymeleaf/content/ 

https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#views-and-view-resolvers-in-spring-mvc

https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/

https://www.veracode.com/blog/secure-development/spring-view-manipulation-vulnerability



斗鱼安全应急响应中心


斗鱼安全应急响应中心(DYSRC,https://security.douyu.com/)是斗鱼安全建立的安全漏洞收集及安全应急响应平台,致力于保障斗鱼旗下所有产品及用户信息安全,与各界安全人员及安全组织、团队共建文明网络安全。


鱼塘里的小鲨鱼都是萌萌小可爱,期待你们来守护小鲨鱼的安全!我们会不定期开展各种奖励活动,给守护斗鱼安全的白帽子创造更大的价值和福利。




关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接