hash传递攻击的相关手法、防御措施及其绕过
“Pass the Hash” 攻击是一种通过窃取用户密码的哈希值,而无需获取实际密码的攻击手法。在 Windows 系统中,用户密码通常以哈希值的形式存储,而攻击者可以直接传递这个哈希值来完成认证,绕过传统的口令验证。这种攻击的产生与弱口令、哈希值存储、以及对密码的哈希而非明文存储等因素有关。攻击者利用这一漏洞绕过身份验证,获取对系统和网络资源的访问权限,可能导致敏感信息泄漏和系统被滥用。通过PTH,可以扩大攻击范围,达到横向移动的目的。
哈希传递攻击的前提是域内主机的域管理员密码都为相同的密码,相同的密码对应的哈希值也相同。所以,如果我们拿到另一台主机的本地管理员权限,即使不知道域管理员的密码,也可以用哈希传递来获得管理员权限。
前言
在开始分析PTH之前,我们先来思考几个问题:
为什么使用PTH,发明这个攻击手法的原因和目的是什么呢?
①首先我们知道,如果获取了明文密码,那我们就可以直接用明文密码进行登录。但是从 Windows Server 2012 r2开始, lsass.exe进程中抓不到明文密码了。微软为了防止用户密码在内存中以明文形式泄露,发布了补丁KB2871997,关闭了Wdigest功能。使攻击者无法从内存中获取明文密码。Windows Server2012以下版本,如果安装了KB2871997补丁,攻击者同样无法获取明文密码。而且安装了 KB2871997补丁,不仅无法dump出明文密码,并且一般情况下无法使用哈希传递攻击。仅可以使用SID=500的用户进行哈希传递攻击,而SID=500的用户默认为administrator。
②可能还会有人有疑问,我们可以使用hash爆破啊。大家都知道windows的认证hash从开始到现在大概分为LM hash和NTLM hash两种。前期的LM hash位数较少,加密方法较简单,我们可以使用爆破试一试。但是从windows 7开始 LM hash就已经被禁用了,普遍使用的是NTLM hash,这种hash使用单向MD4函数穷举,加密方法较复杂,爆破难度大。在Windows Server 2012 或者安装了KB2871997补丁之后,就真的不能捕获到明文密码了么?
答案是否定的。那我们该怎么在有这个补丁的情况下获得明文密码呢呢?
更新KB2871997补丁后,Wdigest Auth强制系统的内存不再保存明文口令.
但是在实际情况中一些系统服务(例如IIS的SSO身份验证、远程桌面服务)在运行的过程中需要Wdigest Auth开启,所以补丁虽然强制关闭Wdigest Auth,但是我们可以选择是否禁用Wdigest Auth。
我们可以先来了解一下,什么是Wdigest Auth
Wdigest Auth(Windows Digest Authentication)是 Windows 操作系统中的一种身份验证协议,用于通过摘要(digest)方式进行用户身份验证。该协议的主要目的是增强传统的 NTLM(NT LAN Manager)身份验证的安全性。
在 Wdigest Auth 中,用户的密码不会以明文形式在网络上传输。相反,系统会使用一种摘要算法,将密码的摘要信息传递给服务器。这样,即使在网络上截获了数据包,攻击者也难以还原出用户的明文密码。
这里Wdigest Auth 的开启与关闭涉及 Windows 操作系统中 LSA(Local Security Authority,本地安全性机构)的策略,其中的一个重要参数是 UseLogonCredential
。
- 如果
UseLogonCredential
为 1,表示开启 Wdigest Auth,此时系统会在内存中保存用户的明文口令。 - 如果
UseLogonCredential
为 0,表示关闭 Wdigest Auth,此时系统在内存中不再保存用户的明文口令。
这里一下说用户的密码不会以明文形式在网络上传输,一下又说此时系统会在内存中保存用户的明文口令,是否冲突呢?其实不然,这两句话在描述 Wdigest Auth 的不同方面。
“在 Wdigest Auth 中,用户的密码不以明文形式在网络上传输。”
这句话强调了 Wdigest Auth 的网络传输安全性。即使攻击者截获了网络数据包,由于使用了摘要算法,攻击者很难还原出用户的明文密码。
“如果 UseLogonCredential
为 1,表示开启 Wdigest Auth,此时系统会在内存中保存用户的明文口令。”
这句话描述了 Wdigest Auth 在系统内存中的行为。如果 UseLogonCredential
为 1,系统将保存用户的明文口令以支持 Wdigest Auth 过程。这是为了在用户的会话期间(例如,单一登录或其他服务需要明文密码的情况)提供更高的效率和功能。
Wdigest Auth 通过在网络上传输时使用摘要算法,保护了密码的传输安全性,而在内存中保存用户的明文口令则是为了提供在用户会话期间的便利性和功能。
那这里我们就来实验一下吧,我用域内的windows server 2016作为实验机器
我们先看一下UseLogonCredential
这个参数有没有打开
1 | 将下列注册表路径的 |
我们来修改下windows server 2016的注册表,我手动找没有找到UseLogonCredential
这个参数,但是输入下面这个命令可以执行成功,修改之后,将用户administrator注销,然后重新登录
1 | reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f |
然后再输入,记得要把病毒防护和防火墙关掉
1 | procdump64.exe -accepteula -ma lsass.exe lsass.dmp |
然后在放在同一目录下执行,记得都要把防火墙和病毒防护全部关掉!!!然后记住要管理员身份运行
1 | sekurlsa::minidump lsass.dmp |
在没有开启前,我们抓到的密码是hash值
然后在修改之后重新登录
得到明文密码
- PTH在什么情况下可以用?
在上面一个问题里面,我们提到了2014年微软发布了补丁KB2871997,那么这个补丁真的可以防御PTH么?
更新KB2871997后,发现无法使用常规的哈希传递方法进行横向移动,但Administrator账号(SID为500),使用该账号的散列值依然可以进行哈希传递。
在工作组环境中:
- Windows Vista 之前的机器,可以使用本地管理员组内的用户进行攻击。
- Windows Vista 之后的机器,只能是sid=500的用户的哈希值才能进行哈希传递攻击
在域环境中: - 域管理员组内用户的哈希值能进行哈希传递攻击,攻击成功后,可以访问域内任何一台机器。但是在打了补丁之后,也只有sid=500的用户才能进行PTH
那怎么判断当前机器是在域内还是在工作组内呢
①查看此电脑的属性选择高级系统设置查看
如果是域则代表是域环境,如果是工作组则代表是工作组内
②输入systeminfo
显示出计算机的操作系统的详细配置信息
然后看域这栏是否为空,如果不为空,则在域内
- 如果我们拿下的这台机器上没有域管的hash怎么办呢?
一般得域管登录过我们的机器,我们才能在机器上抓到其hash。但实际上一个域内可能有几百几千台机器,不一定我们拿下的那台机器就有域管的hash。那这时候我们应该怎么办呢?我们一般会先在拿下的这台主机上提权到sid=500的管理员用户,然后用域内用户的hash横向移动到其他机器,直到获取到域管的hash为止。但是一般都不会那么容易获取到,都会有防御措施。这时候我们就会用其他横向移动的方法,或者去打一些其他的服务。
复现环境
域控:windows server 2016
域内主机:windows 10
攻击机:kali
在域内进行PTH的前提是:
1.获得一台域主机的权限
2.Dump内存获得其hash
3.通过PTH尝试登录其他主机
4.直到获得域管理员账户hash,登录域控,最终成功控制整个域
PTH攻击实例
这里假设我们已经拿下了windows 10,我们就在这台机器上进行PTH攻击
因为win10和我的攻击机不在同一个局域网内,所以我这里先代理一下,使得攻击机和win10之间可以相互通信
这里记得要把主机和win10的防火墙都关了
①猕猴桃
这里注意ntlm hash
dump出来可能有好几个hash,就是登陆过这个计算机的都会有,这里如果实在不知道哪个是域控的,可以都试试,这里记得用管理员权限执行猕猴桃
1 | privilege::debug |
成功之后会弹出一个弹窗,在弹窗输入命令执行即可
②impacket
一般都是在本地打
wmiexec
(比psexec隐蔽,使用wmiexec进行横向移动的时候,Windows操作系统默认不会将WMI的操作记录在日志中)
1 | wmiexec.py -hashes ":<hash>" <user>@<ip> |
注意要把防火墙关了
atexec
1 | atexec.py -hashes ":<hash>" <user>@<ip> "command" |
psexec
- psexec远程运行需要远程计算机启用文件和打印共享且默认的Admin$共享映射到C:windows目录。
- psexec建立连接之后目标机器上会被安装一个
PSEXESVC
服务。但是psexec安全退出之后这个服务会自动删除(在命令行下使用exit命令退出)
exe版的似乎没有-hashes
这个参数,所以只能用明文密码
1 | PsExec64.exe \\192.168.0.1 -u administrator -i -p Admin111 cmd |
还有py版的
1 | psexec.py -hashes ":<hash>" <user>@<ip> |
③利用msf的psexec模块
1 | use exploit/windows/smb/psexec_psh |
(这个没有实验过,在set smbpass password
,这个命令里的password
似乎可以用hash值代替,还有CS也可以PTH)
④利用wmiexec.exe
下载地址:https://github.com/maaaaz/impacket-examples-windows
1 | wmiexec.exe -hashes ":cb0a99e1c922b84b1b632df155665470" WANYUE/Administrator@192.168.0.1 "dir" |
PTH攻击的防御
目前还没有完全可以防御PTH的手法,要使得不被PTH攻击的第一步就是避免攻击者获得自身主机hash值。
打补丁其实是防御的一个好方法,虽然并不能完全防御,但是一般权限的用户就不能PTH了。记住就算打了补丁也要记得把sid=500
的管理员账户禁用了。
KB2871997补丁的特点
参考链接:
https://blog.csdn.net/ping_pig/article/details/121228950、
https://www.freebuf.com/column/220740.html
注意:安装了KB2871997补丁或者系统版本大于windows server 2012时,系统的内存不保存明文的密码。
① 支持受保护用户组
Protected Users组是一个新的域全局安全组,所属用户会被强制要求使用Kerberos认证,可以避免PTH攻击。注意:真正影响PTH的因素是UAC。
② 远程桌面客户端支持 Restricted Admin RDP 模式
受限管理员模式能够避免发送明文,服务端也不会缓存用户凭据,但是这种方式也可以增加了新的攻击路径,即可以以pth的方式向远处桌面服务器发起认证。
③ LSA 凭据清理和其他更改
从 LSASS 中删除明文凭据
用户注销后,凭据将始终从内存中清除
具体更改为:
1、 支持“ProtectedUsers”组;
2、 Restricted Admin RDP模式的远程桌面客户端支持;
3、 注销后删除LSASS中的凭据;
4、 添加两个新的SID;
5、 LSASS中只允许wdigest存储明文密码。
那在打了补丁之后对PTH的防御方法就有:
1、 将FilterAdministratorToken的值设置为1,限制本地administrator账户的远程;
2、 可以使用脚本或者人工定时查看LocalAccountTokenFilterPolicy是否曾经被攻击者修改过;
3、 在组策略中的“拒绝从网络访问这台计算机”将需要限制的组、用户加入到列表中。