详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

Posted ChaMd5安全团队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详细分析Solr的CVE-2019-0193以及velocity模板注入新洞相关的知识,希望对你有一定的参考价值。

环境搭建

java "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9000" -Dsolr.solr.home="../example/example-DIH/solr/" -jar start.jar --module=http

然后idea加远程调试9000端口,dist、server/lib文件夹加到library里。dist是solr的主要jar

首先是CVE-2019-0193

首先看exp

 
   
   
 
  1. POST /solr/tika/dataimport HTTP/1.1

  2. Host: 10.27.52.42:8983

  3. Content-Length: 416

  4. Content-type: application/x-www-form-urlencoded

  5. Connection: close


  6. command=full-import&dataConfig=

  7. <dataConfig>

  8. <dataSource type="URLDataSource"/>

  9. <script><![CDATA[ java.lang.Runtime.getRuntime().exec("open -a Calculator");

  10. ]]></script>

  11. <document>

  12. <entity name="a"

  13. url="https://stackoverflow.com/feeds/tag/solr"

  14. processor="XPathEntityProcessor"

  15. forEach="/feed"

  16. transformer="script:" />

  17. </document>

  18. </dataConfig>

solr的admin后台文件是server/solr-webapp, 所以首先还是得看web.xml,看大概的一些filter、url-pattern路由才能知道后台怎么过去的。

请求都走了SolrRequestFilter这个过滤器,对应着org.apache.solr.servlet.SolrDispatchFilter,进去看一下看了doFilter方法,主要就是通过getHttpSolrCall返回一个HttpSolrCall对象,然后调用call方法到了servlet类中,然后handler.handleRequest(req, rsp);进到了handleRequest中对请求响应进行处理。

在handleRequest中,this.handleRequestBody(req, rsp);调用了抽象方法来对请求处理,看一下哪些类实现了这个抽象方法。

有点多,这些都是可以通过路由直接请求到的类。这里不仔细看了。

exp是请求/solr/tika/dataimport,所以直接进入exp中的dataimport类。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

一开始通过loadDataConfig,其中调用了readFromXml方法,从xml数据中读取信息并解析,根据解析出的document,script,function,dataSource等标签构建出DIHConfiguration对象并返回。然后根据传的参数,没debug,进了这里。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞里边只是在新线程中进了runCmd中,还是进了runCmd。根据我们传的full-import,进了这里。在doFullImport中,首先会创建一个DocBuilder对象,DocBuilder的主要功能是从给定配置中创建Solr文档,同时会记录一些状态信息。随后通过execute()方法会通过遍历Entity的所有元素来解析config结构,最终得到是一个EntityProcessorWrapper对象。

下面是通过docBuilder.execute()进入doFullDump然后进入buildDocument方法。可以看到,execute中传入的生成的builder对象的config属性是之前根据我们传入的payload生成的DIHConfiguration对象。buildDocument()方法会为发送的配置数据的每一个processor做解析,当发送的entity中含有Transformers转换器时,会进行相应的转换操作。问题出在ScriptTransformer。script转换器能够对把其他java支持的语言转成java函数执行。而内容我们可控,这就很尴尬了。引用A-Team大佬的描述:

脚本转换器允许使用Java支持的语言(比如javascript, JRuby, Jython, Groovy, or BeanShell)编写任意转换函数,其中Javascript语言已默认集成在Java中了,使用其他语言的话需要自己整合。每个转换函数都 必须接收一个row变量(与Java中的Map<String,Object>类型对应,所以是支持get、put、remove等操作的),函数的功能是修改已知field的值,或者添加新的fields。处理完之后,将row对象作为返回值返回。这个脚本会以最高级别插入到DIH配置文件中,每个row会调用一次。

详细分析Solr的CVE-2019-0193以及velocity模板注入新洞跟buildDocument(), 下面通过epw.nextRow();进入到了applyTransformer,这里就是问题触发点。

详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

首先是loadTransformers,进入加载转换器。下边startwith判断,如果转换器以script开头,则把ScriptTransformer加到transformers里。


加载转换器后,通过transformers.iterator();遍历所有转换器。跟进t.transformRow,然后就很清晰了。通过initEngine初始化转换引擎,进去看一下,通过eval完成了js函数定义。出来后通过invokeFunction完成了rce详细分析Solr的CVE-2019-0193以及velocity模板注入新洞最后说一下,payload中document这部分

详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

这里就是buildDocument中,需要对传入的实体进行解析,根据我们传入的datasource类型加载对应的datasource。这里主要的作用还是构建我们的script转换器,并且让exp不报错。如果传一个不存在的datasource会报错无法执行exp。solr一共有6中datasource,这里用URLDatasource主要是很方便。网上除了看到URLDataSource外还看到了JdbsDataSource的payload,可以直接ldap+jndi


看下新的这个洞

两次请求,第一个是覆盖了config然后才能velocity模板注入。这里确实牛逼,膜

详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

首先第一个包,他是config进来的。和之前一样,看下configHandler的handleRequestBod

详细分析Solr的CVE-2019-0193以及velocity模板注入新洞进到command.handlePOST里,继续跟handleCommands, 里边SolrResourceLoader.persistConfLocally,进去看一下详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

可以看到,直接把我们要覆盖的配置写入configoverlay.json中。这里第一次请求需要做的事情就完成了。

下面看第二次请求。
第二次理论上应该是把configoverlay.json中的配置读出来,然后写到VelocityResponceWriter的配置中,但我跟了几遍代码,都没有找到读文件配置的部分。。配置是true和false的区别就在初始化velocity对象时,对象的配置值不同。。这里应该是内存中的值,当文件中的值更改后,会进入init方法中重置该值(大概)。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞继续往下跟,进入到在createInitInstance中,通过解析请求参数中的class,使createInstance方法创建一个VelocityResponceWriter对象,然后调用他的init方法。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞跟进能看到prle和srle就是传入的要覆盖的属性。他们被覆盖到了VelocityResponceWriter对象的this.paramsResourceLoaderEnabled和this.solrResourceLoaderEnabled属性。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞当到了createEngine的时候可以看到,paramsResourceLoaderEnabled是true时将params加到了loader里。接下来通过engine.getTemplate(templateName + ".vm");就能够从url中获得传过去的exp。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞

然后返回继续到template.merge进入velocity中,然后继续跟一下会发现在render中通过ASTprocess解析注入的模板完成RCE详细分析Solr的CVE-2019-0193以及velocity模板注入新洞而当是false时,engine.getTemplate会报错找不到该vm,原因就是paramsResourceLoaderEnabled为false时,velocity并不会从url中获得velocity的模板字符串,从而无法进行模板注入。详细分析Solr的CVE-2019-0193以及velocity模板注入新洞可以继续跟一下Solr的各个handler,感觉可能还会有其他直接render的地方能直接ssti。 

招新小广告

ChaMd5 ctf组 长期招新

尤其是crypto+reverse+pwn+合约的大佬

欢迎联系admin@chamd5.org





以上是关于详细分析Solr的CVE-2019-0193以及velocity模板注入新洞的主要内容,如果未能解决你的问题,请参考以下文章

CVE-2019-0193 远程命令执行-漏洞复现

Solr的安装以及中文分析器的配置

SOLR源码分析—edismax检索打分机制

Solr远程命令执行分析

ElasticSearch和solr的差别

solr的学习