ADCS攻击系列:滥用ESC10通过配置错误的注册表实现权限提升
Active Directory证书服务(ADCS)负责在AD环境中颁发和管理数字证书。这些证书用于加密和验证用户身份。
与AD的许多组件一样,ADCS自身也存在漏洞,攻击者可利用这些漏洞进行权限提升和域控接管。这些弱点使用“ESC”前缀加数字(如ESC1、ESC2等)来引用特定的错误配置。
在本ADCS系列中,我将以实践性、分步骤的方式逐一剖析错误配置。今天,我们将探讨ESC10,它涉及配置错误的注册表设置,这些设置削弱了证书映射的安全性。
在演示中,我将使用HTB Academy的“ADCS攻击模块”作为实验环境。
目录
- 理解ESC10
- StrongCertificateBindingEnforcement(Kerberos映射)
- CertificateMappingMethods(Schannel映射)
- ESC10利用要求
- 所需工具
- 滥用ESC10
- Kerberos映射
- Schannel映射
- 缓解措施
- 资源
理解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:S4U2Self0x10:S4U2Self显式
如果启用了UPN映射位0x04并且我们控制了一个用户,我们只需将其UPN更改为administrator。然后,当我们请求带有该UPN的证书时,Active Directory会错误地将其映射到实际的Administrator账户。
ESC10利用要求
由于ESC10是关于注册表错误配置的,而不是模板错误配置,因此作为低权限用户无法可靠地识别它。没有域管理员权限,我们无法读取DC的注册表。
这意味着发现过程通常是试错法,我们尝试流程并查看什么能成功。以下是需要检查的内容:
- 控制一个拥有GenericWrite、WriteOwner或WriteDACL等权限的用户或机器账户。
- 任何允许客户端身份验证的证书模板,检查内置模板(如“User”模板)是否已启用。
- 对于滥用Kerberos映射,需要将
StrongCertificateBindingEnforcement设置为0——这种情况很罕见,因为微软正推动在默认情况下(当未设置该键时)强制执行完全强制模式(2)。 - 对于滥用Schannel,需要启用
CertificateMappingMethods的0x04UPN映射标志,此标志默认禁用——同样,在现代环境中也不再常见。
注意: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。
blwasp用户对james拥有GenericAll权限
2. 验证我们对用户的权限
我们可以使用Impacket的dacledit模块来确认我们对目标用户james的权限。
|
|
如输出所示,blwasp对james拥有“FullControl”,确认我们可以继续修改其属性。
blwasp对james拥有完全控制权限
如果我们对目标用户只有WriteOwner或WriteDACL权限,我们需要先修改DACL以授予自己完全控制权。这也可以通过dacledit完成。以下命令授予当前用户对目标用户对象(james)的完全控制权。
|
|
授予当前用户对目标用户的完全控制权
3. 获取目标用户凭据
完全控制目标用户james后,我们有几个选择。我们可以重置他们的密码,也可以使用影子凭据添加额外的凭据。
为了贴合现实场景(我们希望避免重置用户密码并造成操作中断),我们将采用影子凭据方法。
影子凭据允许我们生成自己的密钥对并将其注入目标账户的msDS-KeyCredentialLink属性。这为我们提供了一种以用户james身份进行身份验证的方式,而无需更改其实际密码。
我们将使用Certipy的shadow命令:
|
|
为James创建影子凭据
4. 修改UPN
现在,为了匹配我们想要模拟的身份,在本例中是administrator(域管理员)。这一步很重要,因为稍后我们请求证书时,嵌入证书中的UPN是KDC将用于账户映射的内容。
如果UPN与特权账户匹配,KDC会将证书映射到该账户并允许我们模拟它。要更新用户james的UPN,我们可以使用以下Certipy命令。
|
|
将james的UPN修改为administrator
5. 以模拟用户身份请求证书
在更新目标用户james的UPN并添加影子凭据后,我们现在可以使用易受攻击的模板以james的身份请求证书。
我们可以使用内置的User模板(如果已启用),或任何其他易受攻击的模板,只要它满足以下条件:
- 允许客户端身份验证(扩展密钥用法:客户端身份验证)
- 具有允许低权限用户注册的宽松注册权限,例如Domain Users、Everyone或Authenticated Users。
要请求证书,我们可以使用Certipy中的req选项:
|
|
由于UPN现在与Administrator匹配,证书在身份验证期间将被映射到Administrator账户,允许我们模拟他们。
使用James的哈希请求证书
6. 恢复更改
获取证书后,我们需要将james的UPN恢复为其原始值,以避免身份验证问题。
如果UPN保持为administrator@lab.local,DC可能会将证书映射到错误的对象(在本例中,映射到james而不是真正的Administrator)。这可能在尝试请求TGT时触发名称不匹配错误甚至KDC_ERR_C_PRINCIPAL_UNKNOWN。
|
|
恢复James账户的更改
7. 转储模拟账户的NT哈希
现在我们有了证书,可以使用auth命令以域管理员身份进行身份验证并转储NT哈希:
|
|
Administrator哈希
8. 使用NetExec验证哈希
接下来,使用nxc通过运行以下命令来验证NT哈希:
|
|
验证域管理员哈希
Schannel映射
当CertificateMappingMethods设置为UPN映射(0x04)时,AD信任任何具有匹配UPN的证书;不强制执行强绑定。
这意味着我们可以修改UPN以匹配高权限账户,并且证书将被接受为该账户。
在基于Schannel的身份验证(通常通过LDAPS使用)中,我们无法像在Kerberos案例中那样使用用户证书进行身份验证。Schannel身份验证允许机器证书对目标进行身份验证。
因此,模拟域用户(如域管理员)在这里没有帮助。相反,我们将模拟DC机器账户DC01$@domain.local以访问DC。
步骤与Kerberos案例类似,但这次我们将目标UPN修改为DC账户,而不是域管理员账户。
1. 识别我们可以控制的用户
与之前相同,我们需要控制一个用户或机器对象,以便我们可以修改其UPN进行模拟。我们将再次使用BloodHound来检查当前用户blwasp拥有ACL权限的用户或机器。
我们之前知道用户blwasp对james拥有GenericAll权限。
blwasp对james拥有GenericAll权限
2. 添加影子凭据
与之前相同,我们将使用Certipy创建影子凭据:
|
|
向james账户添加影子凭据
3. 修改UPN
现在我们将修改UPN。但与Kerberos案例中将其设置为域管理员用户不同,我们将为其设置一个DC机器账户的UPN——在本例中,对于Schannel基于证书的身份验证,我们设置为LAB-DC.LAB.LOCAL。
|
|
使用DC机器账户更新james
确保在机器账户名称中包含$并将其格式化为有效的UPN。
4. 以模拟机器账户身份请求证书
现在我们可以使用User模板为james请求证书。由于我们将james的UPN更新为DC的UPN(LAB-DC$@lab.local),生成的证书现在应映射到DC机器账户。
|
|
5. 恢复更改
获取证书后,我们需要将james的UPN恢复为其原始值,以避免身份验证问题,例如证书映射到错误的对象或触发KDC_ERR_C_PRINCIPAL_UNKNOWN。
|
|
6. 通过Schannel连接到DC
接下来,我们使用从滥用ESC10获得的证书对域控制器进行身份验证。Certipy提供了-ldap-shell选项,允许我们通过Schannel(LDAPS)进行绑定。
|
|
如下图所示,我们成功地以LAB\DC$身份通过LDAPS进行了身份验证。
使用lab-dc.pfx证书通过LDAPS访问DC
虽然这不会像我们在获取TGT后通过Kerberos获得交互式shell那样,但Certipy中的LDAP shell确实提供了一些命令,可用于发起攻击,例如基于资源的约束委派(RBCD),以完全接管DC。
LDAP shell命令
RBCD,简而言之,是在目标机器上配置的一种设置,用于定义允许哪些用户或计算机模拟其他用户到该机器。
只有在有权编辑msDS-AllowedToActOnBehalfOfOtherIdentity属性的情况下,才能修改受信任账户列表,允许我们添加我们控制的用户或机器。
在我们的案例中,将添加一个新的计算机账户,并设置DC机器信任我们新创建的账户的RBCD。
7. 创建新的计算机账户
现在我们已经通过LDAPS(Schannel)对域控制器进行了身份验证,我们可以使用Certipy的LDAP shell中的内置add_computer命令创建一个新的计算机账户。
我们将创建一个名为rbcd-test$、密码为PasswordTest123!的机器账户。在LDAP shell中,运行以下命令:
|
|
添加完成后,我们将完全控制rbcd-test$,并可以在下一步中将其用于配置RBCD。
添加新的计算机账户
8. 在DC上设置RBCD
现在我们已经创建了机器账户(rbcd-test$),下一步是配置RBCD,使其能够模拟用户到DC(lab-dc$)。
我们将使用Certipy的LDAP shell中的set_rbcd命令来实现,该命令修改DC计算机对象上的msDS-AllowedToActOnBehalfOfOtherIdentity属性,以包含我们的新机器账户。
|
|
如下图所示,rbcd-test$账户被添加到允许模拟用户到lab-dc$的受信任账户列表中。
在DC上配置RBCD
现在我们有了账户rbcd-test$,它可以模拟任何用户来访问DC。我们必须切换到Kerberos来获取服务票据(ST)并交互式地访问DC。
Schannel允许执行LDAP绑定操作,但它不会授予服务票据或允许你作为另一个用户与SMB或WinRM等服务交互。那是Kerberos的工作。
Schannel身份验证可以为攻击奠定基础,但执行攻击需要Kerberos。
9. 通过Kerberos身份验证获取服务票据
现在RBCD已配置,我们可以使用我们控制的机器账户请求服务票据(TGS)以访问诸如CIFS(用于SMB访问)或HOST(用于WinRM访问)等服务。
我们将模拟Administrator账户:
|
|
如下图所示,如果成功,这会将票据保存在名为administrator@cifs_LAB-DC.LAB.LOCAL@LAB.LOCAL.ccache的.ccache文件中。
获取管理员的ST票据
注意:在现实场景中,不要直接模拟administrator账户,而应在BloodHound中查找一个实际的域管理员进行模拟。这样可以避免因用户不存在而引发“Client not found in Kerberos database”等问题。
10. 设置Kerberos票据
之后,设置KRB5CCNAME变量指向该票据,以便wmiexec或smbclient等工具可以使用它,然后使用klist命令检查票据是否正确导入。
|
|
为KRB5CCNAME设置Kerberos票据
要清除当前的Kerberos票据:
|
|
要设置另一个票据:
|
|
11. 访问DC
最后,我们可以使用smbclient或wmiexec,通过获得的票据交互式地访问DC。
对于SMB访问:
|
|
对于通过WMI执行命令:
|
|
通过WMI访问DC
缓解措施
- 如果尚未应用,请应用KB5014754,该更新强制执行强证书映射。
- 如果未应用补丁,请将
StrongCertificateBindingEnforcement设置为2(完全强制)或至少为1(兼容模式)。 - 禁用弱UPN映射,在
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel中移除或避免使用值0x04——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