Thymeleaf在3.0.0-3.0.11存在模板注入,根据网上的资料,在3.0.12-3.0.15之间的版本虽然进行了修复,但是还存在可以绕过的问题,本文主要学习Thymeleaf模板注入的代码审计。通过模板注入需要关注返回的视图是否可控或者视图中的部分内容可控,且返回的内容不能被RestController、ResponseBody、Http ServletResponse、redirect重定向、forward转发等,因为被上述注解修饰或者重定向后,不会通过模板进行解析;还有一种场景,当返回类型为void时,springboot会默认从URL部分中获取视图名,如果路径可控,同样会存在模板注入的问题。
一、环境搭建
1、依赖引入。Spring-boot和thymeleaf做了很好的集成,在spring-boot中引入了spring-boot-starter-thymeleaf后,会通过版本依赖引入相对应的thymeleaf版本,比如spring-boot 2.2.0.RELEASE引入的thymeleaf版本为3.0.11.RELEASE,如下:
2、controller代码。接口都是将前端输入的参数与返回的内容进行拼接,拼接后的内容为视图名。如/lang接口,当用户在前端输入的rtype的值为cn时,返回的视图名为index-cn,经过模板拼接后最终为index-cn.html,这样就可以找到具体的视图了。
二、代码审计
1、通过以下两种方法进行查找:
(1)逐个controller查找,比较费时;
(2)通过全局搜索返回部分内容可控的关键字"::",两个引号。
先看前三个接口,/lang、/lang1、/lang2,参数为rtype,返回类型为string,最后都通过return返回了视图,且无上述注解及response参数;再看第四个接口/path/{path},返回类型为void,无返回,但是输入信息通过了日志记录。
2、插入POC
(1)/lang1接口,该接口将输入信息作为了视图名,注意插入POC的时候要对关键的字符进行URL编码:
(2)/path/{path}接口,该接口无返回
3、现在看第五个接口/lang3,该接口的参数类型为int,此时模板会进行类型转换,会报错,然后我使用String.valueOf(rtype)进行类型强制转换后,前端输入POC时,仍然会报错:
说明和返回类型也存在关系,在审计的时候要注意。
三、实战复现,这里以若依v4.6.0为例
1、确认Thymeleaf版本信息。这套源码在POM.XML中不能直接看到Thymeleaf版本,可以在External Libraries中看到版本号为3.0.11,或者在POM.xml通过spring-boot-dependencies找到依赖配置,Ctrl+左键可以找到spring-boot-dependencies-2.2.12.RELEASE.pom,在该文件中可以看到版本号:
2、通过第1种方法未找到,通过第2种方法,找到几处,如下:
这里选择第1处进行测试,参加包括fragment、taskName、mmap:
通过接口构造请求,插入POC:
另外还有几处,这里就不再赘述了。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)