Pentesting LDAP

LDAP Icon
LDAP (Lightweight Directory Access Protocol) is a protocol used to access and manage directory information such as users, groups, and computers within an organization. It’s heavily used in Active Directory environments, where port 389 (TCP/UDP) is used for plaintext communication and 636 (LDAPS) for encrypted.

From a pentesting perspective, LDAP is a goldmine of information. It can lead to obtaining user accounts, descriptions, service accounts, SPNs for Kerberoasting, and potential plaintext passwords hiding in object attributes. Even without credentials, LDAP can often leak valuable intel.

Discovery and Enumeration

Discovery

Start by identifying whether LDAP is exposed and what version is running. The goal here is to detect the protocol, confirm it’s LDAP, and identify if anonymous access may be possible. You can use the Nmap tool to discover servers with the LDAP ports 389 or 636 open.

nmap -p 389,636 -sV 10.1.1.1          #Check for LDAP or LDAPS services on a single host
nmap -p 389,636 -sV 10.1.1.0/24       #Check for LDAP or LDAPS services on a subnet
nmap -p 389,636 -sV -iL targets.txt   #Check for LDAP or LDAPS services on a list of IPs

Use the NSE scripts to fingerprint the LDAP service and possibly retrieve the naming context (root domain):

nmap -n -sV --script "ldap* and not brute" 10.1.1.1     #Use NSE LDAP scripts

Look for responses like:

  • Microsoft Windows Active Directory LDAP
  • OpenLDAP
  • Indication of anonymous bind support

 

Enumeration

Once LDAP is confirmed, move to enumeration. The aim is to pull as much information as possible from the server, either anonymously or with credentials, such as:

  • Naming context (domain info)

  • Usernames

  • Computer accounts

  • Group memberships

  • Descriptions (which may leak creds)

  • SPNs (for Kerberoasting)

 

Null Bind / Anonymous Enumeration

Some LDAP servers allow binding without credentials. If enabled, this is a quick win to start extracting basic info. You can use the ldapsearch command-line tool.

ldapsearch -x -H ldap://10.1.1.1:389 -s base -b "" "(objectClass=*)"     #Check if anonymous bind works and get domain root

If the above is successful, you can try to enumerate users and other LDAP objects directly.

ldapsearch -x -H ldap://10.1.1.1 -b "dc=example,dc=local"     #Attempt full enumeration with anonymous bind

Even without creds, you may be able to extract:

  • Users (sAMAccountName)

  • Descriptions (which often leak internal info)

  • Domain naming context

  • OU structure

 

Authenticated Enumeration

If credentials are available (domain user, service account, low-priv creds), LDAP can be fully queried using the ldapsearch command-line tool. Use the naming context returned from the rootDSE query as your base (-b)

ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(objectClass=user)" sAMAccountName cn mail description      #List all users in the domain
ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(objectClass=computer)" name dNSHostName operatingSystem    #List all computer objects
ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(objectClass=group)" cn member                              #Retrieve domain groups

 

Credential Hunting

Many organisations store credentials, temporary passwords, or legacy info in the description field of user accounts. You should always grep LDAP output for sensitive strings.

ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(objectClass=user)" sAMAccountName description | grep -iE 'pass|pwd|key|legacy'   #Dump all user descriptions and grep for keywords

Alternatively, you can craft specific filters:

ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(&(objectCategory=person)(objectClass=user)(description=*pass*))"   #Only users where the description field contains the word "pass"

SPN and Kerberoasting

Once you have valid credentials (even low-priv), you can use LDAP to enumerate Service Principal Names (SPNs), which are tied to service accounts and are the target for Kerberoasting.

ldapsearch -LLL -H ldap://10.1.1.1 -D "domain\user" -w "pass" -b "dc=example,dc=local" "(servicePrincipalName=*)" servicePrincipalName sAMAccountName    #Find all user accounts with SPNs set

Then use impacket to obtain the hashes:

GetUserSPNs.py domain.local/<user>:<password> -dc-ip 10.1.1.1 -outputfile spns.txt

This outputs hashes you can crack offline with hashcat or john.

Filter Examples and LDAP Flags

LDAP filters allow us to fine-tune queries. Below are powerful examples to use during enumeration:

Filter Purpose LDAP Filter Expression
All users (objectClass=user)
User accounts only (&(objectCategory=person)(objectClass=user))
Description contains ‘pass’ (&(objectClass=user)(description=*pass*))
SPNs set (servicePrincipalName=*)
No password required userAccountControl:1.2.840.113556.1.4.803:=32
Password never expires userAccountControl:1.2.840.113556.1.4.803:=65536
Admin accounts (&(objectCategory=person)(objectClass=user)(adminCount=1))

Other Tools

The following tools are also useful to help automate or streamline LDAP enumeration.

windapsearch

windapsearch -d example.com --dc-ip 10.1.1.1 -u [email protected] -p 'Password123' --full    #Full AD search

ldapdomaindump

ldapdomaindump -u 'DOMAIN\\user' -p 'pass' 10.1.1.1 -o ./ldap_dump    #JSON & HTML output

godap

godap 10.1.1.1   #Check for anonymous ldap bind