高级域渗透技术之再谈Kerberoast攻击

丝绸之路 内网渗透 2019年5月5日发布
Favorite收藏

导语:Rebeus是一个用C#编写Kerberos 滥用工具包,最初是由@gentilkiwi 编写的 Kekeo 工具包中的一个端口,这个工具包从那时起就在不断发展。

Rebeus是一个用C#编写Kerberos 滥用工具包,最初是由@gentilkiwi 编写的 Kekeo 工具包中的一个端口,这个工具包从那时起就在不断发展。要了解更多关于 Rubeus 的信息,请查看"从 Kekeo 到 Rubeus"这篇文章后续的"Rubeus ——Now With More keo"或最近修订的 Rubeus README.md

我最近对 Rubeus 做了一些改进,其中包括重新审查了它的 kerberos 实现。 这导致了对 Rubeus 的 Kerberoast 方法的一些修改,也解释了我们之前在这个领域看到的一些"奇怪"的行为。 由于 kerberos 是一种如此常用的技术,现在我们已经对它的细微差别有了更好的理解,因此我想深入研究细节。

如果你不熟悉 Kerberoast,现有的大量信息可供你查阅,其中一些我在这篇文章的开头做过一些讨论。 如果你对 Kerberos (或 Kerberos)的工作原理没有一个基本的了解,那么这篇文章的大部分内容对你来说就没有什么意义,所以如果你对这些概念感到不舒服的话,我强烈推荐你多读一些相关的文章。 但是这里有一个关于 kerberos 执行过程的简短总结:

1. 攻击者对一个域进行身份验证,然后从域控制器服务器获得一个票证授予票证(TGT) ,该票证授予票证用于以后的票证请求

2. 攻击者使用他们的 TGT发出服务票证请求(TGS-REQ) 获取特定形式(sname/host)的 servicePrincipalName (SPN), 例如,MSSqlSvc/SQL.domain.com。此SPN在域中应该是唯一的,并且在用户或计算机帐户的servicePrincipalName字段中注册。 在服务票证请求(TGS-REQ)过程中,攻击者可以指定它们支持的Kerberos加密类型(RC4_HMAC,AES256_CTS_HMAC_SHA1_96等等)。

3. 如果攻击者的 TGT 是有效的,则 DC 将从 TGT 中提取信息并填充到服务票证中。 然后,域控制器查找哪个帐户在 servicedprincipalname 字段中注册了所请求的 SPN。 服务票证使用注册了所要求的 SPN 的帐户的哈希进行加密, 并使用了攻击者和服务帐户都支持的最高级别的加密密钥。 票证以服务票证回复(TGS-REP)的形式发送回攻击者。

4. 攻击者从 TGS-REP 中提取加密的服务票证。 由于服务票证是用链接到请求 SPN 的帐户的哈希加密的,所以攻击者可以离线破解这个加密块,恢复帐户的明文密码。

本文中我们将要提到的三种主要加密密钥类型分别是RC4_HMAC_MD5 (ARCFOUR-HMAC-MD5,其中帐户的 NTLM 散列函数作为密钥)、 AES128_CTS_HMAC_SHA1_96和 AES256_CTS_HMAC_SHA1_96。 为了简单起见,我将它们称为 RC4、 AES128和 AES256。

此外,这里所有的例子都是在 Windows 10客户端上运行的,而Server 2012域控制器是一个2012 R2的域功能级别。

Kerberoast 方法

Kerberos 通常采用两种通用的方法:

· Kerberos 协议的一个独立实现,通过连接到网络上的设备使用,或者通过 SOCKS 代理将精心设计的流量作为输入。 例如 Meterpreter 或者Impacket。这需要一个域帐户的凭据来执行roasting,因为需要请求一个 TGT 在以后的服务票证请求中使用。

· 在域联接的主机上使用内置的 Windows 功能(如.NET KerberosRequestorSecurityToken . Net kerberos / requestorsecuritytoken类)请求票证,然后使用Mimikatz 或Rubeus  从当前登录会话中提取票。另外一种可供选择的方法是几年前@machosec 意识到GetRequest() 方法可以用来从 KerberosRequestorSecurityToken 中挖掘出服务票证字节,这意味着我们可以放弃使用 Mimikatz 来提取票证。 这种方法的另一个优点是,现有用户的 TGT 可用于请求服务票证,这意味着我们不需要明文凭证或用户的散列来执行 kerberos 广播。

要利用Kerberoast,我们就真的需要 RC4加密类型的服务票证响应,因为这比其他的 AES 加密类型更容易被破解。如果我们在攻击者一方实现了协议,我们就可以选择在服务票证请求过程中指定我们只支持 RC4,从而更容易破解散列格式。 在主机端,我过去认为 KerberosRequestorSecurityToken方法默认请求的是 RC4加密的票证,因为通常返回的就是这个,但实际上"正常"票证请求行为发生在所有支持的密码都得到支持的情况下才会发生。 那么为什么这种方法通常会返回 RC4哈希呢?

是时候快速绕道了。

msDS-SupportedEncryptionTypes

我们过去讨论过的一个防御指标是"加密降级活动"。 由于现代域(功能级别在2008及以上)和计算机(vista / 2008 +)默认支持在 Kerberos 交换中使用 AES 密钥,因此在任何 Kerberos 票证授予票证(TGT)请求或服务票证请求中使用 RC4都应该是异常的。 肖恩 · 梅特卡夫有一篇名为"检测 Kerberoast 攻击活动"的优秀文章,其中涵盖了如何处理 DC 事件来检测这种类型的攻击行为,尽管他指出"可能会出现误报"。

为什么这种方法会出现误报的问题,这个问题的完整答案也解释了我多年来看到的一些使用 Kerberoast的"奇怪"行为。

为了说明这一点,假设我们有一个在其 servicePrincipalName (SPN)属性中注册了 MSSQLSvc/SQL.testlab.local 的用户帐户sqlservice 。 我们可以使用

powershell -C ”Add-Type -AssemblyName System.IdentityModel; $Null=New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList ‘MSSQLSvc/SQL.testlab.local”

为此 SPN 请求服务票证。 然而,应用于当前登录会话的结果服务票证指定使用 RC4,尽管请求用户的(harmj0y) TGT 使用的是 AES256。

 1.png

如前所述,由于某种原因,长期以来我认为 KerberosRequestorSecurityToken方法特别需要 RC4。 然而,看一下 Wireshark 从客户端捕获的 TGS-REQ (Kerberos 服务票证请求) ,我们可以看到所有适当的加密类型(包括 AES)都被指定为支持:

2.png

正如我们所期望的那样,返回的 TGS-REP (服务票证应答)中的enc-part部分使用发起请求的客户端的 AES256密钥进行了适当的加密。 然而,我们关心的用于 Kerberoast 的 enc-part 部分(包含在返回的服务票证中)是用sqlservice帐户的 RC4密钥(而不是 AES 密钥)加密的:

3.png

到底发生了什么?

事实证明,这与 KerberosRequestorSecurityToken方法无关。 这个方法请求了一个由提供的 SPN 指定的服务票证,这样它就可以构建一个包含 SOAP 请求的服务票证的 AP-REQ,我们可以在上面看到它执行的"正常"请求并声明它支持 AES 加密类型。

这种行为是由于 msDS-SupportedEncryptionTypes 域对象属性引起的,Jim Shaver 和 Mitchell Hennigan 在他们的 DerbyCon——"Return From The Underworld: The Future Of Red Team Kerberos"演讲中谈到了这一点。 此属性是在[ MS-KILE ]2.2.7中定义的一个32位无符号整数,表示具有以下可能值的位字段:

4.png

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/6cfc7b50-11ed-4b4d-846d-6f08f0812919

根据微软的[ MS-ADA2]说明 ,"密钥分发中心(KDC)使用这些信息[ msDS-SupportedEncryptionTypes ]同时为这个帐户生成服务票证。" 因此,即使域支持 AES 加密(即域功能在2008及以上) ,在请求的 SPN 注册的帐户上,msDS-SupportedEncryptionTypes 字段的值决定了 Kerberoast 流程中返回的服务票证的加密级别。

根据 MS-KILE 3.1.1.5的说明,该字段在 Windows 7+ 和 Server 2008R2+上默认值分别是0x1C (RC4_HMAC_MD5 | AES128_CTS_HMAC_SHA1_96 | AES256_CTS_HMAC_SHA1_96 = 28)。 这就是为什么机器的服务票证几乎总是使用 AES256的原因,因为最高的且相互支持的加密类型将用于 Kerberos 票证交换。 我们可以通过在Rubeus.exe klist 后执行dir \\primary.testlab.local\C$来确认这一结果:

5.png

但是,此属性仅在默认情况下设置在计算机帐户上,而不是在用户帐户上。 如果该属性没有定义,或者设置为0,[MS-KILE]3.3.5.7告诉我们默认使用的值是0x7,这意味着将使用 RC4对服务票证进行加密。 因此,在前面的例子中,注册到用户帐户 sqlservice的MSSQLSvc/SQL.testlab.local SPN中,我们收到的是使用 RC4加密的票证。

如果我们在活动目录的用户账户和计算机账户中选择"This account supports AES [128/256] bit encryption",那么 msDS-SupportedEncryptionTypes 就会被设置为24,并且指定只支持 AES 128/256加密。

6.png

7.png

当我第一次研究这个问题时,我假设这意味着既然 msDS-SupportedEncryptionTypes 值是非空的,而且 RC4的标志位并不存在,那么如果在为一个帐户请求服务票证时(通过 /tgtdeleg 标志)只指定为 RC4,交换票证的时候就会出现错误。

但是你猜怎么着? 我们仍然得到一个 RC4(类型是23)加密的票证,我们可以破解这个票证!

8.png

通过Wireshark 抓包确认 RC4是请求中唯一受支持的 etype值,而且票证的 enc-part 实际上是用 RC4加密的。

¯\_(ツ)_/¯

我假设这是出于故障安全向后兼容的原因,并且我在多个测试域中运行了这个场景,得到了相同的结果。 然而,当我要求其他人复现时却无法做到这一点,所以我不确定我是否遗漏了什么,或者这是否准确地反映了正常的域的行为。 如果任何人有更多关于这个的信息,或者不能复现,请告诉我!

为什么上述问题很重要? 因为如果那是真的的话,这就意味着在用户账户上禁用 RC4_HMAC 似乎不是一个简单的方法。 这意味着,即使你使用 servicePrincipalName 字段设置了对用户帐户启用 AES 加密,这些帐户仍然会使用对黑客友好的 RC4进行加密,从而可以继续执行 Kerberoast攻击!

经过一些测试,似乎如果你使用这篇文章里描述的方法在域或域控制器级别禁用 RC4 ,那么为任何帐户请求 RC4服务票证都将失败。 然而,TGT 请求也不再适用于 RC4。 因为这可能会导致很多东西出现问题,所以在生产环境中做任何改变之前,一定要先在实验室环境中先尝试进行类似的测试。

旁注: 还可以为表示域信任的 trustedDomain 对象设置 msDS-SupportedEncryptionTypes 属性,但它最初也是未定义的。 这就是为什么内部域的信任票证最终默认使用的是 RC4:

9.png

然而,与用户对象一样,这种行为可以通过修改可信域对象的属性来改变,指定外部域支持 AES:

10.png

这将可信域对象上的 msDS-SupportedEncryptionTypes 的值设置为24(AES128_CTS_HMAC_SHA1_96 | AES256_CTS_HMAC_SHA1_96) ,这意味着内部域将默认发出AES256加密的信任票证:

11.png

尝试建立一个更好的 Kerberoast

由于我们倾向于执行约定的方式,因此,我们经常会倾向于滥用基于主机的功能,而不是在来自攻击者服务器上的我们自己的协议实现中的管道。 我们经常在高延迟的命令和控制服务器(C2)上操作,所以对于像 Kerberos 这样复杂的多方交换,我们的个人偏好传统上总是在使用 KerberosRequestorSecurityToken 方法。 但是正如我在第一个章节中提到的,这个方法在请求服务票证时会请求最高支持的加密类型。 对于启用了 AES 的用户帐户,此默认方法将返回加密类型为 AES256的票证(哈希中的类型是18) :

12.png

现在,Rubeus 的 Kerberoast攻击的一个明显的替代方法是允许指定一个现有的 TGT 块或者文件,然后在票证请求中使用它。 如果我们有一个真正的 TGT,并且正在实现原始的 TGS-REQ或TGS-REP过程并手动提取出正确的加密部分,那么我们可以在发出服务票证请求时指定需要的支持的任何加密类型。 因此,如果我们有启用了AES 的帐户,我们仍然可以得到一个基于 RC4的票证,然后进行离线破解! 实际上,这种方法现在是在 Rubeus 中使用kerberoast 命令的 /ticket:<blob/file.kirbi参数实现的。

那么这种做法的缺点是什么呢?首先,你需要一个票证授予票证来构建原始的 TGS-REQ 服务票证请求,所以你需要: a)在系统上特权升级后并提取出另一个用户的 TGT; b)拥有一个用户的散列,你可以使用 asktgt模块来请求一个新的 TGT。 如果你好奇为什么用户不能在没有特权提升的情况下提取出可用的 TGT 版本,请查看"Rubeus — Now With More Kekeo"这篇文章中的解释。

解决方案是@gentilkiwiKekeo tgtdeleg 技巧,它使用 Kerberos GSS-API 为启用了无约束委派的目标 SPN 请求了一个"假"委派(例如 cifs/DC.domain.com)。 这是以前在 Rubeus 中使用 tgtdeleg 命令实现的。 这种方法允许我们为当前用户提取可用的 TGT,包括会话密钥。为什么我们不在对"易受攻击的"SPN 执行 TGS-REQ 时使用这个"假冒"的委派 TGT,并指定 RC4作为我们支持的唯一加密算法呢?

新的  kerberost /tgtdeleg 选项就是这样做的!

13.png

14.png

在这个字段中,默认的 KerberosRequestorSecurityToken Kerberoast 方法也有失败的时候——我们希望 /tgtdeleg选项可以在其中的一些情况下仍然可以正常工作。

如果我们想更进一步,避免可能的"加密降级"指示器,我们可以搜索不支持 AES 加密类型的帐户,然后声明我们支持服务票证请求中的所有加密类型。 由于结果支持的最高加密类型将是 RC4,我们仍然会得到可破解的票证。 kerberoast /rc4opsec 命令执行 tgtdeleg 技巧并过滤掉这些启用了AES的帐户:

15.png

如果我们想要相反的结果,并且只想要启用了 AES 的帐户,/aes 标志将执行相反的 LDAP 过滤器。 虽然我们目前没有工具来破解使用 AES 的票证(即使我们这样做了,由于 AES 关键的推导算法将使得破解速度会慢上千百倍) ,但是破解的方法正在研究中。

用于 Kerberoast广播的 /tgtdeleg 方法的另一个优点是,由于我们正在手动构建和解析 TGS-REQ/TGS-REP流量,服务票证将不会在我们正在使用的系统上进行缓存。 默认的 KerberosRequestorSecurityToken方法导致在当前登录会话中为我们正在处理的每个 SPN 缓存了一个服务票证。 /tgtdeleg方法导致一个附加的cifs/DC.domain.com 票证被添加到当前的登录会话中,最小化了潜在的基于主机的指示器(即用户登录会话中的大量服务票证)。

作为参考,我在 README 中整理了一个比较了在Rubeus中的不同的kerberost方法的表格:

16.png

最后要说明的是,从这个commit开始,kerberost应该比域信任更有效。 在 README 的 kerberoast 章节中我添加了两个外部可信域的示例。

总结

希望这篇文章的内容消除了一些人(比如我)可能对 kerberoast 的不同加密支持产生的一些困惑。 我也渴望人们尝试使用新的 Rubeus Kerberoast参数,看看他们在该领域会如何工作。

像往常一样,如果我在这篇文章中犯了一些错误,请让我知道,我会尽快纠正它! 此外,如果有人对 “RC4票证依旧可用于仅支持AES的账户”这种情况有什么看法,请给我发电子邮件(will [at] harmj0y. net)或者在 https://bloodhoundgang.herokuapp.com/ 上找我。

本文翻译自:https://posts.specterops.io/Kerberoast-revisited-d434351bd4d1如若转载,请注明原文地址: https://www.4hou.com/system/17739.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论