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
引用白皮书中的描述:
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用于将证书映射到用户本身。
根据微软的唯一性约束: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/3c154285-454c-4353-9a99-fb586e806944 , UPN与SPN一样是强制唯一的,每一个用户拥有唯一的UPN,这意味着我们不可能获取具有两个相同UPN的用户,同理,我们也无法为不同用户申请相同身份映射的证书。
Machine模板
然而machine并没有UPN这个参数,那机器用户的证书模板使用什么表明用户身份呢,
可以看到,模板中指定的是主机的dns值。
而主机的dns命名,保存在主机用户的 dNSHostName
字段
然而值得注意的是,该字段与UPN和SPN不同,**该字段并不具有强制唯一的原则**
而根据微软的策略:https://docs.microsoft.com/en-us/windows/win32/adschema/r-validated-dns-host-name
允许兼容不相同的dns名称与主机名。例如,samaccountname
为 test$
的机器,他的 dNSHostName
可以是 qwe.cia.local
这就意味着,我们可以拥有两个有相同 dNSHostName
值的不同机器,同样意味着,或许可以为不同机器申请相同映射的证书。这句话换一种表达就是,或许可以为某台机器申请映射到另一台机器身份的证书。
漏洞探索
于是我们可以联想到之前的CVE-2021-42287 和 CVE-2021-42278,或许同样可以将机器用户的dNSHostName
改为域控的值以获得映射到域控的证书。与CVE-2021-42287 和 CVE-2021-42278相同,用户对自己创建的机器的dNSHostName
同样具有写权限
这意味着我们或许可以将其改为与域控相同的值。
然而此时我们会遇到问题。
可以看到机器账户的SPN其中有的是和dNSHostName
相关联的,当dNSHostName
改变时,SPN会相应的改变,而当改为和域控相同时,该SPN理论上会改为部分与域控相同,然而正如前面所说,SPN是唯一性的,并不可以有两个相同的SPN,因此直接更改dNSHostName会间接导致SPN冲突导致失败。
又经过观察,SPN只有后两个值是包含dNSHostName,而前两个包含的是samaccountname,如果能把他们删掉的话,是不是就不会造成冲突了呢。同样,用户对创建的机器的SPN同样拥有写权限,之前的文章也讨论过针对滥用SPN写权限造成的危害。
于是我们可以将该机器包含dNSHostName的SPN删除,然后就可以成功更改机器的dNSHostName为dc的dNSHostName了!
当我们为b1uepc$申请Machine模板的身份认证证书时,成功获取了带有dc的dns名 dc.cia.local
的证书!
证书映射
这次的攻击并不需要像之前的漏洞那样,在申请了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
总结
总结一下这个漏洞的成因
- 机器用户申请的ca证书,使用域信息里的 dNSHostName 参数进行认证
- 域内成员的dNSHostName参数不强制唯一
- 用户对自己创立的机器用户的dNSHostName与SPN具有写权限
- 更改创建的机器用户的dNSHostName为域控同名,获得域控权限
这也是一个很精彩的漏洞,而且感觉针对这种 “重名” 的利用方式应该还会有其他的姿势等待挖掘,慢慢期待一下。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!