Lightweight Directory Access Protocol (LDAP) is an integral part of Active Directory (AD). LDAP is open source and used for authentication against directory services such as Active Directory.
LDAP is the language that applications use to communicate with services like Active Directory and with other server that provide directory services as well. LDAP lets systems in the network talk with the AD.
2 types of LDAP authentication:
- Simple authentication including anonymous authentication, unauthenticated authentication, and username/password authentication. It will create a BIND request to LDAP server.
- SASL authentication. SASL using authentication services like Kerberos to bind to the LDAP server. The LDAP protocol sends LDAP message which starts challenge and response messages.
LDAP authentication messages are sent in cleartext.
LDAP queries<
Communicating with directory services using LDAP is done with queries.

| Query | Result |
|---|---|
| (objectCategory=computer) | find all workstations in a network |
| ((&(objectCategory=person)(objectClass=user)) | searches for all users |
| (objectClass=group) | searches for all groups |
Example queries
Find disabled users
Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))' -Properties * | select samaccountname,useraccountcontrol
Find out how many users, computers and groups
PS C:\Users\mczen> (Get-ADUser -Filter *).Count
# Or specify a group
(Get-ADGroupMember -Identity "IT").Count
Powershell Filters
Filters in PowerShell allows us to get better output and retreive data we are looking for. It can be used to narrow down specific data in large result.
This would filter out all Microsoft software making the list of search results a lot smaller.
PS C:\zen> get-ciminstance win32_product -Filter "NOT Vendor like '%Microsoft%'" | fl
IdentifyingNumber : {748D3A12-9B82-4B08-A0FF-CFDE83612E87}
Name : VMware Tools
Vendor : VMware, Inc.
Version : 10.3.2.9925305
Caption : VMware Tools
Meaning
-eq Equal to
-le Less than or equal to
-ge Greater than or equal to
-ne Not equal to
-lt Less than
-gt Greater than
-approx Approximately equal to
-bor Bitwise OR
-band Bitwise AND
-recursivematch Recursive match
-like Like
-notlike Not like
-and Boolean AND
-or Boolean OR
-not Boolean NOT
Find users with DoesNotRequirePreAuth who's accounts can be ASREPRoasted.
# Administrative groups
Get-ADUser -Filter {adminCount -eq '1' -and DoesNotRequirePreAuth -eq 'True'}
# All users
Get-ADUser -Filter {DoesNotRequirePreAuth -eq 'True'}
# Get group members
Get-ADGroupMember -Identity "Protected Users"
Get info about a host
# Get basic information
Get-ADComputer WS01
# Get detailed information, including operating system, last logon time, etc.
Get-ADComputer WS01 -Properties *
# Get specific properties
Get-ADComputer WS01 -Properties OperatingSystem, LastLogonDate, Description
LDAP Search Filters
The -LDAPFilter enables us to use LDAP search filters. LDAP filters must have 1 or more criteria, when using more we use AND or OR to concatenate.
| Operator | Function |
|---|---|
| & | and |
| | | or |
| ! | not |
Search criteria
When using an LDAP search filter we need to specifiy rules, like (displayName=mczen).
| Critera | Rule | Example |
|---|---|---|
| Equal to | (attribute=123) | (&(objectclass=user)(displayName=Smith) |
| Not equal to | (!(attribute=123)) | !objectClass=group) |
| Present | (attribute=*) | (department=*) |
More attributes https://docs.bmc.com/docs/fpsc121/ldap-attributes-and-associated-fields-495323340.html
Object Identifiers (OIDs)
Object Identifiers (OIDs) are unique identifiers used to name objects. We can use machting rule OIDs with LDAP filters, found here. This query will return all administratively disabled user accounts, or ACCOUNTDISABLE (2) with matching rule: 1.2.840.113556.1.4.803
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)' | select name
1.2.840.113556.1.4.803is the Object Identifier (OID) for a bitwise AND operation.:=2checks if account is disbabled
Find all groups
Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=Harry Jones,OU=Network Ops,OU=IT,OU=Employees,DC=ZENCORP,DC=LOCAL)' | select Name
1.2.840.113556.1.4.1941This OID find all groups that the user is a member off:=:Specifies the equality match.
LDAP Queriy - Description Field
Get-ADUser -Properties * -LDAPFilter '(&(objectCategory=user)(description=*))' | select samaccountname,description
objectCategory=user: Ensures that only user objects are retrieved.description=*: Ensures that only users with a non-empty description field are retrieved.
LDAP Query - Find Trusted Users
This filter "(userAccountControl:1.2.840.113556.1.4.803:=524288)" can be used to find all users or computers marked as trusted for delegation, or unconstrained delegation. Trusted users can act on behalf of other users in AD.
# Get users
Get-ADUser -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | select Name,memberof, servicePrincipalName,TrustedForDelegation | fl
# Get computers
Get-ADComputer -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | select DistinguishedName,servicePrincipalName,TrustedForDelegation | fl
1.2.840.113556.1.4.803is the Object Identifier (OID) for a bitwise AND operation:=524288checks if the bit corresponding to theTRUSTED_FOR_DELEGATION
LDAP Query - Users With Blank Password
Get-AdUser -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32))(adminCount=1)' -Properties * | select name,memberof | fl
(userAccountControl:1.2.840.113556.1.4.803:=32): Checks if the bit corresponding to thePASSWD_NOTREQDflag is set in theuserAccountControlattribute. This indicates that a password is not required for the account.
LDAP Anonymous Bind
LDAP anonymous binds allow unauthenticated attackers to retrieve information from the domain, this can be used to list users, groups, computers, account attributes and password policies.
A anonymous bind is a request where the username and password fields are left empty.
We can use python to interact LDAP:
Python 3.8.5 (default, Aug 2 2020, 15:09:07)
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldap3 import *
>>> s = Server('10.129.1.207',get_info = ALL)
>>> c = Connection(s, '', '')
>>> c.bind()
True
>>> s.info
Ldapsearch
We can use tools suchas windapsearch and ldapsearch to enumerate a domain.
# ldapsearch
ldapsearch -H ldap://10.129.1.111 -x -b "dc=zencorp,dc=local"
# Info
python3 ldapsearch-ad.py -l 10.129.1.207 -t info
# Discover users in domain
ldapsearch -H ldap://10.129.86.8 -x -b "DC=ZENCORP,DC=LOCAL" -s sub "(&(objectclass=user))" | grep sAMAccountName: | cut -f2 -d" "
Windapsearch
# Check for bind
python3 windapsearch.py --dc-ip 10.129.1.111 -u "" --functionality
# Get domain users
python3 windapsearch.py --dc-ip 10.129.1.207 -u "" -U
# Show groups
python3 windapsearch.py --dc-ip 10.129.42.188 -u "" -G
# Unconstrained delegation
python3 windapsearch.py --dc-ip 10.129.42.188 -u "" -U --unconstrained-users
Credentialed Enumeration
When having domain credentials we get retrieve all kinds for information from LDAP.
python3 windapsearch.py --dc-ip 10.129.1.207 -u zencorpo\\john.doe --da
Of checking for users with unconstrained delegations.
python3 windapsearch.py --dc-ip 10.129.1.207 -d zencorp.local -u zencorp\\john.doe --unconstrained-users
Or using ldapsearch
# Check password policy
ldapsearch -l 10.129.1.207 -d zencorp -u john.doe -p pass123 -t pass-pols
# Check for Kerberoastable users
ldapsearch -l 10.129.1.207 -d zencorp -u john.doe -p pass123 -t kerberoast | grep servicePrincipalName
# Check ofr ASREPRoastable users
ldapsearch -l 10.129.1.207 -d zencorp -u john.doe -p pass123 -t asreproast
.png)
Properties here