相关文章推荐
无邪的钢笔  ·  How to check is the ...·  11 月前    · 
温文尔雅的领带  ·  jQuery随机数生成·  1 年前    · 
瘦瘦的柚子  ·  Interface for ...·  1 年前    · 

0x01 漏洞背景

2019年10月31日,一个Solr Velocity模板远程命令执行的POC被公开到Github。经过分析测试,该POC在Solr的多个版本测试成功,包含最新版本,所以该漏洞目前处于0day状态。由于Solr默认未开启登录认证,只需请求 /节点名/config ,将配置项 params.resource.loader.enabled 设置为 true ,再构造链接即可让Solr中的 Velocity 模版引擎渲染传入的 恶意模版 ,造成命令执行。下面我们来具体分析漏洞细节!

0x02 知识储备

Velocity 是一个基于Java的模板引擎,简单来说就是可以将模版渲染成html页面。下面以一个小demo来演示使用 Velocity 如何渲染出 test by chixiao lab ,方便大家快速理解 Velocity 的功能和使用。

如果我们的模版 test.vm 内容改如下时,那么 Velocity 将会执行 id 命令,并显示执行结果。

1
2
3
4
5
6
7
8
9
10
#set($x='')
#set($rt=$x.class.forName('java.lang.Runtime'))
#set($chr=$x.class.forName('java.lang.Character'))
#set($str=$x.class.forName('java.lang.String'))
#set($ex=$rt.getRuntime().exec('id'))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

所以某个应用以 Velocity 作为模版渲染引擎,如果要渲染的模版内容用户可控的话,那就可以构造恶意模版来执行任意命令。本次Solr漏洞就是这种情况!

0x03 漏洞分析

下面我们在 Solr 8.2.0 上以公开的POC触发的漏洞链进行分析。

Solr在查询数据结束后,会通过 wt 参数的值来确定数据返回的格式,可以是 XML JSON CSV , Velocity模版渲染 等等。本次漏洞正是出现在查询结果用 Velocity模版渲染

从代码层面看,Solr会根据 wt 值,创建对应的类型的 QueryResponseWriter 来将查询数据处理成对应的格式,最后将数据 write() 到客户端。

由于我们这里设置的是 wt=velocity ,故 QueryResponseWriter 类型为 VelocityResponseWriter 。我们在 solr-velocity-8.2.0.jar 包的 VelocityResponseWriter.write() 方法打断点,作为漏洞分析的开始位置。

首先Solr会先创建一个Velocity模版引擎对象 engine ,跟进 createEngine() 方法。

发现当设置 "params.resource.loader.enabled": "true" 时,属性 this.paramsResourceLoaderEnabled 的值为 true ,程序将创建一个参数资源加载器对象,也就是模版内容将从前端传来的参数中加载(PS:知识储备的案例是从文件加载)。

继续跟进 SolrParamResourceLoader 类的构造方法,解析了前端传来的所有参数,并对 v.template. 开头的参数进行处理。我们请求的参数为 ...&v.template=custom&v.template.custom=恶意模版内容 ,所以 put 进入 templates 模版 map key custom.vm , value 就是我们指定的 恶意模版内容

之后在获取模版对象时,将前端传入的参数 v.template 值拼接 .vm ,也就 custom.vm ,作为要渲染的模版名。而 custom.vm 正是我们上一步传入的恶意模版。

然后我们重新回到 write() 方法,不管 wrapResponse 变量为 true 还是 false ,恶意模版都被传入 merge() 进行合并渲染,至此漏洞触发。

0x04 参考