译文 | 介绍黄金 GMSA 攻击
2022-3-1 22:50:0 Author: mp.weixin.qq.com(查看原文) 阅读量:35 收藏

开卷有益 · 不求甚解


前言

本文介绍了一种针对组管理服务帐户 (gMSA) 的新攻击,称为“黄金 GMSA”攻击,允许攻击者转储密钥分发服务 (KDS) 根密钥属性,然后离线生成所有关联 gMSA 的密码。

TL;DR

具有高权限的攻击者可以通过两个步骤随时获得生成域中任何 gMSA 密码的所有成分:

  1. 从域中的 KDS 根密钥中检索多个属性
  2. 使用GoldenGMSA工具生成与密钥关联的任何 gMSA 的密码,无需特权帐户。

gMSA 101

服务帐户的密码通常不会定期轮换,这使它们处于危险之中,尤其是因为它们可以通过Kerberoasting 攻击成为目标。gMSA (组托管服务帐户;小写g 是个谜)是 Windows Server 2012 中引入的一种特殊类型的 Active Directory (AD) 帐户,用于解决这个确切的问题。此对象的唯一目的是用作服务帐户,具有密码轮换的重要功能。一个或多个具有兼容服务的服务器可以使用 gMSA 帐户。

gMSA 的密码由 AD 管理。每 30 天自动轮换一次,随机生成 256 字节的密码,无法破解。正如Microsoft 文档所述:

MS Docs 中的 Microsoft 密钥分发服务描述

密码是根据定期更改的秘密和 gMSA 的未命名属性计算的。使用的密钥存储在 KDS 根密钥对象中。

自动轮换密码——这怎么可能?

这种帐户背后的想法很有趣。可写 DC 管理 gMSA 的密码并每 30 天轮换一次(默认情况下)。当使用此帐户的服务器需要使用 gMSA 时,它首先通过检索名为msDS-ManagedPassword的属性从 DC 请求最新密码。此属性是包含密码的二进制大对象 (BLOB)。

MSDS-ManagedPassword_BLOB

gMSA 的 msDS-GroupMSAMembership 属性指定允许谁获得密码。反过来,可写 DC 使用此属性来验证调用者是否有权获取它。到目前为止,我们可以看到一种直接滥用它的方法:如果攻击者获得了可以访问 msDS-ManagedPassword 的帐户的访问权限,则攻击者可以读取特定 gMSA 的密码。

密码存储

DC 通常不在其数据库中存储密码,而仅在密码中存储秘密。这就提出了一个问题:假设可写 DC 不存储明文密码;如何通过读取 msDS-ManagedPassword 属性来检索它?事实证明 msDS-ManagedPassword 是一个构造属性,这意味着该属性不存储在 AD 中,而是在授权用户尝试读取它时计算出来的。

msDS-ManagedPassword 是如何构造的?

我们现在知道密码是由可写 DC 按需构建的。我们也知道每一个可写的DC都可以构造属性,结果总是一样的。此页面显示了密码是如何生成的,但不够详细,无法让我们自己构建它。

寻找构造该属性的函数将引导我们找到 ntdsai.dll!dbGetConstructedAtt,它是负责构造属性的函数。

dbGetManagedServiceAccountPassword

我们可以看到对dbGetManagedServiceAccountPassword的调用,但我们只对密码感兴趣,而不是整个ManagedPasswordBlob 。深入挖掘函数最终导致我们调用函数KdsCli.dll !KdsGetGmsaPasswordBasedOnKeyId。

KdsGetGmsaPasswordBasedOnKeyId

让我们回顾一下这个函数的参数:

  • _SecurityDescriptor 是一个预定义的安全描述符 (SD),硬编码在 ntdsai.dll 中,授予 S-1-5-9(企业域控制器)读写权限,如下图所示:
gmsa安全描述符
  • _SID 是所需 gMSA 的 ObjectSID。
  • _MsdsManagedPasswordID 是 gMSA 对象的一个属性,除其他外,它通过 GUID 引用 gMSA 用于密码生成的 KDS 根密钥实例。我们没有找到这个属性的正式文档,但是更多的逆向帮助我们弄清楚了如何使用下面屏幕截图中显示的参数自己构建它。
Msds_ManagedpasswordID
  • _OutPassword 是指向将存储密码的缓冲区的指针。
  • 密码大小是将写入 OutPassword 的字节数。它的硬编码值为 256。

检索密钥并构造密码

执行流程最终到达函数 GetKeyFromKdsService,它调用 RPC 方法GetKey。

获取密钥状态

我们可以看到参数与 [ MS-GKDI ]中的文档相匹配

GetKey 方法

有趣的说明: GetKey 对调用者提供的 TargetSD 执行访问检查,这意味着我们可以使用授予我们访问权限的安全描述符调用此函数,并且 DC 将返回一个密钥。不幸的是,SD 也用于密钥的计算。因此,即使我们总是可以更改 SD 以绕过访问检查,除非提供的 SD 是有效的,否则我们将得到一个无效的密钥。产生有效密钥的唯一有效安全描述符是我们之前提到的硬编码安全描述符 (gmsaSecurityDescriptor),它只授予企业域控制器访问权限 (S-1-5-9)。

如果调用者具有所需的权限,则此方法会生成一个密钥并将其返回到组密钥信封(GKE) 结构中。获得密钥后,我们终于可以调用 kdscli.dll!_GenerateGmsaPassword 生成密码了。

生成 Gmsa 密码

第六个和第七个参数是可选的,不影响密码。因此,为此,我们可以将它们设置为 null。

gMSA 密码生成回顾

gMSA 密码是通过调用驻留在 kdscli.dll(不幸的是,未导出)中的函数生成的,我们在任何 Windows 端点上都有该函数。调用这个函数需要三件事:

  1. SID
  2. gMSA 的 msds-ManagedPasswordID(可以使用 LDAP 查询检索)
  3. GKE,可以通过RPC调用高权限DC上的GetKey方法生成

实现 GetKey 和离线密码生成

我们试图尽可能简化生成 gMSA 密码,使其可以离线完成。该过程中唯一的 RPC 调用是针对 GetKey。因此,我们决定将其反转并移植到生成 GKE 的 C# 代码中。

正如 Microsoft 所记录的,我们发现密钥会定期更改。但是密钥是从 KDS 根密钥对象的属性和三个从时间戳派生的整数(L0KeyID、L1KeyID、L2KeyID)派生的,如下面的屏幕截图所示。

获取当前间隔ID

当前时间戳存储在 gMSA 的 msDS-ManagedPasswordID 属性中,默认情况下所有域用户均可读取,因此我们可以检索时间戳并生成这些整数。

DC 用于生成密码但我们没有的唯一成分是 KDS 根密钥的以下属性:

  • cn
  • msKds-SecretAgreementParam
  • msKds-RootKeyData
  • msKds-KDFParam
  • msKds-KDF算法ID
  • msKds-创建时间
  • msKds-UseStartTime
  • msKds-版本
  • msKds-DomainID
  • msKds-PrivateKeyLength
  • msKds-PublicKeyLength
  • msKds-SecretAgreementAlgorithmID

检索这些属性需要对 KDS 根密钥对象具有读取和扩展权限,默认情况下只有域管理员拥有。但是,这些值不会定期更改。

这意味着,如果我们破坏这些值,我们可以使用它们为与 KDS 根密钥关联的任何 gMSA 计算 GKE,并离线生成其密码。

黄金 GMSA 攻击

Golden GMSA 攻击发生在攻击者转储 KDS 根密钥的相关属性,然后使用它们为关联的 gMSA 帐户离线生成密码时。Golden GMSA 攻击有点类似于 Golden Ticket 攻击,只要 krbtgt 密码保持不变,攻击者就可以通过破坏 krbtgt 帐户来伪造 Ticket Granting Tickets (TGT)。

Golden Ticket 攻击和 Golden GMSA 攻击之间的一个显着区别是我们不知道旋转 KDS 根密钥秘密的方法。因此,如果 KDS 根密钥被泄露,则无法保护与其关联的 gMSA。在这种情况下,唯一的缓解措施是使用新的 KDS 根密钥创建新的 gMSA。

将 Golden GMSA 攻击武器化

我们将 Golden GMSA 攻击武器化为您可以在此处下载的工具。

GoldenGMSA 攻击工具可以从指定的 KDS 根密钥对象中检索必要的属性或使用用户提供的值来生成 GKE。该工具还可以根据 gMSA SID 检索 msDS-ManagedPasswordID,当然,还可以离线生成 gMSA 的密码。

攻击者可以通过伪造 Silver Ticket 或通过 S4U2Self 获取特权帐户的 Kerberos 服务票证来使用密码破坏使用 gMSA 的服务。如果 gMSA 具有高权限,攻击者可能会使用它来破坏其他资源,并且在某些情况下会破坏整个林。

Golden GMSA 攻击示例

攻击者可以使用 GoldenGMSA 工具枚举所有 gMSA 及其关联的 KDS 根密钥。具有高权限的攻击者还可以使用 GoldenGMSA 工具转储 KDS 根密钥。

攻击者稍后可以使用转储的 KDS根密钥BLOB完全离线生成 gMSA的密码。

密码是 Base64 编码的,因为它可能包含不可打印的字符。

检测 Golden GMSA 攻击

默认情况下, KDS根密钥的泄露不会生成安全事件。防御者应该在KDS根密钥对象上为每个读取msKds -RootKeyData属性的人配置 SACL 。配置系统访问控制列表 ( SACL )后,任何转储KDS根密钥的密钥数据的尝试都将在DC上生成安全事件4662 ,其中 对象类型是 msKds- ProvRootKey并且帐户名称不是DC ,如以下屏幕截图所示:

事件 4662 对对象执行了操作

防御 Golden GMSA 攻击

组托管服务帐户是一项出色的 Active Directory 功能,可以减轻与服务帐户相关的一些风险,例如 Kerberoasting 攻击。但是,与 gMSA 关联的密码是使用如果受到破坏就无法轮换的输入生成的,这使得具有高权限的攻击者可以转储 KDS 根密钥并离线生成关联 gMSA 的密码,只要它们存在。

防御者应监控对 KDS 根密钥的异常访问,例如读取 msKds-ProvRootKey 属性的非 DC 和链接到 gMSA 帐户的异常登录事件。

译文申明

  • 文章来源为近期阅读文章,质量尚可的,大部分较新,但也可能有老文章。
  • 开卷有益,不求甚解,不需面面俱到,能学到一个小技巧就赚了。
  • 译文仅供参考,具体内容表达以及含义, 以原文为准 (译文来自自动翻译)
  • 如英文不错的,尽量阅读原文。(点击原文跳转)
  • 每日早读基本自动化发布(不定期删除),这是一项测试

最新动态: Follow Me

微信/微博:red4blue

公众号/知乎:blueteams



文章来源: http://mp.weixin.qq.com/s?__biz=MzU0MDcyMTMxOQ==&mid=2247485822&idx=1&sn=7d6fcfdd0338b68f7f9e146b77580cc5&chksm=fb35a0b6cc4229a0f0c76f0b351cfcaf33ab374a6f51d2760a02d609e223e715cbd72b21b72b#rd
如有侵权请联系:admin#unsafe.sh