(360 A-TEAM 长期招收高级安全研究人员,APT 攻防人员,请联系 wufangdong@360.net)
n1nty@360 A-TEAM
以前看过 MSCACHE 相关的东西,最近因为想到一个可能会有所成果的思路,所以又开始深入了解,遗憾的是最后只搞出来一个很鸡肋的东西,但是本次过程也让我学到一些与加解密有关的基础知识,也不算没有收获。这里写一篇文章分享一下过程中我学到的东西。
MSCACHE 简介
MSCACHE,或者叫 domain cached credentials、DCC、域缓存凭据。
你的办公笔记本加了公司的域,你一直是使用域账号登陆这台机器。你尝试登陆时所输入的账号密码将由域控来进行验证,验证通过后你就能登陆这台笔记本。 但是你是否发现过,当你的笔记本处于断网状态的时候,你依然可以用域账号来登陆这台笔记本。也就是说,当这台机器根本连不上域控的时候,你也可以使用域账号来登陆这台机器,那这个时候,是谁来负责验证你输入的域账号密码是否正确呢? 就是 MSCACHE。
MSCACHE 是缓存在机器本地注册表中的域凭据+域授权信息,后面就直接用 “凭据” 来代表 “凭据信息” + “授权信息”。
MSCACHE 中包含的内容
我们关心的内容主要有以下几项:
域用户的 mscache hash,或者叫 dcc hash,根据操作系统的版本不同,又分为 dcc1 hash 与 dcc2 hash。Vista 之前保存的是 dcc1, 之后保存的是 dcc2。 两种 hash 的生成算法不一样。
这段 mscache hash 主要用于对用户输入的密码进行验证
域用户的授权信息,比如这个域用户是属于哪个域组的
授权信息主要用于在验证通过后来生成 access token。
一些其他的信息,比如 UPN,logon server 之类的
以下的记录全是关于 Vista 后的系统
DCC1 与 DCC2
前面说了,MSCACHE 保存的是 dcc hash,而并不是 NTLM 的 HASH。所以你导出的域缓存的 hash 是不能用于 PTH 的,只能用来破解。
这里简单记录一下两种 Hash 的生成算法:
DCC1 = MD4 (NT HASH + LowerUnicode(username))
DCC2 = PBKDF2(HMAC-SHA1, Iterations, DCC1, LowerUnicode(username))
顺便推荐一个叫做 passlib 的 Python 库,这个库可以生成各种我们可能会在安全行业里面碰见的 Hash 或密文。如果你使用 passlib 生成 nthash,则代码如下:
from passlib.hash import nthash
nthash.hash('1qazVFR$')
'eb3be2c31408717684a0e320fcf9a376'
也可以直接用它来生成 dcc hash。
MSCACHE 工作原理简介
当机器可以连上域控的时候,你用域账号去登陆这台机器,在登陆成功后(域控验证了你的身份后),系统会将你的凭据以及授权信息保存在注册表里面。默认是保存 10 个凭据(可以对这个值进行更改)。当被保存的凭据已经超过 10 个的话,新的凭据会覆盖掉老的凭据。
凭据被缓存在注册表里的这些用户,在机器连不上域控的时候也可以登陆这台机器(只能交互式登陆,比如控制台或远程桌面。远程桌面的时候要注意,不能使用带有 NLA 功能的 RDP 客户端,要用老的比如 XP 上带的 RDP 客户端),但是没有被缓存在注册表里的用户是无法登陆的。
MSCACHE 的保存位置默认只有 SYSTEM 权限可读
HKEY_LOCAL_MACHINE\SECURITY\Cache
上图的 NL$1 至 NL$10 就是 10 个可以保存凭据的注册表值。这些值都是二进制类型的,并且其中部分是加密的。
MSCACHE 解密 - Bootkey, LSA Key, NLKM Key
所以,我们要想解密 MSCACHE,要进行以下步骤:
得到 bootkey
利用 bootkey 解密 LSA Key
利用 LSA Key 解密 NLKM Key
利用 NLKM Key 解密 MSCACHE
数据
位置
算法
Key
MSCACHE
HKLM\SECURITY\Cache
AES-CTS
NLKM Key
NLKM Key
注册表 LSA Secrets 区域
AES
变形后的 LSA Key
LSA Key
HKLM\SECURITY\Policy\PolEKList
AES
变形后的 boot key
bootkey
被拆成了 4 部分,保存在:
HKLM\System\CurrentControlSet\Control\Lsa\JD
HKLM\System\CurrentControlSet\Control\Lsa\Skew1
HKLM\System\CurrentControlSet\Control\Lsa\Data
HKLM\System\CurrentControlSet\Control\Lsa\GBG
我们熟知的 SAM 文件也是被 bootkey 加密的,这就是为什么你在解密 SAM 文件的时候,你还需要一个 SYSTEM 文件(HKLM\System HIVE 的离线文件,bootkey 保存在这个 HIVE 下)
上面这一切步骤都已经有人写好了,比如 mimikatz,比如用 python 实现的 impakcet。
各位如果对 bootkey 以及 lsa secrets 以及它们具体的加密流程有兴趣的话,可以看一下这两篇文章:
http://moyix.blogspot.com/2008/02/decrypting-lsa-secrets.html
http://moyix.blogspot.com/2008/02/syskey-and-sam.html
MSCACHE 结构
Mimikatz 作者分析出了 MSCACHE 的数据结构,MSCACHE 并不是完全加密的。
其中,只有 enc_data 为加密信息,这段加密信息里面保存了用户的 mscache hash,以及用户的域授权信息。 这段数据解密后的数据结构如下:
mshashdata 就是 mscache hash,可以看出来它位于解密后的 enc_data 的前 16 个字节。
需要关注的是,mimikatz 给出的这个结构也并不完整,我在调试的时候,发现 LogonDomainName 后面还有几十上百个字节不知道是做什么的。Twitter 上问 mimiatz 作者,没有得到回复。
相关工具
cachedump,这个应该是我知道的最早的一个能导出 mscache 的工具了
mimikatz lsadump::cache,它带有一个多数人不知道的缓存替换功能
impacket secretsdump.py,值得一提的是我发现 secretsdump.py 里面的解密代码是错的,MSCACHE 的加密算法是 AES-CTS,而它是按 AES-CBC 去解的。所以会导致最后两个 block 的数据解出来是错的,不过它只需要读取解密后最前面的那部分数据,所以最后的数据解密出错并不影响它的功能。
各类后渗透脚本等等
绝大多数都只是导出 MSCACHE,只有 mimikatz 带了一个修改的功能,但是只能修改密码。后面会说到。
想法
MSCACHE 用于在目标机器因各种原因无法联系域控的时候,利用注册表里面缓存的之前成功登陆者的信息来对用户进行身份验证。 这相当于什么,这相当于是除本地 SAM 以及域数据库以外的另一个账户数据库啊!如果我们直接往一台机器的这个 MSCACHE 区域插进去一条缓存信息,那是不是就有了一个一般情况下别人发现不了的后门账号?
当然这里还有一个前提条件是,在目标机器无法联系域控的时候才会使用 MSCACHE 进行验证。 在真实动手实践之前,我感觉这个限制应该有绕过的方法。 比如目标机器在 A 域里,这时我往它的 MSCACHE 里面插入一个根本不存在的 B 域的账号,这时我用 B 域账号去登陆的时候,机器肯定找不到 B 域,我认为这时它应该就会使用 MSCACHE 里的缓存信息来做验证了。
mimikatz lsadump::cache
在有了上述的那个想法后,我开始找资料去实现那个想法。查找资料的过程中发现 mimikatz 有一个很少有人注意到的功能。它可以对 MSCACHE 中的凭据做修改,但是只能修改 hash 部分。
比如我们通过 lsadump::cache 看到当前机器上有一个缓存凭据:
此时利用
lsadump::cache /user:subuser /ntlm:32ed87bdb5fdc5e9cba88547376818d4
就可以将缓存中保存的密码替换为 123456。
(注意缓存中保存的并不是 nt hash,这里 mimikatz 只是接收一个 nt hash 然后再将它转换成 mscache hash 而已)
更改完后,在这台机器不能连上域控的情况下,你就可以用 subuser/123456 来登陆这台机器。
失败的想法
然而经过好几天的测试,发现我想错了。 机器在找不到 B 域的时候,会去联系自己的域控也就是 A 域的域控来做验证,自然验证就会失败了。 除非有两种情况:
像前面所说的,它连 A 域的域控也联系不上了,这时 MSCACHE 就生效了
B 是一个真实存在的域,且与 A 域有信任关系。 这个时候,只要它连不上 B 域的域控,MSCACHE 就可以生效。
无论是哪种情况,在实战中都没什么太大的可能。对于第 1 种情况,要么你做中间人让目标连不上他自己的域控,要么你就只能等他自己因为一些什么事情主动脱离了域控所在的网络(比如移动办公的笔记本被带回家。。)
mscache.py
https://github.com/360-A-Team/mscache
虽然这个研究没有达到我想到的结果,但是我依然写了一个可能基本不会用到的小工具,用于检验这些天的学习成果。
我将 mimikatz 的 lsadump::cache 的改密码的功能移植到了 python 里面,同时对其进行了扩展,比如除了改密码外还可以:
更改域名
更改用户名
给缓存的账号添加权限,比如将不是域管提成域管
等等
我参考了 mimikatz 的源代码,将它实现的 AES-CTS 加解密功能移植到了 Python 里,并基于 Impacket 的 secretsdump.py 写成了这个小工具叫 mscache.py
简单演示一下
reg save hklm\security security
reg save hklm\system system
导出目标机器的注册表然后将 security 与 system 文件拖回本地
python mscache.py --security security --system system可以看到缓存了两个用户的凭据:subuser@sub.ateam.com 与 testmscache@ateam.com
python mscache.py --security security --system system --patch subuser
对名为 subuser 的用户进行 patch
程序输出了一段 reg add 的命令,在目标主机上执行这段命令后,缓存中 subuser 这个用户的用户名将变成 fakeuser,密码变为 n1nty@360 A-TEAM。
同时如果你选择进行 patch 的那个用户不是 domain admins 组的成员的话,工具会把它提升成 domain admins 组的成员。
然后,在目标机器不能连上域控的时候(或者你制造一些什么条件让他连不上域控?),你就可以用如下账号密码进行登陆:
FAKE\fakeuser
n1nty@360 A-TEAM
无论这个用户之前是什么权限,你登陆后将会是管理员。
EvilMade
black hat 上之前出现过一个利用 MSCACHE 以及 Kerberos kpasswd 协议的漏洞,通过物理接触来绕过 Windows 登陆以及突破 Windows 全盘加密技术的方法,叫做 Evil Made,有兴趣的可以看看。
参考资料
http://moyix.blogspot.com/2008/02/decrypting-lsa-secrets.html
https://webstersprodigy.net/2014/02/03/mscash-hash-primer-for-pentesters/
https://security.stackexchange.com/questions/30889/cracking-ms-cache-v2-hashes-using-gpu
http://www.jedge.com/wordpress/windows-password-cache-mscache-mscash-v2/
http://moyix.blogspot.com/2008/02/cached-domain-credentials.html
https://cqureacademy.com/blog/windows-internals/cached-credentials-important-facts
https://serverfault.com/questions/162900/do-domain-service-accounts-benefit-from-cached-credentials
https://technet.microsoft.com/en-us/library/2009.07.windowsconfidential.aspx
https://www.techrepublic.com/blog/diy-it-guy/diy-cache-credentials-on-a-domained-pc/
and many more...
360 A-TEAM 是隶属于 360 企业安全集团旗下的纯技术研究团队。团队主要致力于 Web 渗透,APT 攻防、对抗,前瞻性攻防工具预研。从底层原理、协议层面进行严肃、有深度的技术研究,深入还原攻与防的技术本质。
欢迎有意者加入!