Attacks in Active Directory: Kerberoast

This page aims to document work around Kerberoast (MITRE ATT&CK T1558.003 [1]) and be a point of reference for people interested into getting information around this attack vector within Active Directory.

Kerberoasting is an attack vector that both red teams and APT groups [2] use in their operations.

It enables attackers extract service account credentials as a low privileged user without communicating with the server that hosts the attacked service. Often, service accounts within domains are (mis-)configured with excessive privileges (for example they belong to privileged groups like Domain Admins) and therefore open the door to full domain compromise.

The article is divided in the following sections:

The anatomy of Kerberoast

In order to show the attack, it’s important to first understand the communication between three parties: the user’s host, the Domain Controller and the server that hosts the service:

  1. An attacker authenticates to the domain using either an user or a computer account and gets a Ticket Granting Ticket (TGT)
  2. The attacker then creates a service ticket request (TGS-REQ) providing the service name (sname) they want to receive a ticket for. The service name can have different formats, the most common of which, are: Service Principal Name (SPN), User Principal Name (UPN), SAM Account Name (SAΝ)
  3. The Domain Controller validates the received TGT, extracts information from it and creates a service ticket. The service ticket is then encrypted with the hashed password of the service account associated with the SPN the user provided in the TGS-REQ. The ticket is sent back to the attacker in a TGS-REP packet.
  4. The attacker extracts the encrypted service ticket TGS-REP and cracks it offline to retrieve the password of the service account

Add a service account

In a lab environment a user account is required. This will be the account of the service starring in the Kerberoast scenario.

With access to a Domain Controller, open dsa.msc (Active Directory Users and Computers) and create a new user account. In my example, I created the following user account:

create user account

Associate a service account with a Service Principal Name (SPN)

Next step in the configuration of the testing environment is to actually create an SPN for the service account. Assuming the lab AD domain is called chestnut.local, in order to create a SPN for the service account we can use the native Windows utility setspn:

setspn.exe -s sql/sql.chestnut.local sql_svc

In this specific example, sql_svc is the username of the service account.

We now have a SPN to work with in a testing environment!

Enumerating SPNs

In a domain in order to enumerate the available SPNs we can use a variety of tools. Assuming we have credentials for an account, we can use the tools listed in this section.

The native Windows utility setspn on a domain controller:

setspn.exe -Q */*

Or using an account domain or a domain-joined host:

setspn.exe -T -Q */*

On Metasploit, the module auxiliary/gather/get_user_spns queries the DC for the SPNs. Although, on my testing machine Metasploit didn’t parse the response from the DC, the network traffic on Wireshark shows that the SPNs are actually returned.

Impacket’s module GetUserSPNs queries the target domain for SPNs that are running under a user account:

impacket-GetUserSPNs -dc-ip 10.1.100.25 chestnut.local/john.doe:SuperSecret!

Rubeus module kerberoast identifies accounts that can be kerberoasted as well as provides functionality to extract the encrypted part of a TGS-REP. It retrieves a list o kereberoastable account via LDAP queries to the Domain Controller, however it doesn’t use the same filters as Impacket does. More specifically, the command below identifies the kerberoastable accounts within the domain:

.\Rubeus.exe kerberoast

The following LDAP query is being made in the background:

rubeus-ldap

In order to retrieve the hash for a specific SPN with Rubeus the following command can be used:

.\Rubeus.exe kerberoast /spn:”<\Service_name>/<host:port>”

In the following section another method of gathering SPNs by using the PowerShell ActiveDirectory module [3] is presented.

Hashcat formatted output from Rubeus

At the time of writing, Rubeus generates in total 3 different hash types compatible with Hashcat (ordered by least crack complexity/effort):

Supported Encryption Algorithms

The ecnryption algorithm supported by the user or computer account is included within the ms-DS-Supported-Encryption-Types attribute of each account and can be queried using PowerShell for example. The KDC uses this information when issues a Service Ticket (ST) for the account.

Artifacts, Detections and Further Actions

Enumeration of SPNs creates space for detections on the wire. In order to enumerate the SPNs, Impacket makes an LDAP query filtering for servicePrincipalName=* (ServicePrincipalNames) and objectCategory=computer (non-computer accounts). Detections are in place by Microsoft’s ATA [3] and the activity is detected.

The following screenshot illustrates the traffic that Impacket generates on the wire. Highlighted in yellow color are the key parts of the communication with the Domain Controller. The LDAP traffic is the query the tools makes to grab the available SPNs. Further down we see the Kerberos authentication request (AS-REQ) and reply (AS-REP). This is when the authentication of the user takes place in order to get a ticket (TGT). Further down, we see the client requesting a service ticket (TGS-REQ) and getting the service tiket (TGS-REP). The response contains the service ticket encrypted with the password hash of the service account.

wire

The detection capabilities have led the attackers in changing their techniques or at least have second thoughts on using “noisy” techniques.

Instead of making LDAP queries to the Domain Controller, we can take advantage of the Active Directory Web Services. The following command is the equivalent of setspn -Q */*

(Get-ADObject -Filter {servicePrincipalName -like “*”} -Properties servicePrincipalName).servicePrincipalName

A different - and less straightforward approach - would be to begin with gathering all the OUs within the domain:

(Get-ADOrganizationalUnit -Filter *).Name

Next, focus on a specific OU and get all the user principal names:

(Get-ADUser -Filter * -SearchBase ‘CN=Users,DC=chestnut,DC=local’).UserPrincipalName

The above search fetches many reults and may require additional analysis to identify service accounts.

If you open Wireshark and let it run in the background while you’re invoking the above commands you’ll see that the traffic is not LDAP. It’s TCP traffic to port 9389. On a Domain Controller, the Active Directory Web Services (ADWS) service is running on port 9389. As such, it’s a vehicle of avoiding detections that may be in place for suspicious LDAP queries.

Use your situational awareness to make out which SPNs will help you achieve your objectives.

Offline password cracking

We can crack passwords using tools such as Hashcat and John the Ripper. Assuming the hashed service ticket (TGS) is in the file hashed.txt and that we use the well-known rockyou.txt password list, we run hashcat:

hashcat -m 13100 hashed.txt /usr/share/wordlists/rockyou.txt

The same process with John the Ripper:

john hashed.txt –wordlist=/usr/share/wordlists/rockyou.txt

Tools

A list of the tools referenced in this article:

References and Resources

[1] https://attack.mitre.org/techniques/T1558/003/

[2] https://www.microsoft.com/security/blog/2021/01/20/deep-dive-into-the-solorigate-second-stage-activation-from-sunburst-to-teardrop-and-raindrop/

[3] https://learn.microsoft.com/en-us/powershell/module/activedirectory/

[4] https://techcommunity.microsoft.com/t5/microsoft-security-and/detecting-ldap-based-kerberoasting-with-azure-atp/ba-p/462448

[5] https://www.harmj0y.net/blog/redteaming/kerberoasting-revisited/

tags: #active directory