🔐 advalidate
用于授权 Active Directory 渗透测试的原生、防锁定、多协议凭据验证与访问映射工具。
## 📖 为什么开发这个工具
在实际测试中,当你获得一个可用的凭据时,接下来的问题总是相同的:**“好吧——它还能在哪里起作用,以及我在哪里是管理员?”** 通常的解决办法是使用 NetExec/CrackMapExec 在整个子网中进行喷射。
这很有效,但有两点一直让我困扰:
1. **账户锁定。** 喷射是锁定真实员工账户、触发 SOC 警报并搞砸整个测试的最快方式。大多数工具什么都不统计,完全指望你在脑子里算清楚。
2. **黑盒外部调用。** 封装一堆外部二进制文件并 grep 它们的 stdout 是非常脆弱的,而且它掩盖了某次尝试被跳过或失败的*原因*。
所以我开发了 `advalidate`:它在进程内**使用原生 Python 库通过五种协议**验证一组凭据与多台主机的匹配情况——没有外部调用——并且**将每一次尝试都置于它根据域自身的密码策略计算出的锁定预算之后**。它会告诉你你的凭据在哪里有效,你在哪里是管理员,并且它拒绝将任何账户推向其锁定阈值。
它是一个**范围界定工具,而不是漏洞利用工具**——请参阅[它刻意*不*做的事情](#-what-its-not)。
## ✨ 它的功能
- 🧩 **五种协议,一个进程** — SMB/WMI, LDAP(S), WinRM, SSH 和 RDP,每个都使用原生 Python 库。没有 NetExec,没有 CrackMapExec,也没有 `smbclient` 子进程。
- 🔑 **三种凭据材料** — `user:password`、`user:NTLMhash` (pass-the-hash) 和 Kerberos **ccache** 票据。
- 🛡️ **每次尝试都经过锁定安全引擎** — 读取域密码策略 + 细粒度 PSO,维护每个账户的预算,并在达到阈值*之前*停止。当无法读取策略时,回退到醒目的 **SAFE MODE**。
- 🧠 **感知不可能的组合** — 声明式能力图意味着它永远不会发起无法生效的尝试(例如通过 SSH 使用 NTLM 哈希)。这些情况会被**跳过并记录** — 而且跳过不会消耗锁定预算。
- 📊 **访问矩阵 + 优先级发现** — 每个主机 × 协议的 `fail` / `auth` / `admin` `rich` 表格,外加一个基于规则的引擎,优先展示最重要的内容(多台主机的管理员权限、触达 DC、尚未枚举的管理员权限)。所有评分都是**可解释的 — 不涉及 AI/LLM 调用。**
- 🌐 **进程内 SOCKS5 代理转发** — `--socks HOST:PORT` *在进程内部*通过代理路由每个原生处理程序(`proxychains` 做不到 — [原因在这里](#-proxy-routing-socks5-vs-proxychains))。
- 💾 **持久化、累积的状态** — SQLite 账本**在跨次运行中**保持预算准确无误;稍后添加凭据时,矩阵/评分会基于目前已知的所有信息进行构建。
## 🚫 它*不*做什么
`advalidate` 是一款**防御性边界工具**。它只验证凭据并映射访问权限 — 仅此而已。它**不会**:
- ❌ 提取凭据(不进行 SAM / LSASS / NTDS 转储)
- ❌ 漏洞利用或运行利用模块
- ❌ 自我传播或自行横向移动
- ❌ 导入 BloodHound
这些**在设计上**均属于超出范围的内容。这款工具只告诉你*你现有的、已授权的凭据能在哪里起作用。*
## ⚠️ 仅供授权使用
## ⚡ 快速开始
```
# clone
git clone https://github.com/Muhammad-Tayab/advalidate.git
cd advalidate
# 隔离环境(推荐)
python3 -m venv .venv && source .venv/bin/activate
# 安装依赖 + `advalidate` 命令
pip install -r requirements.txt
pip install -e .
```
确认它已在你的 `PATH` 中:
```
advalidate --version
advalidate capabilities # print the credential × protocol map and exit
```
**不想安装?** 直接从仓库运行 — 行为完全一致:
```
python -m advalidate capabilities
```
Kali / Debian 注意事项(PEP 668,以及 aardwolf 的 Rust 构建)
在外部管理的 Python(Kali/Debian)上,请添加 `--break-system-packages`,或者直接使用上面的 venv。在 Kali 上,传输库通常是预装的;如果 `aardwolf` 尝试从源码构建并因为缺少 `setuptools_rust` 或 Rust 工具链而失败,请针对已存在的依赖项单独安装该包:
```
pip install -e . --no-build-isolation --no-deps --break-system-packages
```
## 📋 用法
```
# 在 subnet、所有协议上验证单个 credential,lockout-safe
advalidate run --targets 10.10.0.0/24 --domain corp.local --cred 'jdoe:Summer2025!'
# Pass-the-hash(自动跳过不可能的组合)
advalidate run --targets hosts.txt --domain corp.local \
--cred 'administrator:aad3b4...:31d6cfe0d16ae931b73c59d7e0c089c0'
# 来自 ccache 的 Kerberos ticket
KRB5CCNAME=jdoe.ccache advalidate run -t dc01.corp.local -d corp.local -c 'jdoe:@'
# 通过进程内 SOCKS5 pivot 路由所有流量
advalidate run -t 10.10.0.0/24 -d corp.local -c 'jdoe:Summer2025!' --socks 127.0.0.1:1080
# 预览将要尝试的操作,而不发送任何 packet
advalidate run -t 10.10.0.0/24 -d corp.local -c 'jdoe:Summer2025!' --dry-run
# 强制执行 rules of engagement:拒绝任何超出授权 scope 的行为
advalidate run ... --scope 10.10.0.0/24 --scope @scope.txt
# 控制尝试节奏(固定延迟 + 随机 jitter)以降低 timing/detection 风险
advalidate run ... --delay 1 --jitter 3
# 手动 policy override + 持久化 state + JSON report
advalidate run ... --lockout-threshold 5 --observation-window 30 --state corp.db --json report.json
```
### 常用选项
| 标志 | 用途 |
|------|---------|
| `-t, --targets` | 主机 / IP / CIDR / `@file`(可重复) |
| `-d, --domain` | AD 域 (FQDN) |
| `-c, --cred` | `user:password` \| `user:[LM:]NT` \| `user:@[ccache]`(可重复) |
| `--scope` | 授权的 CIDR/主机/`@file`;拒绝此范围外的所有目标 |
| `--socks HOST:PORT` | 为所有原生处理程序进行进程内 SOCKS5 路由 |
| `--lockout-threshold` / `--observation-window` | 手动提供域策略 |
| `--safety-margin N` | 低于阈值的保留余量(默认为 `1`) |
| `--force` | 完全无视预算(需要交互式确认) |
| `--dry-run` | 打印尝试计划;不发送任何内容 |
| `--delay` / `--jitter` | 尝试之间的固定 + 随机步调 |
| `--state` | SQLite 账本 + 结果文件(启用跨次运行的安全性) |
| `--json` | 将访问矩阵 + 发现结果写入 JSON 文件 |
| `-v, -vv` | 显示每一次跳过 / 预算 `HOLD` / 离开 SAFE MODE 的时刻 |
运行 `advalidate run -h` 获取完整列表。
## 🧠 锁定安全模型
账户锁定是进行喷射时最大的风险,这也是这款工具存在的原因。该模型分层运行:
1. **策略发现。** 在首次使用*有效*凭据时,`advalidate` 会通过 LDAP/SAMR 读取域密码策略 — `lockoutThreshold` 和 `lockoutObservationWindow` — 并枚举可以按账户或组覆盖域默认设置的**细粒度密码策略 (PSO)**,将最具体的策略应用于每个目标。
2. **按账户预算。** 预算基于**正在认证的账户**,而不是主机。跨*所有*协议和*所有*主机的每一次尝试都会消耗该账户的预算。时间戳允许条目在观察窗外老化并释放预算。
3. **停止规则。** 它绝不让账户达到其阈值:
attempts_in_window ≥ threshold − safety_margin → HOLD
在默认 `safety_margin = 1` 和阈值为 5 的情况下,它每个窗口下每个账户最多只使用 4 次尝试,然后保持 (HOLD)。
4. **SAFE MODE。** 如果无法读取策略(预认证或读取失败),它**不会**盲目乐观地猜测 — 而是降至保守的硬编码默认值(`阈值 3 / 30 分钟 / 余量 1` → 每个窗口 2 次尝试)并打印醒目的警告。
5. **始终可见,始终可覆盖。** 它会在喷射前打印当前模式及每个账户的预算。`--lockout-threshold` / `--observation-window` 用于手动提供策略,`--safety-margin` 更改余量,而 `--force` 会完全覆盖预算 — 但需经过明确的交互式确认,适用于你*知道*没有锁定策略的账户(紧急破窗账户、实验室目标)。
## 🧩 凭据 × 协议能力矩阵
`advalidate` 知道每个协议实际可以消耗哪种身份验证材料,并**跳过不可能的组合而不是让它们失败**(失败的尝试会消耗锁定预算 — 而跳过则不会)。该映射是声明式的,可通过 `advalidate capabilities` 打印。
| 凭据材料 | SMB / WMI | LDAP(S) | WinRM | SSH | RDP |
|---------------------|:---------:|:-------:|:-----:|:---:|:---:|
| **密码** | ✅ | ✅ | ✅ | ✅ | ✅ |
| **NTLM 哈希 (PtH)** | ✅ | ✅ | ✅ | ❌ | ⚠️ 仅限 Restricted Admin |
| **Kerberos 票据** | ✅ | ✅ | ✅ | ⚠️ GSSAPI¹ | ⚠️ 依赖环境 |
- ❌ = **跳过并记录** — 从不尝试(例如 SSH 无法消耗 NTLM 哈希)。
- ⚠️ RDP **pass-the-hash** *仅*在目标启用了 **Restricted Admin mode** 时有效;否则将被跳过。
- ¹ SSH-over-Kerberos 需要两端均支持 GSSAPI/GSS;视为依赖环境。
## 🌐 代理路由:SOCKS5 vs proxychains
**长话短说 — 对于原生处理程序,请使用 `--socks`。`proxychains` 无法代理它们。**
`proxychains` 通过 `LD_PRELOAD` 加载一个垫片,为*它启动的子进程*挂钩 libc 的 `connect()`。`advalidate` 的处理程序是**进程内的 Python 库** — impacket, ldap3, paramiko 和 aardwolf 都在这个进程内部打开 socket。没有可供包装的子进程,因此 `proxychains python -m advalidate ...` **无法**路由处理程序的任何流量。
所以 `advalidate` 自行进行代理:
- **`--socks HOST:PORT`(主要)** *在进程内*将每个处理程序连接到 SOCKS5 代理 — paramiko 通过预连接的 socket,impacket 通过包装了 SOCKS 的 socket,ldap3 通过代理的 socket 源,aardwolf 通过其原生的 `asysocks` 支持。
- **`--proxychains`(次要)** **仅**在真正的子进程调用前添加 `proxychains`(如果有的话) — 它**对原生处理程序没有影响**,当你传递该参数时,工具也会明确说明这一点。
## 🗺️ 整体运作方式
```
advalidate/ # repo root
├── advalidate/ # the Python package
│ ├── __main__.py # enables `python -m advalidate`
│ ├── cli.py # click entry point (-> `advalidate` command)
│ ├── handlers/ # one native handler per protocol
│ │ ├── smb.py # impacket — SMB + WMI (+ admin detection)
│ │ ├── ldap.py # ldap3 — LDAP/LDAPS, NTLM + simple bind
│ │ ├── winrm.py # pywinrm — NTLM
│ │ ├── ssh.py # paramiko
│ │ └── rdp.py # aardwolf — NLA/CredSSP check (async, bridged)
│ ├── core/
│ │ ├── credential.py # credential model (password / hash / ticket)
│ │ ├── capability.py # declarative cred × protocol legality map
│ │ ├── engine.py # orchestrator: gates + sequences every attempt
│ │ ├── targets.py # host/CIDR/file expansion + in-scope guard
│ │ ├── store.py # validated-result store (persistent SQLite)
│ │ ├── matrix.py # access matrix: fail | auth | admin
│ │ └── scoring.py # rule-based prioritization / re-scoring engine
│ ├── safety/
│ │ ├── policy.py # domain policy + PSO reader (LDAP/SAMR)
│ │ └── budget.py # per-account lockout budget + SAFE MODE + ledger
│ └── proxy/socks.py # in-process SOCKS5 wiring for each library
├── tests/ # pytest suite (safety/scoring/CLI logic, no network)
├── .github/workflows/ci.yml
├── pyproject.toml # packaging + `advalidate` console script
├── requirements.txt
└── LICENSE
```
入口点是 `advalidate.cli:main`,同时作为 `advalidate` 控制台命令和 `python -m advalidate` 暴露。
## 📊 输出
一个 `rich` 访问矩阵 — 每个主机一行,每个协议一列 — 随后是由基于规则的评分引擎生成的优先级发现块:
```
Access Matrix — corp.local
┏━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━┳━━━━━┓
┃ host ┃ SMB ┃ LDAP ┃ WinRM ┃ SSH ┃ RDP ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━╇━━━━━┩
│ dc01 │ admin │ auth │ admin │ – │ auth│
│ fs01 │ admin │ auth │ auth │ – │ – │
│ web01 │ auth │ – │ fail │ auth│ – │
└───────────────┴───────┴──────┴───────┴─────┴─────┘
Prioritized findings
1. [CRITICAL] jdoe is local admin on 2 hosts (dc01, fs01)
2. [CRITICAL] jdoe authenticates to the Domain Controller (dc01)
3. [INFO] admin on fs01 not yet enumerated
```
添加 `--json report.json` 可获取机器可读的矩阵 + 发现结果,你可以直接将其放入报告中。
## 🧪 测试
该套件涵盖了安全、评分、能力和 CLI 逻辑 — 不涉及网络,没有实际目标:
```
pip install pytest
pytest -q
```
CI 会在每次推送时在 Python 3.10 / 3.11 / 3.12 上运行相同的套件(参见 [`.github/workflows/ci.yml`](.github/workflows/ci.yml))。
## 📦 依赖项
| 包 | 用途 |
|---------|---------|
| `impacket` | SMB + WMI,SAMR/LDAP 策略读取 |
| `ldap3` | LDAP / LDAPS (NTLM + 简单绑定) |
| `pywinrm` | WinRM (NTLM) |
| `paramiko` | SSH |
| `aardwolf` | RDP NLA / CredSSP 凭据检查 |
| `python-socks`, `PySocks`, `asysocks` | 进程内 SOCKS5 路由 |
| `click` | CLI |
| `rich` | 访问矩阵表格 + 彩色日志 |
所有版本均固定在 [`requirements.txt`](requirements.txt) 中。**非必需:** NetExec / CrackMapExec / evil-winrm / smbclient — 每个协议均为原生实现。
## 🗺️ 路线图
**已在基础规范之外实现:** 持久化的跨次运行尝试账本 (SQLite),作用域内的 CIDR 范围保护 (`--scope`),每次尝试的抖动/节流,以及 `--dry-run` 计划模式。
**计划中:** 配置文件支持,更丰富的支持组的 PSO 解析,结构化的 NDJSON 流式传输。
**永久超出范围(设计使然):** 凭据提取 (SAM/LSASS/NTDS)、漏洞利用模块、自主传播/横向移动、BloodHound 导入。
## 📜 许可证
MIT — 详见 [`LICENSE`](LICENSE)。仅为授权的安全测试和教育目的提供;使用风险及责任完全由您自行承担。
Mhammad Tayab 构建 — 因为只有当你确切知道一个凭据能在哪里起作用时,它才是有用的,而且在第一天就锁定客户的账户并不是查明这一点的正确方法。