Active Directory 证书服务攻击与防御(一)

阅读量    101534 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

作者: daiker@Amulab

0x00 前言

specterops发布了一篇关于Active Directory 证书服务相关漏洞的白皮书

https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf,关于Active Directory 证书服务的攻击第一次系统的进入我们的视野。

我在白皮书的基础上学习了Active Directory 证书服务相关的漏洞,作为学习成果,用两篇文章来介绍Active Directory 证书服务相关的基础以及相关的漏洞利用。截止这篇文章发布为止,有些漏洞利用相关的工具并没有发布出来,在文章里面我会用其他的方式来演示。

白皮书里面,最核心的点在于证书服务发布的部分证书可用于kerberos认证,并且在返回的PAC里面能拿到NTLM hash。这就是可以做很多事了,比如

1、拿到用户的凭据,能不能用用户的凭据来申请一个证书,这个证书用于kerberos认证,后面就算用户的密码改了,只要证书在手,就能用证书随时拿回NTLM。

2、能不能在用户的电脑上找到证书,以后拿着这个证书去做认证。

3、什么样的证书能用于kerberos认证。

4、拿到CA服务器证书之后,能不能给任何用户颁发证书,再用这个证书做认证,跟黄金票据一样。

5、CA服务器上有没有一些配置,能让一个用户申请别人的证书,然后拿到这个证书做认证。

6、CA证书申请有个界面是http的,http默认不开签名,我们能不能通过Ntlm_Relay将请求relay到这里,申请用以进行kerberos认证的证书。

关于这些,都会在这两篇文章里面讨论。在写完之后,由于内容过长,我将文章拆分为两篇,第一篇是介绍一些基础部分,以及三个相关的利用

1、窃取证书

2、通过凭据申请可用以Kerberos认证的证书

3、通过证书窃取用户凭据

在第二篇主要介绍一些其他的利用,包括

1、证书服务中的Ntlm_Relay

2、证书模板配置错误

3、黄金证书

3、PKI 设计缺陷

4、防御指南

整体的思路如下图

 

0x01 Active Directory 证书服务安装

在开始讲解证书服务之前,我们先装个证书服务,方便起见,直接在域控上安装就行。

下一步下一步比较简单。

 

0x02 Active Directory 证书服务概述

0x0201 企业 PKI

​ PKI是一个术语,有些地方会采用中文的表述——公钥基本结构,用来实现证书的产生、管理、存储、分发和撤销等功能。我们可以把他理解成是一套解决方案,这套解决方案里面需要有证书颁发机构,有证书发布,证书撤掉等功能。

​ 微软的Active Directory 证书服务(我们可以简称AD CS)就是对这套解决方案的实现。ADCS能够跟现有的ADDS服务进行结合,可以用以加密文件系统,数字签名,以及身份验证。下面详细介绍下AD CS中比较重要的的证书颁发机构以及证书模板。

0x0202 证书颁发机构

证书颁发机构 (CA) 接受证书申请,根据 CA 的策略验证申请者的信息,然后使用其私钥将其数字签名应用于证书。然后 CA 将证书颁发给证书的使用者。此外,CA 还负责吊销证书和发布证书吊销列表 (CRL)。

ADCS里面的CA分为企业CA和独立CA,最主要的区别在于企业CA与ADDS服务结合,他的信息存储在ADDS数据库里面(就是LDAP上)。企业CA也支持基于证书模板和自动注册证书,这也是我们比较关心的东西,如果没有特指,文章里面提到的CA默认就是企业CA。

举个例子,我们有个有个域名daiker.com,如果要做https,我们就需要找证书颁发机构申请证书,比如说沃通CA。

我们也可以自己搭建一个证书颁发机构。

但是使用自建的证书发布服务之后,浏览器还是不信任我们证书,我们经常可以看到

自行签名的根证书。之所以出现这个是因为电脑本身并不相信我们的CA证书。以下证书是windows内置的CA证书。如果我们能够把我们的CA证书放在这个列表里面,我们的证书就能得到信任。

对于企业来说,如果使用ADCS服务,想让员工的计算机信任我们企业自己的CA证书,有以下几种方式

1、安装企业根CA时,它使用组策略将其证书传播到域中所有用户和计算机的“受信任的根证书颁发机构”证书存储

2、如果计算机不在域内,可以手动导入CA证书

另外AD CS支持可缩放的分层 CA 模型,在此模型中,子从属 CA 由其父 CA 颁发的证书认证。层次结构顶部的 CA 称为根 CA。根 CA 的子 CA 称为从属 CA。

以上图为例子,每个企业仅有一个根CA,他由自己颁发,在大多数组织中,它们只用于颁发从属 CA,不直接颁发证书。而具体的证书由从属CA颁发,比如网站的证书,LDAPS的证书,这样做方便管理,在机器比较多的域内还能起到负载均衡的作用。当然,AD CS支持分层的CA模型不代表一定要分层,对于比较小的公司,一般都只有一个根CA,所有的证书由这个根CA进行颁发。

0x0203 证书模板

证书模板是证书策略的重要元素,是用于证书注册、使用和管理的一组规则和格式。这些规则是指谁可以注册证书。证书的主题名是什么。比如要注册一个web证书,那可以在Web服务器这个默认的证书模板里面定义谁可以注册证书,证书的有效时间是多久,证书用于干啥,证书的主题名是什么,是由申请者提交,还是由证书模板指定。

我们可以使用certtmlp.msc打开证书模板控制台

这些都是系统默认的证书模板。

如果需要发布一个新的模板的话,可以右键复制模板,然后自己定义这些规则。

我们关心以下规则

  • 常规设置:交付证书的有效期,默认是一年

  • 请求处理:证书的目的和导出私钥的能力(虽然设置了证书不可被导出,但是mimikatz依旧能导出,我们后面会详细说)
  • 加密:要使用的加密服务提供程序 (CSP) 和最小密钥大小
  • Subject name,它指示如何构建证书的专有名称:来自请求中用户提供的值,或来自请求证书的域主体的身份。这个需要注意的是,默认勾选了在使用者名称中说那个电子邮件名,当用户去申请的时候,如果用户的LDAP属性没有mail就会申请失败。

  • 颁发要求:CA证书经理程序批准

这个值得注意,就算用户有注册权限(在ACL里面体现),但是证书模板勾选了这个,也得得到证书管理的批准才能申请证书,如果没有勾选这个,那有权限就可以直接申请证书了。

  • 安全描述符:证书模板的 ACL,包括具有注册到模板所需的扩展权限的主体的身份。关于这个的内容看证书注册那节的证书注册权限里面。
  • 扩展:要包含在证书中的 X509v3 扩展列表及其重要性(包括KeyUsageExtendedKeyUsages

​ 这里我们要特别注意的是扩展权限里面的应用程序模板,

这个扩展决定了这个模板的用途,比如说文档加密,文档签名,智能卡登陆等等。

经过测试与研究,spectorops的工程师发现包含以下扩展的证书可以使用证书进行kerberos认证。

1、客户端认证

2、PKINIT 客户端身份验证

3、智能卡登录

4、任何目的

5、子CA

其中PKINIT不是默认存在的,需要我们手动创建,点击新建,名称自定义,对象标识符为1.3.6.1.5.2.3.4

 

0x03 证书注册

0x00301 证书注册流程

1、客户端生成一个证书申请文件,这一步可以使用openssl生成,比如

openssl req -new -SHA256 -newkey rsa:4096 -nodes -keyout www.netstarsec.com.key -out www.netstarsec.com.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=netstarsec/OU=sec/CN=www.netstarsec.com"

或者直接找个在线的网站https://myssl.com/csr_create.html生成

2、客户端把证书申请文件发送给CA,然后选择一个证书模板。

这一步可以申请的方式比较多,上面这种是通过访问证书注册界面进行注册的。ADCS请求注册证书的方式在下一小节具体说明。

3、CA证书会判断模板是否存在,根据模板的信息判断请求的用户是否有权限申请证书。证书模板会决定证书的主题名是什么,证书的有效时间是多久,证书用于干啥。是不是需要证书管理员批准。

4、CA会使用自己的私钥来签署证书。签署完的证书可以在颁发列表里面看到。

0x00302 证书注册接口

1、访问证书注册网页界面

要使用此功能,ADCS 服务器需要安装证书颁发机构 Web 注册角色。我们可以在添加角色和功能向导>AD证书颁发机构Web注册服务里面开启。

开启完就访问https://CA/certsrv 访问证书注册网页界面

2、域内机器可以通过启动 certmgr.msc (用于用户证书)或 certlm.msc (用于计算机证书)来使用 GUI 请求证书

3、域内机器可以通过命令行certreq.exe和PowershellGet-Certificate来申请证书

4、使用MS-WCCE,MS-ICPR这俩RPC,具体交互流程得去看文档

5、使用CES,需要安装证书注册WEB服务,soap的格式,具体的交互流程得看MS-WS-TEPMS-XCEP

6、使用网络设备注册服务,得安装网络设备注册服务

0x0303 证书注册权限

知道了证书注册的流程,注册的接口,接下来我们关注的就是证书注册的权限。跟证书注册相关的权限主要有两块,一块体现在CA证书上,一块体现在证书模板上。

我们可以运行certsrv.msc之后右键证书颁发机构,右键属性,安全查看权限。

对于CA证书的权限,我们比较关注的是请求证书的权限。默认情况下,所有认证用户都有请求权限。如果有请求的权限,CA就去判断请求的模板是否存在,如果存在,就交给证书模板去管理权限。

证书模板的权限,可以运行certtmpl.msc之后选择特定的证书模板,右键属性,安全查看权限

我们比较关注以下权限

  • 注册权限(Enroll)

拥有这个权限的用户拥有注册权限

  • 自动注册的权限(AutoEnrollment)在配置证书自动注册的时候需要证书模板开启这个权限,关于证书自动注册的更多细节,在下一小节会详细说明。
  • AllExtendedRights/Full ControlAllExtendedRights 包括所有的扩展权限,就包括了注册权限和自动注册权限。Full Control包括所有权限,也包括有的扩展权限

我们关心完CA的权限以及证书模板的权限之外,还得注意一个配置CA证书管理程序批准

如果证书模板没有勾选这个,那么有ca的证书请求权限,证书模板的注册权限,就可以申请下证书。但是如果勾选了这个选项,那么就算有注册权限,那也得得到证书管理员的批准才能注册证书。

0x0304 证书自动化注册

相较于注册,自动化注册顾名思义就是自动化,不需要用户手动注册。有些软件需要用户证书去访问,让每个用户自己手动申请证书又不太现实,这个时候自动化注册证书的优势就体现出来了。

接下来演示下怎么配置证书自动化注册。

1、配置一个证书模板

选择一个已有的模板,右键复制模板

名字改成用户自动化注册

去掉以下两个勾,因为有些用户可能没有配置邮箱,自动化申请证书的时候就会失败。

给这个证书模板赋予任何Domain Users有注册和自动化注册的权限

然后下发一个组策略

新建一个组策略,命名为自动注册证书

然后打开用户配置>策略>安全设置>公钥策略,配置下图圈出来的三个

然后等组策略生效,域内的每个用户登录的时候都会自动申请一个证书,不用人为申请证书。

 

0x04 Active Directory 证书服务在LDAP中的体现

ADCS的信息同样也存储在LDAP上,我们可以在配置分区底下的Service底下的Public Key Services看到证书相关的信息

,比如在我们的环境就位于CN=Public Key Services,CN=Services,CN=Configuration,DC=test16,DC=local

每一块的对象的用途都不一样,接下来我们详细介绍我们比较关注的几个对象

  • Certification Authorities

这个对象是证书颁发机构,定义了受信任的根证书。

每个 CA 都表示为容器内的一个 AD 对象,objectClass为certificationAuthority

CA证书的内容以二进制的内容放在cACertificate底下。

  • Enrollment Services这个对象定义了每个企业 CA。每个企业CA 都表示为容器内的一个 AD 对象,objectClass为pKIEnrollmentServiceCA证书的内容以二进制的内容放在cACertificate底下。dNSHostName定义了CA的DNS主机
  • certificateTemplates这个对象定义了所有证书模板
  • NTAuthCertificates此条目用于存储有资格颁发智能卡登录证书并在 CA 数据库中执行客户端私钥存档的 CA 的证书。关于智能卡,后面会单独写一篇文章详细阐述智能卡,在这篇文章里面,默认提及的证书都是软件层面的,不涉及到硬件的。
  • CDP这个容器存储了被吊销的证书列表

 

0x05 窃取证书

在我们控的计算机上可能会存在一些证书,这些证书有可能是用客户端身份验证,有可能是CA证书,用以信任其他证书的。我们可以将这些证书导出来,这里我们分为两种情况导出来。

0x0501 从系统存储导出证书

这种情况我们使用windows自带的命令certutil来导出

certutil默认查看的是计算机证书,可以通过指定-user参数来查看用户证书

(图形化查看用户证书是命令是certmgr.msc,图形化查看计算机证书的命令是certlm.msc)

certutil还可以通过-store来查看存储分区,参数有CA,root,My分别对应中间证书机构,个人证书,受信任的根证书颁发机构

有些证书在导入的时候需要密码或者勾选证书不可导出

这个时候就需要使用mimikatz来导出证书了。下面我们举两个导出的案例。

1、导出用户证书

打开certmgr.msc

如果我们想查看个人证书可以用

certutil -user -store My

找到我们想导出的证书的hash

如果仅仅是只是导出证书,不导出私钥

certutil -user -store My f95e6b5dbafac54963c450052848745a54ec7bd9 c:\Users\test1\Desktop]test1.cer

如果要导出证书包含私钥

certutil -user -exportPFX f95e6b5dbafac54963c450052848745a54ec7bd9 c:\Users\test1\Desktop]test1.pfx

这一步如果我们需要输入一个密码,这个密码是待会儿这个导出的证书 导入到咱们的电脑的时候要用的

2、查看计算机证书

打开certlm.msc

如果我们想查看计算机证书可以用

certutil -store My

找到我们想导出的证书的hash

certutil -store My 888d67d9ef30adc94adf3336462b96b5add84af4 c:\Users\test1\Desktop\win10.cer

在我们要导出pfx文件的时候

这种是勾选了证书不允许被导出的,certutil就导出不了,回过去看我们刚刚查看证书的hash的时候

就可以看到,里面标志着私钥不能被导出,这个时候我们就需要用到mimikatz了,mimikatz的crypto::certificates默认也是不支持导出私钥不能被导出类型的证书的私钥】

这个时候可以使用crypto::capi修改lsass

然后就可以导出了

0x0502 从文件系统搜索证书

我们经常可以在邮件,磁盘里面看到证书,我们一般按照后缀来搜索证书的,我们一般关注以下后缀

1、key后缀的,只包含私钥

2、crt/cer 后缀的,只包含公钥

3、csr后缀的,证书申请文件,不包含公钥,也不包含私钥。没啥用

4、pfx,pem,p12后缀的,包含公私钥,我们最喜欢的。

搜索文件后缀的每个人使用的工具不一样,我个人比较喜欢的是SharpSearch,.Net的项目,支持内存加载,可以写成CNA插件。

 

0x06 通过用户凭据申请可用于kerberos认证的证书

在所有默认的证书模板里面,我们最关注的模板默认有用户模板和计算机模板。

前面我们说过,使用认证进行kerberos认证的需要扩展权限里面包含以下其中一个

1、客户端身份认证

2、PKINIT 客户端身份验证

3、智能卡登录

4、任何目的

5、子CA

如果用户如果想要注册证书,需要经过两个权限的检验。

1、在CA上具有请求证书的权限,这个默认所有认证的用户都有请求证书的权限。

2、在模板上具有注册证书的权限。

用户/计算机模板,他刚好满足这些条件。

1、他们的扩展属性都有客户端身份认证

2、用户证书默认所有的域用户都有注册权限

3、计算机默认所有的域内计算机都有注册权限

4、用户/计算机模板不需要企业管理员批准

这两个默认的证书模板,让我们不需要有域管的凭据,只需要一个域内用户的凭据,就可以注册证书,这个证书还可用于进行kerberos认证。因此我们这里注册的时候选择的模板是用户/计算机模板(具体哪个模板看我们拥有的凭据是用户还是计算机)。

当我们拿到用户的凭据,想使用这个凭据去申请用户证书,我们可以

1、访问证书注册网页界面

这个咱们之前说过,需要安装证书颁发机构 Web 注册角色。我们可以尝试访问下,访问的路径是https://CA/certsrv,会弹401认证,我们输入用户的凭据就行。

这个浏览器建议用IE

2、使用certmgr.msc申请

如果我们在域内,直接打开certmgr.msc申请就行

 

0x07 通过证书窃取用户凭据

0x0701 请求kerberos证书

在传统的kerberos认证的时候,是使用用户密码进行认证的。回顾下申请TGT的过程。

用用户hash加密时间戳作为value,type为PA-ENC-TIMESTAMP, 放在PA_DATA上。KDC收到请求,使用用户hash解密value的值得到时间戳跟当前时间做比对,如果在合理的范围(正常五分钟),就认证通过。

事实上也可以使用证书作为认证,这也是这次spectorops关于ADCS研究的最大亮点,后面漏洞紧紧围绕这点。

RFC4556引入了对 Kerberos 预身份验证的公钥加密支持。这个RFC 的title是Public Key Cryptography for Initial Authentication in Kerberos,后面我们使用简称PKINIT来介绍使用证书进行kerberos身份认证这种方法。

PKINIT同样也使用时间戳,但不是使用用户密码派生密钥加密消息,而是使用属于证书的私钥对消息进行签名。

我们可以使用rubeus 进行验证。

我们首先为用户Administrator注册一个证书,使用certmgr.msc进行注册

然后导出来,记得跟私钥一起导出来

接下来我们拿着这个证书去请求kerberos认证

Rubeus4.0.exe asktgt /user:Administrator /certificate:administrator.pfx /domain:test16.local /dc:dc-05.test16.local

0x0703 请求NTLM 凭据

在微软的文档https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pkca/4e5fb325-eabc-4fac-a0da-af2b6b4430cb里面有一段话

也就是当使用证书进行kerberos认证的时候,返回的票据的PAC包里面还有NTLM票据。

这个东西Benjamin(mimikatz,kekeo作者)在17年已经研究并进行武器化

详情见https://twitter.com/gentilkiwi/status/826932815518371841

下面我们用一个案例来说明。

当我们控制了一台主机,里面有个用户的证书

我们使用certutil来导出证书(如果导出不了的话,就用mimikatz来导出证书)

然后把pfx文件拷贝到我们自己的计算机,双击导入,输入刚刚我们输的密码。

我们本地的计算机做个代理进内网,并且把dns也代理进去(dns设置为内网的域控)

使用kekeo获取用户的NTLM

我们再做个测试,把用户的密码改了

这个时候用之前获取的证书继续发起请求,还是能获取到NTLM Hash。

 

0x08 引用

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多