Detecting LDAP Reconnaissance

Techniques to identify Active Directory enumeration



After gaining a foothold within an organization, threat actors often need to perform internal reconnaissance to discover users, permissions, and other potentially useful resources available. One of the most commonly used methods to achieve this is by gathering data from Active Directory in Windows enterprise environments. However, these activities often fly under the radar because attackers are simply (ab)using a legitimate feature.

Lightweight Directory Access Protocol (LDAP) queries are how clients obtain information from Active Directory. Clients specify a search filter to search for objects, such as users or computers, that match specific criteria. LDAP is used in the background by Windows to lookup and authenticate members of the domain, and has a variety of different use cases. But, since most objects in the directory can be read by any authenticated user, it can be easily abused to collect broad information about every user, group, and system on the domain.

Detection Mechanisms

Network indicators

In many environments today, LDAP queries are encrypted in-transit. While encrypting traffic is a great way to prevent eavesdropping, it also makes purely network-based detection difficult. Many current detection techniques look for an anomalous spike in traffic on ports 389 and 636 (LDAP & LDAPS), but determined threat actors can simply slow their collection over a longer time period to avoid this methodology.

Anomalous Traffic Spike

A suspicious spike in LDAP traffic

Canary / Honey Accounts

Canary accounts are decoys designed to mimic legitimate accounts and bait attackers into utilizing them. They are never supposed to be used legitimately, so any activity around them can be used as an early warning sign of possible reconnaissance or enumeration activity. Canary accounts also have a very low false positive rate, since they are not normally accessed. However, baselining and whitelisting may still be necessary to rule out legitimate applications that inadvertently interact with the canaries. When deploying canary accounts, it is important to keep in mind that attributes such as a very old last logon time could tip off its existence to threat actors. It is critical to make these accounts “blend in”.

To create a canary object (e.g. user, computer, etc.), use the Active Directory Users and Computers (ADUC) console. Depending upon your use case, apply some of the following properties to the canary:

  • Set user logon hours to 24/7 deny
  • Periodically update the “last logged into” property to make the honey account less obvious
  • Set a service principal name (like “MSSQLSvc/fqdn”) to catch potential Kerberoasting activity
  • Toggle “Do not require Kerberos pre-authentication” to catch potential AS-REP Roasting

Then, configure auditing for any of the following scenarios by modifying the group policy via:

Group Policy Management -> Default Domain Policy -> Edit

Edit Group Policy

Detect Enumeration

Event ID 4662

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> Audit Policies -> DS Access -> Audit Directory Service Access

Audit DS Access

To detect enumeration, enable Directory Service access logging, and configure auditing for each canary object:

  1. Toggle: “Active Directory Users and Computers -> View -> Advanced Features”
  2. In the security tab of the canary object’s properties, click the “Advanced” button
  3. Under the auditing tab, click the “Add” button
  4. Set the following properties:
    • Principal: Everyone
    • Applies to: This object only
    • Permissions: Read all properties

Audit Canary Access

Note: in the resulting events, the Object Name isn’t translated from its GUID

Detect Canary Account Login Attempts

Event ID 4768 (or 4625)

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> Audit Policies -> Account Logon -> Audit Kerberos Authentication Services

Audit Kerberos Authentication

This will record all failed Kerberos authentication attempts, so filter events accordingly based on the canary name in the “TargetUserName” field

Audit Kerberos TGS Requests

Event ID 4769

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> Audit Policies -> Account Logon -> Audit Kerberos Service Ticket Operations

Audit Kerberos TGS

To detect potential Kerberoasting attempts on your canary object, configure logging for service ticket requests.

Note: this generates a huge amount of noise, so before forwarding to a SIEM, filter logs based on:

  • RC4 or DES Encryption (Ticket Encryption: 0x17) OR (Ticket Encryption: 0x1 OR 0x2 OR 0x3)
  • Canary name in the “Service Name” field

Host-based detection

The highest-fidelity detection can be achieved by logging sent LDAP queries at the host level. All LDAP queries could be logged on the Domain Controller (DC) itself, but this often leads to performance issues. A typical DC generates huge amounts of data as LDAP queries are part of its primary functionality, thus, it becomes infeasible to collect and store this data directly on the DC in any large enterprise environment. However, by logging queries directly on domain-joined endpoints, the data becomes much more manageable. Host-based logging gives visibility into the searches performed from each endpoint (which is often the pivot point of an attacker), and also provides important context around the data. For example, the PID of the process that sent the query can be captured in this manner. Luckily, this functionality is already built-in to Windows via an Event Tracing for Windows (ETW) log provider. For more information about ETW, check out Event Tracing For Windows 101.

Enabling this log provider is very simple:

wevtutil set-log "Microsoft-Windows-LDAP-Client/Debug" /enabled:true /quiet:true /retention:false /maxsize:100032

Or by using the Event Viewer GUI:

1. Event Viewer -> View -> Show analytic and debug logs

Show Debug Logs

2. Enable “Applications and Services Logs -> Microsoft -> Windows -> LDAP-Client -> Debug”

Enable Debug Log

3. Increase the default log size and/or change the event overwrite settings. Note: if overwriting is enabled, the Event Viewer will not be able to display entries, but they are still recorded. Source

Change Logsize

The “Microsoft-Windows-LDAP-Client” logs are stored on disk as binary event trace logs (.etl) This means that they must be converted into human-readable format before being forwarded to a SIEM. To automate the collection process, you can use SilkETW or Splunk-ETW. In this example, I will use the Splunk-ETW Technology Add-on. Installation instructions are pretty straightforward and well-documented on the project’s GitHub page.

After installing the add-on on the forwarder(s), create a new “profile” named ldap.ini in $SPLUNK_HOME\etc\apps\Splunk-ETW\profile with the contents: [Microsoft-Windows-LDAP-Client].

Next, to enable the profile we just created, add the following to inputs.conf at $SPLUNK_HOME\etc\system\local\inputs.conf:

disabled = 0

Then, you should begin to see events populate Splunk with the sourcetype: Splunk-ETW (a restart of Splunk may be required)

Now that we have visibility into the actual LDAP queries that are being sent, we can begin to differentiate “signal” from “noise”. But first, let’s take a look at the syntax of LDAP search filters. Filters are boolean expressions, more simply known as “true” or “false” statements, that specify what objects should be returned in the search. For example, the following search filter will return all objects in the “user” class:


Parenthesis serve as a grouping around the different “clauses”, and allow for multiple attributes to be specified in a single search query. These groupings can also be chained together with logical comparative operators, AND (&) or OR (|). For example, another way to enumerate user accounts could be to search for all objects that have the “homedirectory”, “scriptpath”, or “profilepath” attributes set. Since we want to find all objects with any value for each of these 3 attributes, we can use the wildcard (*) character in place of the value. So, to return objects with any value for “homedirectory” OR “scriptpath” OR “profilepath” we could use the following:


Most legitimate LDAP queries will be searching for a very specific object, instead of trying to find all objects that match generic criteria. After running some popular enumeration tools in the BLS lab environment, we observed the following elements of suspicious queries begin to standout:

  • Generic search looking for all objects of a general type
  • Large number of generic filters in single query (e.g. return all computers AND users AND groups)
  • Multiple queries from the same PID in a short time-frame
  • Wildcards present in search filter

Suspicious Search Filter

A suspicious search filter

Utilizing these observations as a basis for generating a detection method, we have created a series of LDAP query filters that can be used with the logging configuration outlined above to generate alerts for suspicious LDAP activity. These queries have been consolidated and published as Sigma rules in the BLS and SigmaHQ repositories.

Below is a list of additional LDAP search filters that could potentially be used for reconnaissance by an attacker. These filters may be useful for threat hunting efforts within your environment to identify suspicious / unwanted LDAP activity:

Domain Enumeration

(objectCategory=domain)All domain objects
(primaryGroupID=516) OR (userAccountControl:1.2.840.113556.1.4.803:=8192)All domain controller objects
(primaryGroupID=521) OR (userAccountControl:1.2.840.113556.1.4.803:=67108864)All domain controller objects (read-only)
(objectClass=trustedDomain)All trusted domains
(objectCategory=groupPolicyContainer)All group policy objects
(|(description=*pass*)(comment=*pass*))Objects with a password in the description or comment
(objectCategory=nTDSDSA)Global Catalog servers

Account Enumeration

(&(objectCategory=person)(objectClass=user)) OR (sAMAccountType=805306368)All users
(userAccountControl:1.2.840.113556.1.4.803:=544)Objects with a "Password Not Required" flag set
(userAccountControl:1.2.840.113556.1.4.803:=65536)Objects with a "Password Never Expires" flag set
(!(UserAccountControl:1.2.840.113556.1.4.803:=2))Objects that are enabled (!disabled flag set)
(adminCount=1)Members of a protected group (AdminSDHolder)
(|(accountExpires=0)(accountExpires=9223372036854775807))Accounts that never expire
(samAccountName=*)Objects with a login account name
(|(homedirectory=*)(scriptpath=*)(profilepath=*))Objects with a home directory, logon script, or profile path

Computer Enumeration

(objectCategory=Computer) OR (objectClass=computer) OR (sAMAccountType=805306369)All computers
(primaryGroupID=515) OR (samAccountName=Domain Computers)All domain computers
(objectCategory=server) OR (objectClass=server)All domain servers
(ms-MCS-AdmPwd=*)Objects with LAPS password attribute

Group Enumeration

(objectCategory=group) OR (objectClass=group)All groups
(sAMAccountType=268435456) OR (groupType:1.2.840.113556.1.4.803:=2147483648)All security groups
(groupType:1.2.840.113556.1.4.803:=2147483656)All universal security groups
(groupType:1.2.840.113556.1.4.803:=2147483652)All domain local security groups
(groupType:1.2.840.113556.1.4.803:=2147483650)All global security groups
(sAMAccountType=268435457)All non-security groups
(sAMAccountType=536870912)All alias objects
(sAMAccountType=536870913)All non-security alias objects
(primaryGroupID=512) OR (samAccountName=Domain Admins)All domain admins
(samAccountName=Backup Operators) OR (memberOf=CN=Backup Operators)All backup operators
(samAccountName=Account Operators) OR (memberOf=CN=Account Operators)All account operators
(samAccountName=Enterprise Admins) OR (memberOf=CN=Enterprise Admins)All enterprise admins
(samAccountName=Group Policy Creator Owners) OR (memberOf=CN=Group Policy Creator Owners)All group policy creator owners
(samAccountName=Server Operators) OR (memberOf=CN=Server Operators)All server operators
(samAccountName=Remote Desktop Users) OR (memberOf=CN=Remote Desktop Users)All remote desktop users
(samAccountName=Distributed COM Users) OR (memberOf=CN=Distributed COM Users)All distributed COM users
(objectcategory=organizationalUnit)All OUs
(primarygroupid=*)Objects with a primary group ID

Kerberos Enumeration

(servicePrincipalName=*)All objects with a SPN
(userAccountControl:1.2.840.113556.1.4.803:=4194304)Objects with Kerberos Pre-Authentication disabled
(userAccountControl:1.2.840.113556.1.4.803:=2097152)Objects with Kerberos DES enabled
!(userAccountControl:1.2.840.113556.1.4.803:=1048574)Objects not marked as 'sensitive and not trusted for delegation'
(userAccountControl:1.2.840.113556.1.4.803:=524288)Objects with unconstrained delegation
(msDS-AllowedToDelegateTo=*)Objects with constrained delegation
(msDS-AllowedToActOnBehalfOfOtherIdentity=*)Objects with resource-based constrained delegation

The Remote Security Account Manager (SAMR) protocol has very similar functionality to LDAP, as it also enables enumeration of domain accounts and groups. It is used by the built-in net.exe command, and its impact should also be considered. For mitigation strategies, see the following:






© 2020 | All rights reserved | 1834 Summerville Avenue | Suite 250 | North Charleston, SC | 29405 | 843.991.4612