CVE-2022-26923——又一个ADCS提权

CVE-2022-26923

前言

周二的微软补丁日中发布了一个针对ADCS 模板滥用漏洞得补丁,相对应的CVE编号是CVE-2022-26923。在经历了spring、vmware、veeam backup和f5等诸多大型产品的漏洞洗礼后,AD终于也迎来了自己的漏洞。漏洞描述中,该漏洞允许拥有普通用户权限的攻击者,实现域内权限提升,获得域控权限。

自从 2021年那篇针对ADCS的白皮书 Certified_Pre-Owned 发布以后,ADCS的安全问题就收到了广泛关注,之前的白皮书中一共总结了ECS 1-8 八种错误配置模板,都可以帮助攻击者轻松获得域控权限,而这次的 CVE-2022-26923 同样是利用了 ADCS 模板的某些配置问题和 AD的一些 “特性” 获得了权限提升。

ADCS身份认证

简单来说,这次的漏洞允许一个拥有普通user权限的攻击者,通过adcs服务,在域内获得权限提升,得到域控的权限。

其实我个人感觉这次的漏洞和之前爆出的 CVE-2021-42287 和 CVE-2021-42278 (通过更改与域控同名机器获取权限提升)也有相似之处,更像是在某些方面将二者组合。漏洞作者在文章中也说确实是受二者启发。

ADCS

还是简单介绍一下ADCS

img

引用白皮书中的描述:

AD CS 是一个服务器角色,用作 Microsoft 的公钥基础结构 PKI 实施。正如预期的那样,它与 Active Directory 紧密集成并支持颁发证书,这些证书是 X.509 格式的数字签名电子文档,可用于加密、消息签名和/或身份验证

ADCS 是一套域内的证书服务,安装了ADCS服务的域内允许通过CA签发的证书进行身份认证。本质上来说ADCS同样遵循X.509协议,客户端将公钥与模板等信息发送给服务端,服务端检查客户端身份以及权限是否允许,并按照模板中约定的事项,使用自己的私钥进行签发证书。

模板

ADCS模板是证书注册策略与配置的集合,它同样是一个AD对象,在ldap中的存储为 CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=cia,DC=local,他存储了所有证书的配置,例如 证书的有效期、用途、主题等。当然并不是所有配置都可以用于注册,而大部分的ADCS攻击面也是针对模板的。

用户可以根据预定义的证书模板请求证书并应用于不同场景,而本次漏洞所关注的用途依然是客户端身份验证。

身份认证

ADCS允许利用于身份认证的场景,一个合法的场景中,用户可以通过正确的凭证向CA申请 User 模板的证书。而后在该证书的有效期内我们都可以通过kerberos中的PKI延展向域控请求有效的TGT票据。

CVE-2022-26923

值得注意的是,同样是用于身份认证,然而用户和机器拥有两套模板。这意味着用户和机器使用证书进行身份认证时肯定存在不同的配置,或许是不同的认证参数,或是不同的校验方式。

User模板

经过观察发现,用户证书模板中包含User的UPN属性,每一个User角色都包含User Principal Name (UPN)属性,正如服务账户包含SPN一样。而User模板将UPN用于识别用户,即将UPN用于将证书映射到用户本身。

DC-2022-05-12-04-54-59

根据微软的唯一性约束: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3c154285-454c-4353-9a99-fb586e806944 , UPN与SPN一样是强制唯一的,每一个用户拥有唯一的UPN,这意味着我们不可能获取具有两个相同UPN的用户,同理,我们也无法为不同用户申请相同身份映射的证书。

Machine模板

然而machine并没有UPN这个参数,那机器用户的证书模板使用什么表明用户身份呢,

img

可以看到,模板中指定的是主机的dns值。

而主机的dns命名,保存在主机用户的 dNSHostName 字段

image-20220512050605329

然而值得注意的是,该字段与UPN和SPN不同,**该字段并不具有强制唯一的原则**

而根据微软的策略:https://docs.microsoft.com/en-us/windows/win32/adschema/r-validated-dns-host-name

允许兼容不相同的dns名称与主机名。例如,samaccountnametest$ 的机器,他的 dNSHostName 可以是 qwe.cia.local

这就意味着,我们可以拥有两个有相同 dNSHostName 值的不同机器,同样意味着,或许可以为不同机器申请相同映射的证书。这句话换一种表达就是,或许可以为某台机器申请映射到另一台机器身份的证书。

漏洞探索

于是我们可以联想到之前的CVE-2021-42287 和 CVE-2021-42278,或许同样可以将机器用户的dNSHostName 改为域控的值以获得映射到域控的证书。与CVE-2021-42287 和 CVE-2021-42278相同,用户对自己创建的机器的dNSHostName 同样具有写权限

img

这意味着我们或许可以将其改为与域控相同的值。

然而此时我们会遇到问题。

image-20220512053457184

可以看到机器账户的SPN其中有的是和dNSHostName 相关联的,当dNSHostName 改变时,SPN会相应的改变,而当改为和域控相同时,该SPN理论上会改为部分与域控相同,然而正如前面所说,SPN是唯一性的,并不可以有两个相同的SPN,因此直接更改dNSHostName会间接导致SPN冲突导致失败。

又经过观察,SPN只有后两个值是包含dNSHostName,而前两个包含的是samaccountname,如果能把他们删掉的话,是不是就不会造成冲突了呢。同样,用户对创建的机器的SPN同样拥有写权限,之前的文章也讨论过针对滥用SPN写权限造成的危害。

img

于是我们可以将该机器包含dNSHostName的SPN删除,然后就可以成功更改机器的dNSHostName为dc的dNSHostName了!

image-20220512054645714

当我们为b1uepc$申请Machine模板的身份认证证书时,成功获取了带有dc的dns名 dc.cia.local 的证书!

image-20220512054951983

证书映射

这次的攻击并不需要像之前的漏洞那样,在申请了tgt后再次更改用户名为其他值,而证书在映射用户时却同样不会产生冲突,这是由于PKINIT 的证书映射机制

KDC首先从AS-REQ中获取请求主体名,例如 user@cia.local ,根据主题名查找账户。然后根据 UAC ,KDC会根据证书主题中的UPNname或DNSname验证映射。KDC会根据samaccountname和域名验证DNSname,例如当 ‘cia.local\test$’ 的 DNSname 为 ‘test.cia.local’ 时,验证成功。而用户的dNSHostName并不被再次用于验证,该值只在申请证书时用于标明。

因此,并不需要再次改变用户的dNSHostName。

复现

针对ADCS的python工具Certipy 已经更新关于该漏洞的利用,通过Certipy,我们可以轻松利用CVE-2022-26923进行域内的提权操作

  • 新建机器账户

新建用户

  • 更改dNSHostName并申请证书与票据

申请证书与证书

  • 获取hash

获取hash

总结

总结一下这个漏洞的成因

  1. 机器用户申请的ca证书,使用域信息里的 dNSHostName 参数进行认证
  2. 域内成员的dNSHostName参数不强制唯一
  3. 用户对自己创立的机器用户的dNSHostName与SPN具有写权限
  4. 更改创建的机器用户的dNSHostName为域控同名,获得域控权限

这也是一个很精彩的漏洞,而且感觉针对这种 “重名” 的利用方式应该还会有其他的姿势等待挖掘,慢慢期待一下。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!