基于 ADWS(net.tcp/9389)的 Active Directory 侦察与只读安全审计,使用 Go 语言实现
adit 是一个单二进制的 Active Directory 侦察与只读安全审计工具,它通过 ADWS(Active Directory Web Services,TCP/9389) 而非 LDAP 与域控制器通信。
adit 是矿井的水平入口——一条安静的进入通道。通过 ADWS 而非 LDAP/389 查询 AD 意味着流量是 WCF net.tcp 帧格式的、基于不常见端口的二进制 XML SOAP,因此相比经典 LDAP 更不容易被检测、过滤或识别特征——同时仍返回相同的目录数据。adit 用 Go 实现了完整的 ADWS 协议栈,无外部运行时依赖。
┌────────────┐ net.tcp/9389 ┌──────────────┐
│ adit │ ───────────────▶ │ ADWS on DC │ ──▶ local LDAP
│ (Linux) │ NMF · NNS · │ (port 9389) │
│ │ NBFSE · SOAP └──────────────┘
└────────────┘
adit 是一个防御/审计和授权评估工具。仅对你有权评估的目录运行它。
| 能力 | 详情 |
|---|---|
| 传输 | 基于 WCF net.tcp(TCP/9389)的 ADWS — MC-NMF 帧格式、MS-NNS 握手、MC-NBFS/NBFSE 二进制 XML、WS-Enumeration/WS-Transfer SOAP |
| 认证 | NTLMv2(sign + seal)和 Kerberos(ccache / keytab / 密码;RFC 4121 密封 GSS) |
| 侦察收集器 | 31 个模块(见下文)→ 每模块 CSV |
| 报告 | 样式化多工作表 XLSX 工作簿 + 自包含 HTML 仪表板(搜索/排序、严重性徽章、滚动监听) |
| 安全审计 | 27 条只读规则(含 ADCS ESC1–4/9)→ 按严重性排序的 JSON,同时呈现在仪表板中 |
| 代理 / 跳板主机 | HTTP CONNECT、SOCKS5/5h、SOCKS4/4a(支持代理认证 + 远程 DNS) |
| 分页 | 服务端 WS-Enumeration Pull 分页,可配置页大小 |
| 离线报告 | 从先前收集的 CSV 重建 XLSX/HTML,无需 DC |
| 依赖 | 纯 Go;无 LDAP 库、无 .NET、无外部服务 |
forest、domain、trusts、sites、subnets、schemahistory、dcs、
users、userspns、groups、computers、computerspns、ous、gpos、
gplinks、passwordpolicy、fgpp、dnszones、dnsrecords、kerberoastable、
asreproastable、krbtgt、adcs、cas、laps、protectedgroups、
groupmembers、gmsa、dmsa、printers、bitlocker
ADCS(adcs)标记 ESC1–ESC4/ESC9;laps 报告谁可以读取每个密码;
protectedgroups 审计 Protected Users。运行 adit -list-modules 查看当前列表。
-audit 运行 27 条只读规则。发现项包含规则 id、严重性、受影响对象、证据和修复建议,并写入 Adit-Audit.json(并且,当与 -collect 结合使用时,会生成一个位于仪表板首位的 "Audit Findings" 部分)。该引擎从不读取机密属性值(LAPS / gMSA / BitLocker),尽管侦察收集器可以。
| 规则 | 严重性 | 标记内容 |
|---|---|---|
| AD-DOM-010 | Critical | 非 Tier-0 主体持有 DCSync(复制)权限 |
| AD-ACL-001/005/006/007/011–016 | Critical | 对特权对象的危险控制(GenericAll/Write、WriteDACL/Owner、ForceChangePassword、Write SPN / KeyCredentialLink / member / AllowedToAct) |
| AD-SDH-001/002 | Critical | AdminSDHolder 的意外控制/所有者 |
| AD-CS-001 | Critical–Medium | ESC1 — 证书模板允许注册者提供的主题 |
| AD-CS-002 | Critical–Medium | ESC2 — Any-Purpose / 无 EKU 证书模板 |
| AD-CS-003 | High–Medium | ESC3 — Certificate Request Agent 模板 |
| AD-CS-004 | High | ESC4 — 证书模板上的弱访问控制 |
| AD-CS-009 | High | ESC9 — 证书模板缺少安全扩展 |
| AD-CS-005 | Critical/High | ESC5 — 对 PKI 对象的危险控制(NTAuthCertificates、CA 存储、CA 对象) |
| AD-CS-006 | Info | 存在 AD CS — ESC6/ESC7/ESC8 需要主机级验证(无法通过 ADWS 观察) |
| AD-DOM-008 | High | 域范围启用了可逆密码加密 |
| AD-USR-001 | High | Kerberos 预认证已禁用(可 AS-REP roast) |
| AD-USR-009 | High | 账户仅使用 DES 加密 |
| AD-CMP-006 | High | 非 DC 上的无约束委派 |
| AD-KCL-001 | High | 特权账户上的 Key Credential(影子凭据) |
| AD-KRB-001 | High | krbtgt 密码陈旧 |
| AD-DOM-005 | Medium | 机器账户配额 > 0(任何用户都可以加入计算机) |
| AD-USR-002 | Medium | 可 Kerberoast 的服务账户(若为特权则为 High) |
| AD-USR-005 | Medium | 设置了 PASSWD_NOTREQD |
| AD-USR-006 | Medium | 特权账户密码永不过期 |
| AD-USR-011 | Medium | 特权账户密码陈旧 |
| AD-CMP-008 | Medium | 配置了基于资源的约束委派 |
| AD-CMP-012 | Medium | 遗留/不受支持的操作系统 |
| AD-GRP-009 | Medium | 特权组中的外部安全主体 |
| AD-GRP-020 | Medium | 通过 primaryGroupID 隐藏的特权成员身份 |
| AD-TRU-001/003 | High/Medium | 无 SID 过滤 / 带 SID 历史的信任 |
| AD-DNS-003/004 | Medium/Low | 存在 WPAD / ISATAP 记录 |
| AD-CMP-011 | Low | 陈旧的计算机账户 |
| AD-INT-005 | High | sIDHistory 包含特权 SID |
阈值可调:-krbtgt-max-age、-priv-pwd-max-age、-stale-days。
ADCS 说明:ESC1–ESC5 和 ESC9 通过 ADWS 从 AD 对象评估。ESC6 (
EDITF_ATTRIBUTESUBJECTALTNAME2)、ESC7(CA 角色 ACL)和 ESC8(Web 注册 / NTLM 中继)位于 CA 主机注册表/HTTP 端点中,无法通过 ADWS 观察 —AD-CS-006标记存在 CA,以便在主机上验证它们(例如使用 Certipy)。
需要 Go 1.26+。无其他构建依赖。
# Build the binary
go build -o adit ./cmd/adit
./adit -version
# …or run without installing
go run ./cmd/adit -h
# Cross-compile release archives for linux/windows/darwin (amd64+arm64) into dist/
bash scripts/build-release.sh
-fqdn 必须是 DC 的真实 FQDN(而非其 IP):ADWS SOAP 的 To 头会被 WCF 的 AddressFilter 与端点匹配。可用例如
nslookup -type=SRV _ldap._tcp.dc._msdcs.<domain> <dc-ip> 找到它。
adit -dc <host> -fqdn <dc-fqdn> -d <DOMAIN> -u <user> -p <pass> [flags]
# RootDSE handshake only (verifies auth + the full protocol stack)
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass'
# Run every collector -> ./report/CSV-Files/*.csv + Adit-Report.{xlsx,html}
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-collect all -o ./report
# A subset of collectors
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-collect users,groups,computers,kerberoastable
# Audit only -> Adit-Audit.json
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' -audit
# Recon + audit: findings lead the XLSX + HTML dashboard
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-collect all -audit -o ./report
# Password (synthesises a krb5.conf from the domain + DC if none is present)
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' -auth kerberos
# Existing ticket cache
KRB5CCNAME=/tmp/krb5cc_1000 adit -dc 10.0.0.10 -fqdn dc01.example.local \
-d EXAMPLE.LOCAL -u user -auth kerberos -ccache /tmp/krb5cc_1000
ADWS 是一个Web 服务但不是 HTTP——它运行在 9389 上的原始 TCP——然而代理仍可隧道传输该 TCP 流。在协议允许的情况下(SOCKS5/4a、HTTP CONNECT),DC 名称在代理处解析,因此仅内部可用的名称也能工作。
# SSH dynamic forward = a local SOCKS5 proxy
ssh -D 1080 -N jump-host &
adit -dc dc01.corp.internal -fqdn dc01.corp.internal -d CORP.INTERNAL \
-u user -p 'pass' -proxy socks5://127.0.0.1:1080 -collect all -audit -o ./report
# Other proxy forms
-proxy socks5://user:[email protected]:1080 # SOCKS5 with username/password auth
-proxy socks4a://10.0.0.5:1080 # SOCKS4a (remote DNS)
-proxy http://user:[email protected]:8080 # HTTP CONNECT (Basic auth)
-proxy https://proxy.corp:8443 # HTTP CONNECT over TLS to the proxy
使用 -auth kerberos + 密码时,KDC 交换仍直接进行;通过跳板主机时,先获取票据并传入 -ccache / KRB5CCNAME。
# Raw LDAP-filter query over ADWS, selecting attributes (paged automatically)
adit -dc 10.0.0.10 -fqdn dc01.example.local -d EXAMPLE.LOCAL -u user -p 'pass' \
-query '(&(objectClass=user)(objectCategory=person))' \
-attrs sAMAccountName,userAccountControl,objectSid
# Rebuild the workbook / dashboard from existing CSVs (no DC needed)
adit -generate-excel-from ./report/CSV-Files -o report.xlsx
adit -generate-html-from ./report/CSV-Files -o report.html
运行 adit -h 查看完整标志列表。