独角兽暑期训练营系列 | Windows Hash传递攻击的本质、缓解及绕过

Author: 独角兽暑期训练营第二季-程赛,指导老师-王永涛 2018/09/04

独角兽暑期训练营

360无线电安全研究院每年暑假都会面向在校学生举办一次暑期训练营,申请者投递简历并提交自己想做的课题介绍后,若入选,会在360技术专家的指导下完成课题。

本系列文章会发布今年5位学员在训练营中的成果。文章相关代码后续会在训练营github代码仓库发布 。

 

LM Hash、NTLM Hash、Net-NTLM Hash的区别与联系

LM Hash

LM Hash是一种较古老的Hash,在LAN Manager协议中使用,非常容易通过暴力破解获取明文凭据。Vista以前的Windows OS使用它,Vista之后的版本默认禁用了LM协议,但某些情况下还是可以使用。

NTLM Hash

Vista以上现代操作系统使用的Hash。通常意义上的NTLM Hash指存储在SAM数据库及NTDS数据库中对密码进行摘要计算后的结果,这类Hash可以直接用于PtH,并且通常存在于lsass进程中,便于SSP使用

Net-NTLM Hash

Net-NTLM Hash用于网络身份认证(例如ntlm认证中),目前分为两个版本:

  • Net-NTLMv1
  • Net-NTLMv2

通常我们使用Responder等工具获取到的就是NetNTLM,这类hash并不能直接用来PtH,但可以通过暴力破解来获取明文密码

联系

Net-NTLM出现在NTLM认证过程中,其计算过程依赖NTLM Hash

参考资料: https://medium.com/@petergombos/lm-ntlm-net-ntlmv2-oh-my-a9b235c58ed4

 

NTLM认证

本文提到的NTLM认证特指Microsoft NTLM Protocol。

工作组环境

NTLM认证是一种在网络上进行认证的安全协议,其主要过程粗略地分为三步:

  1. 客户端发起认证请求
  2. 服务端收到认证请求,向客户端发送随机数(chanlleng/挑战)
  3. 客户端使用NTLM Hash打乱该随机数,生成Net-NTLM Hash,发送回服务端

域环境

上面的过程发生在工作组环境中,在域环境中使用NTLM Pass-Through认证,核心过程与工作组没有太大区别:

标题: fig:

主要区别在于Server会将认证信息使用netlogon协议发送给域控制器,由域控制器完成检验并返回认证结果

参考资料: http://davenport.sourceforge.net/ntlm.html

 

网络登录与非网络登录

网络登陆

在网络登录过程中不使用凭证输入对话框来收集数据,而会使用到预先生成的凭据。

非网络登陆

分为网络明文登陆和交互式登陆等。这些登录类型在认证期间将用户明文密码发送到服务器。 服务器可以在LSASS中缓存这个密码或其处理后的值,并使用它来验证其他资源。

网络登录与NTLM认证

NTLM认证出现在网络登录中,而远程服务器不缓存用户凭据,这也与ntlm认证的特性相吻合。 Double-Hop的问题也与网络/非网络登录的性质有关。

 

PtH攻击原理

注意:本文所指均为狭义上的Pass-the-Hash,即一种在NTLM认证中使用NTLM Hash进行认证的手段

标题: fig:

在上面的三步过程中,我们发现并没有使用到用户提供的明文密码,而是使用NTLM Hash来计算NetNTLM Hash。Hash传递攻击就发生在NTLM认证的第三步,我们能使用获取到的NTLM Hash来完成一次完整的认证。

PtH操作演示

靶机ip:

标题: fig:

攻击机ip:

标题: fig:

以mimikatz为例,在攻击机上以管理员身份运行mimikatz:

标题: fig:

在攻击之前我们需要知道目标账户名以及hash值,这里我们假设获取到了ntlm hash:

标题: fig:

我们使用mimikatz来pth:

标题: fig:

这里需要domain,user,ntlm以及打开的程序四个参数。默认情况下打开cmd。 我们知道,pth只是一种无明文认证的手段,我们还需要针对具体的服务进行攻击,这里以smb服务为例。通常我们访问一个unc路径时,不考虑double-hop的情况下,如果没有指定windows会自动用当前用户的凭据进行ntlm认证,例如命令dir \\Target\aaa。由于windows某些ssp会在lsass中缓存hash值,并使用它们来ntlm认证,那么理论上我们如果在lsass中添加包含目标账户的hash的合法数据结构,就可以在使用类似dir这些命令时用目标账户进行认证,这也是mimikatz中pth功能的原理。 上一步里面我们已经用mimikatz修改了内存中的hash值,那么我们就能利用弹出的cmd来测试一下是否能网络登录目标系统,访问c$共享。 这里使用的exist用户是非内置管理员用户,尽管c$共享允许管理员组成员访问,但由于uac对网络登录的限制,导致直接访问会被Access Died:

标题: fig:

出于演示的需要,我们把靶机上的UAC级别设置为从不通知并重启,再次pth:

标题: fig:

能成功访问c$共享。

 

缓解手段及其局限性或可能的绕过方式

试图缓解PtH的危害可以从两个方面入手(当然不仅仅是这两方面):

  1. 禁止NTLM认证
  2. 防止NTLM Hash被获取到

第一种方式当然是一劳永逸地阻止了PtH,但是NTLM认证已经被微软使用了很长时间,完全禁止可能会破坏已部署的一些环境,在实际应用中阻力较大。 由于NTLM认证的天然缺陷,微软似乎很难改变其行为,因此更多地把防御放在了阻止Hash被获取到这种思路。下面我们来介绍微软发布的一些补丁以及它们可能的绕过方式。

kb2871997

kb2871997在缓解PtH上做出了不少努力,其为windows增加的特性值得深入研究。它在win server 2012 R2及以上版本已默认集成。 根据微软公告,安装kb2871997后会有这么些行为:

删除lsass的明文凭证

我们前面提到过,lsass进程会缓存用户凭据,有明文有Hash,这取决于使用的ssp类型以及补丁情况。

标题: fig:

上图中msv、tspkg、wdigest、kerberos这几个ssp都获取到了凭据,它们分别用于Terminal Server认证(RDSH),ntlm认证,摘要认证以及kerberos认证。我们能看到只有msv没有明文密码。从前文中对ntlm认证过程的描述,我们可以发现除了第一步客户端要求用户输入明文密码,之后的认证过程再也没有出现过明文密码。这也就是说,ssp只需要计算ntlm hash并放在内存中就行了。 我们看到摘要认证wdigest在windows 2008 中缓存了明文密码。摘要认证类似于ntlm认证,也使用了挑战-响应机制,但它与ntlm认证较大的区别在于客户端计算响应时,需要使用到明文密码,为了实现SSO,需要将明文密码放在内存中方便进行计算,因此客户端一方的ssp理论上必须在内存中缓存明文密码,这也是为什么我们能抓到明文密码的原因;与之相比,NTLM SSP使用的单向函数如NTOWFv2只需要计算一次并放置在内存中,之后计算响应只需要这个hash值即可。

kb2871997会删除除了wdigest ssp以外其他ssp的明文凭据,但对于wdigest ssp只能选择禁用。用户可以选择将HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential更改为0来禁用。

标题: fig:

安装kb2871997之后我们使用mimikatz抓取内存中的密码:

标题: fig:

wdigest ssp默认仍然在内存中存储明文密码,更改注册表后注销,重新登录,再次抓取:

标题: fig:

wdigest已经抓不到明文密码以及密码hash。

局限性

这仅仅是增大了从内存中获取ntlm hash的难度,但并不能阻止从注册表等其他地方获取。

能够禁止用户网络登录

下图中,工作组环境可以在本地安全策略->用户权限分配->拒绝从网络访问这台计算机配置是否允许用户或用户组网络登录:

标题: fig:

理论上UAC无法限制RID为500的用户网络登录,但打补丁并配置好禁止administrator(RID==500)网络登录,测试结果如下:

标题: fig:

局限性

处理方式太过粗暴,可能会影响用户正常需求。

添加“受限管理员模式”

受限管理员模式能阻止主机缓存内存中远程验证用户的凭据。  我们来做两个测试

  • 测试一: RDP客户端使用微软自家的mstsc,服务端未打kb2871997,不加任何参数启动:

标题: fig:

  • 启动连接,客户端要求我们输入用户名和密码:

标题: fig:

  • 登录成功后,使用mimikatz获取内存中的密码:

标题: fig:

  • 我们能够获取到明文密码,ntlmssp的NTLM Hash也能获取到,这里就不再截图了。

测试二:客户端使用mstsc /restrictedadmin,也即受限管理员模式启动,服务端支持受限管理员模式:

标题: fig:

我们发现mstsc提示将使用我们到windows登录凭据进行连接。 如果客户端和服务端有相同用户名和密码的账户,可以直接连接成功,没有弹出要求输入凭据的对话框。连接成功后,使用mimikatz获取内存中的密码:

标题: fig:

我们发现远程桌面会话没有缓存用户凭据,这其实就是受限管理员模式的特性。  下面我们来聊聊为什么会出现这种情况:

  1. 远程桌面默认无约束委派用户凭据,以达到完全在远程服务器上代表用户的目的。当我们连接到远程桌面服务器上,可以使用dir命令连接其他的smb服务器并使用我们的凭据认证,这是因为客户端进行远程桌面连接的时候会发送用户的明文密码,这个密码可以用于计算NTLM Hash并缓存在远程桌面服务器上。
  2. 受限管理员模式下,远程桌面客户端会首先使用客户端机器上已缓存的NTLM Hash进行认证,不需要用户输入用户名和密码,也就不会把明文密码委派到目标;即便缓存的hash认证失败,用户必须输入明文密码,mstsc也不会直接发送明文密码,而是计算出所需的值后再发送。这种模式下,登录到远程桌面服务器上并使用dir命令向其他smb服务器认证时,将使用空用户(用户名\ )登录,几乎都会登陆失败。

从上面两种模式对比可以看出,客户端直接发送明文密码到服务端,可能会被mimikatz从内存中获取到;而受限管理员模式则能避免发送明文,服务端内存中也不会缓存用户凭据。

参考 https://blogs.technet.microsoft.com/kfalde/2013/08/14/restricted-admin-mode-for-rdp-in-windows-8-1-2012-r2/

局限性

“受限管理员模式”的初衷是为了保护远程桌面服务端,即当服务端被攻陷时,使用受限管理员模式可以在一定程度上保护客户端用户的凭据不被mimikatz等工具获取到。因此,这个保护措施并不是直接针对PtH,效果也是有限的。 实际上受限管理员模式本身就会增加新的攻击路径,即可以以PtH的方式向远程桌面服务器发起认证。也就是说,在实际应用中,我们可以利用mimikatz的sekurlsa::pth来启动mstsc,使用受限管理员模式来无明文密码登录,当然也有些其他的RDP客户端可以实现利用密码Hash来认证,例如FreeRDP。

Protected Users

受保护用户是一个新的域全局安全组,对于该组的成员,Windows 8.1设备或Windows Server 2012 R2主机不会缓存受保护用户不支持的凭据。如果这些组的成员登录到运行早于Windows 8.1的Windows版本的设备,则该组的成员没有其他保护。

登录到Windows 8.1设备和Windows Server 2012 R2主机的受保护用户组的成员不能再使用:

  • 默认凭据委派(CredSSP) – 即使启用了“ 允许委派默认凭据”策略,也不会缓存纯文本凭据
  • Windows摘要 – 即使启用明文凭据也不会进行缓存
  • NTLM – NTOWF未缓存
  • Kerberos长期密钥 – Kerberos票证授予票证(TGT)在登录时获取,无法自动重新获取
  • 离线登录 – 未创建缓存的登录验证程序

如果域功能级别是Windows Server 2012 R2,则该组的成员不能再:

  • 使用NTLM身份验证进行身份验证
  • 在Kerberos预身份验证中使用数据加密标准(DES)或RC4密码套件
  • 通过使用无约束或约束委派来委派
  • 更新用户票证(TGT)超过最初的4小时生命周期

标题: fig:

在域账户未加入Protected Users组时,我们使用mimikatz获取内存中的凭据:

标题: fig:

我们可以看到ntlmssp缓存了emanon账户的密码hash。我们将此用户加入Protected Users:

标题: fig:

标题: fig:

注销,重新登录,再次使用mimikatz抓取密码:

标题: fig:

emanon用户的ntlm hash已经无法获取到,但机器账户DM1$以及本地用户的hash仍然能获取到,这也说明Protected Users保护范围是有限的。  网上有些文章提到了Pass-the-Key(Overpass-the-hash),Protected Users对这种攻击方式也有一定缓解功能。PtK是在域中攻击kerberos认证的一种方式,据称可以在NTLM认证被禁止的情况下用来实现类似PtH的功能(毕竟是针对kerberos认证,其实与NTLM认证没什么关系)。关于这种攻击方式可以查看本节的参考,这里不再赘述。我们比较关心使用mimikatz来Pass-the-Key所需要的信息,其中必须有的是请求tgt所需的用户hash,这可以使用mimikatz中的sekurlsa::ekeys来获取:

标题: fig:

经测试,域功能级别为windows server 2012 R2(未测试低等级),将域用户加入Protected Users用户组后无法通过ekeys命令获取Hash。当然,机器账户还是能够获取到。

局限性

Protected Users是一个域安全组,仅能在域中保护用户,并且阻止抓取用户Hash并没有直面PtH这种攻击方式,域用户凭据仍可能通过注册表Cache、钓鱼攻击等方式获取到。

参考资料: https://www.blackhat.com/docs/us-14/materials/us-14-Duckwall-Abusing-Microsoft-Kerberos-Sorry-You-Guys-Don’t-Get-It-wp.pdf

Additional LSA Protection

LSA(包括本地安全机构服务器服务(LSASS)进程)验证用户是否进行本地和远程登录,并实施本地安全策略。Windows 8.1操作系统为LSA提供额外保护,以防止未受保护的进程读取内存和代码注入。启用此功能后无法把debugger attach到进程上。在win8.1及2012 r2以上有效,启用的方法是reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa /v RunAsPPL /t REG_DWORD /d 1 之后重启。 重启之后,使用mimikatz抓取内存中的密码:

标题: fig:

使用lsadump::lsa /inject:

标题: fig:

同样无法获取到密码hash

绕过方式

mimikatz能够通过加载其驱动程序来绕过LSA Protection。在实际使用中需要注意mimikatz同目录下需要有驱动程序mimidrv.sys 命令:

privilege::Debug
!+
!processprotect /process:lsass.exe /remove

测试:

标题: fig:

标题: fig:

参考资料: https://adsecurity.org/?page_id=1821

Microsoft本地管理员密码解决方案(LAPS)

LAPS是用于管理计算机本地用户密码的一个客户端扩展(CSE),在域中依赖比较少,核心在于组策略支持。 LAPS一个重要功能是随机化所有域成员本地管理员密码,密码按照较强的密码策略生成,定期修改。这使得用相同凭据横向渗透变得很困难。

本地管理员密码明文存储在AD中,仅有管理员及获得管理员委派的账户能访问到。

局限性

LAPS和仅仅增大了横向渗透的难度,并且配置上出错也可能导致前功尽弃。LAPS配置上可能出现的一个问题是向非授权用户授予“All Extended Rights”权限,这导致如果我们获取该账户,就能访问AD中的密码。

参考资料:  https://github.com/leoloobeek/LAPSToolkit

Credentials Guard

Credentials Guard是win10中引入的新功能,据称能保护NTLM密码哈希值,Kerberos票证授予票证和应用程序存储的凭据。该进程是唯一能使用明文凭据的进程,它的原理大概是这样: 当NTLM认证过程中需要用到例如ntlm hash这类凭证的时候(第三步),将Credentials Guard视为黑箱,由lsass等进程输入生成NetNTLM所需的信息(第二步收到的challenge等等),由CG处理并输出结果,而CG本身内存禁止读取,使得mimikatz这一类工具无从下手:

标题: fig:

参考资料: https://www.blackhat.com/docs/us-15/materials/us-15-Moore-Defeating%20Pass-the-Hash-Separation-Of-Powers-wp.pdf

绕过方式

对付Credentials Guard有一些曲线救国的方法:

memssp

SSP的二进制形式是DLL,提供用来处理身份认证的接口(SSPI)。如果我们无法从内存中直接获取凭据,那么通过注册一个ssp来处理用户登录时输入的凭据也是一种办法。mimikatz直接在内存中加载自定义的ssp dll,能够在用户登录时获取到明文凭据。  演示: mimikatz 内存注入ssp

标题: fig:

锁屏等待用户再次登录后,查看system32下的文件

标题: fig:

NetNTLM Downgrade Attack

NetNTLM有两个版本——v1和v2。v1相比v2更加脆弱,因此如果我们能将NetNTLMv2降级为v1,破解的效率会更高;如果能降级到NetLM,那么爆破成功率就变得极高。

这篇文章中提到了一种迂回获取凭据的方式,核心思想是修改注册表使Windows允许在网络认证中发送算法较弱的NetHash例如NetNTLMv1,而实际上我们可以直接与NTLM SSP交互而不必产生网络流量,并能获取到NetNTLMv1用于降低破解的难度。

Credentials Guard运行时,我们虽然不能直接从内存获取到NTLM Hash,但利用上面提到的思路获取NetNTLM Hash是有可能的。

Internal-Monologue.ps1使用演示:

标题: fig:

参考资料:  https://blog.nviso.be/2018/01/09/windows-credential-guard-mimikatz/  https://github.com/eladshamir/Internal-Monologue   https://technet.microsoft.com/en-us/library/2006.08.securitywatch.aspx

 

总结

由于NTLM认证本身具有缺陷性,导致攻击者可以在不知道明文密码,只知道密码Hash的情况下完成认证。这个缺陷就目前来看无法修复,微软也只能建议使用更安全的kerberos协议来代替ntlm协议,而其发布的补丁也并没有触及PtH这种攻击思想的本质,仅仅是增大了攻击的难度或者粗暴地禁止NTLM认证,因此依然存在绕过的可能。

 

Thanks

我在学习及研究过程中受到@360无线电安全研究院&天马安全团队及@SycloverSecurity的大力支持与帮助,在此表示衷心的感谢。

(完)