At SynerComm's Fall IT Summit 2018 we presented a talk about the top 5 attacks used to compromise a Domain Administrator account. As a short recap, the top five are the following:
Permissive Global Group Access + mimikatz
This is the classic case where a Domain Administrator logs into a machine where Domain Users group is a local administrator. Any user on the network can then log into the machine and extract the administrator's password from memory.
LLMNR and NBT-NS Poisoning
LLMNR and NBT-NS can be used to hijack the NTLMv2 hash for users who mistype the name of an SMB share of HTTP address.
SYSVOL Passwords + Leaked AES Keys
Although this vulnerability came out years ago, many companies still have cpassword fields in their SYSVOL XML files that can be decrypted using the Microsoft leaked AES key.
Kerberoasting
Due to Microsoft’s implementation of the Kerberos protocol, any domain account can get the krb5tgt hash for a domain user used as a service. Strong passwords must be enforced on these accounts.
DC Backups
If the backup file of a domain controller is discovered on a share that is not properly secured it is trivial to extract the NTDS.dit database and pull all the NTLM hashes for the domain.
The AssureIT team put together a list of tools to help you check for these vulnerabilities in your network. The presentation file and the self-audit kit can be found here:
DA101-Protecting_your_Domain_Admin_account.pptx
On August 15th, 2018 a vulnerability was posted on the OSS-Security list. This post explained that OpenSSH (all versions prior to and including 7.7) is vulnerable to username enumeration by sending a malformed public key authentication request (SSH2_MSG_USERAUTH_REQUEST with type "publickey") to the service. Upon receiving this request, the server would validate the user THEN check if the request was well-formed. As a result, if an invalid user was requested the OpenSSH service would return a SSH2_MSG_USERAUTH_FAILURE indicating the server rejected the request due to an invalid username. However, if a valid user was requested the server would simply close the connection because the request was malformed.
This behavior was caused by the following code:
87 static int 88 userauth_pubkey(struct ssh *ssh) 89 { ... 101 if (!authctxt->valid) { 102 debug2("%s: disabled because of invalid user", __func__); 103 return 0; 104 } 105 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 || 106 (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || 107 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0) 108 fatal("%s: parse request failed: %s", __func__, ssh_err(r));
On lines 101-103 you can see that the program checks to see if the user is valid, and if it is not, returns 0, which gets turned into a SSH2_MSG_USERAUTH_FAILURE. However, per lines 105-108, if the server fails to validate the SSH request it then calls “fatal” and exits the process without responding to the client. This allows us to determine whether a user is valid.
I wrote the following code as a means to exploit the aforementioned vulnerability. The code is roughly based off of my own research into the vuln and the POC provided by Matthew Daley.
There were several challenges while writing this exploit. As demonstrated by Matthew Daley in his POC, the easiest way to corrupt the packet is to override the Paramiko Message object’s add_boolean function. However, once the first request is sent the original status of add_boolean must be returned or else calling Transport.start_client() to initiate another connection will fail. According to some messages I received, that stumped several other exploit developers trying to create a similar exploit.
Another challenge was that the OpenSSH sever would occasionally be overwhelmed by the influx of SSH requests causing it to refuse to negotiate the SSH transport. When this occurs, the exploit automatically attempts to retry to a max number of 3 times.
Thanks,
Justin ( @Rhynorater )
GitHub repo: https://github.com/Rhynorater/CVE-2018-15473-Exploit
ExploitDB: https://www.exploit-db.com/exploits/45233/
┌─[justin@parrot]─[~/projects/CVE-2018-15473-Exploit] └──╼ $python sshUsernameEnumExploit.py --help usage: sshUsernameEnumExploit.py [-h] [--port PORT] [--threads THREADS] [--outputFile OUTPUTFILE] [--outputFormat {list,json,csv}] (--username USERNAME | --userList USERLIST) hostname positional arguments: hostname The target hostname or ip address optional arguments: -h, --help show this help message and exit --port PORT The target port --threads THREADS The number of threads to be used --outputFile OUTPUTFILE The output file location --outputFormat {list,json,csv} The output file location --username USERNAME The single username to validate --userList USERLIST The list of usernames (one per line) to enumerate through