你用密码登录了,但攻击者根本不需要密码
Windows 认证体系中有个一直没被修掉的设计缺陷:NTLM 协议在验证身份时,用的是密码的哈希值而不是密码本身。这意味着一旦攻击者在某台机器上拿到了一个用户的 NTLM hash——不管是通过内存抓取(mimikatz)、注册表导出,还是从 LSASS 进程里直接提取——他就可以拿着这个 hash 去向域内任何接受 NTLM 认证的服务证明"我是这个人"。整个过程不需要破解出原始密码,甚至不需要知道密码是什么。这就是所谓的 Pass-the-Hash 攻击。
听起来有点荒谬:系统明明有密码,为什么验证时不用密码?原因在于 NTLM 的挑战-响应机制。客户端收到服务端发来的随机 challenge 后,用密码的 hash 对 challenge 加密,返回结果给服务端验证。服务端手里存的也是 hash,它拿到 challenge 和响应后自己做一遍同样的运算来比对。密码本身从头到尾没出现过。攻击者拿到 hash 后,完全可以代替客户端完成整个流程。
一个常见的攻击链是这样的:先在一台低权限的工作站上拿到某个普通域用户的 hash,然后用这个 hash 横向移动到一台该用户有本地管理员权限的服务器,再从那台服务器上提取更高权限账户的 hash,一步步攀升直到拿到域控。整个链条里攻击者不需要爆破任何一个密码。
防御的关键在于限制 NTLM 的使用范围和减少 hash 的暴露面。微软从 Windows 10 / Server 2016 开始引入了 Credential Guard,把 LSASS 里的 hash 放到虚拟安全模式(VSM)中隔离运行,普通进程无法直接读取。同时,禁用 NTLM、强制使用 Kerberos,或者至少在域内限制 NTLM 认证的可用范围,都能显著缩小攻击面。不过现实环境里完全禁用 NTLM 很难做到——太多老旧系统和第三方应用还依赖它。
#Security
Windows 认证体系中有个一直没被修掉的设计缺陷:NTLM 协议在验证身份时,用的是密码的哈希值而不是密码本身。这意味着一旦攻击者在某台机器上拿到了一个用户的 NTLM hash——不管是通过内存抓取(mimikatz)、注册表导出,还是从 LSASS 进程里直接提取——他就可以拿着这个 hash 去向域内任何接受 NTLM 认证的服务证明"我是这个人"。整个过程不需要破解出原始密码,甚至不需要知道密码是什么。这就是所谓的 Pass-the-Hash 攻击。
听起来有点荒谬:系统明明有密码,为什么验证时不用密码?原因在于 NTLM 的挑战-响应机制。客户端收到服务端发来的随机 challenge 后,用密码的 hash 对 challenge 加密,返回结果给服务端验证。服务端手里存的也是 hash,它拿到 challenge 和响应后自己做一遍同样的运算来比对。密码本身从头到尾没出现过。攻击者拿到 hash 后,完全可以代替客户端完成整个流程。
一个常见的攻击链是这样的:先在一台低权限的工作站上拿到某个普通域用户的 hash,然后用这个 hash 横向移动到一台该用户有本地管理员权限的服务器,再从那台服务器上提取更高权限账户的 hash,一步步攀升直到拿到域控。整个链条里攻击者不需要爆破任何一个密码。
防御的关键在于限制 NTLM 的使用范围和减少 hash 的暴露面。微软从 Windows 10 / Server 2016 开始引入了 Credential Guard,把 LSASS 里的 hash 放到虚拟安全模式(VSM)中隔离运行,普通进程无法直接读取。同时,禁用 NTLM、强制使用 Kerberos,或者至少在域内限制 NTLM 认证的可用范围,都能显著缩小攻击面。不过现实环境里完全禁用 NTLM 很难做到——太多老旧系统和第三方应用还依赖它。
#Security