刨根问底:Hash传递攻击原理探究

2015-10-01 596330人围观 ,发现 7 个不明物体 系统安全终端安全

原创作者:walkerfuz

0×00 前言

甲:你知道Hash传递攻击吗,就是可以直接用Hash登录远程主机而不用明文密码。

乙:貌似这是个漏洞,Win7之后应该已经被修复了。

甲:我刚才用Metasploit试了试,最新的Win7系统也支持。

乙:不可能吧,既然Hash都不用破解就能登录远程主机,那微软费那么大劲将明文密码存储为NTLM Hash的机制不就是多此一举吗?

甲:~!@#$%……

你说的如此有理,我竟然无言以对。

自己就是上述路人甲,这就是不懂原理的悲哀,看似什么都会,其实什么都不会。为以身正学,特梳理薄弱知识点,供勉之。

0×01 Pass The Hash介绍

关于Hash传递攻击,维基百科有言:

Pass the hash is a hacking technique that allows an attacker to authenticate to a remote server/service by using the underlying NTLM and/or LanMan hash of a user's password, instead of requiring the associated plaintext password as is normally the case.

意为攻击者可以直接通过LM Hash和NTLM Hash访问远程主机或服务,而不用提供明文密码。

国内涉及Hash传递攻击的讨论主要包括:

1. 利用Metasploit中的Psexec模块访问远程主机共享资源

2. 利用Win8.1/2012受限管理员模式特性访问远程主机

Metasploit的Psexec模块在我的机器上第一次能成功,第二次就出现错误:

[-] Exploit failed: ActiveRecord::RecordInvalid Validation failed: Data has already been taken

结束掉Postgres.exe进程后,可登录成功,但无法上传载荷,初步分析为Metasploit数据库的问题,故采用Impacket开源工具包中的Psexec.py进行实验。

攻击环境:Win7x64 Workgroup Python2.7 + Psexec.py

目标环境:最新Win7x86 Workgroup

1. 安装impacket包(依赖包:Pyasn1-0.1.8和pycrypto2.6.1)

2. 将Psexec.py文件拷贝至任意文件夹并运行:

C:\ >python psexec.py test@11.11.11.25 -hashes A********BCDE:84********83 -c calc.exe
Impacket v0.9.14-dev - Copyright 2002-2015 Core Security Technologies
[*] Trying protocol 445/SMB...
[*] Requesting shares on 11.11.11.25.....
[*] Uploading file oOhZZRyI.exe
[*] Opening SVCManager on 11.11.11.25.....
[*] Creating service Ouqw on 11.11.11.25.....
[*] Starting service Ouqw.....
[*] Uploading file calc.exe
[!] Press help for extra shell commands

目标机器上:

可以发现calc进程已经执行。(这里涉及到Win7后的会话隔离特性:calc进程运行在会话0,而登陆的test账户运行在会话1,所以无法显示其计算器的界面)

期间用Wireshark抓包可得:

而如果用net use命令直接登录远程共享:

对比可以发现net use中smb协议建立在NetBIOS协议之上,而psexec.py中smb协议建立在TCP协议之上。

如此看来,难不成SMB协议直接用Hash与远程主机进行协商验证?为何net use使用的是NetBIOS协议?带着这些问题,让我们一起走进SMB协议的世界。

0×02 SMB协议简介

SMB协议是一种通过网络在File sharing、printer sharing、named pipes、mail slots以及RPC之间操作数据的协议,CIFS为其跨平台公开版本,是客户系统在网络上向服务器请求文件和打印服务的运行机制且:

The SMB 2 Protocol uses either TCP or NetBIOS over TCP as underlying transports.

目前SMB协议版本发展:

There are several different versions of SMB used by Windows operating systems:
CIFS – The ancient version of SMB that was part of Microsoft Windows NT 4.0 in 1996. SMB1 supersedes this version.
SMB 1.0 (or SMB1) – The version used in Windows 2000, Windows XP, Windows Server 2003 and Windows Server 2003 R2
SMB 2.0 (or SMB2) – The version used in Windows Vista (SP1 or later) and Windows Server 2008
SMB 2.1 (or SMB2.1) – The version used in Windows 7 and Windows Server 2008 R2
SMB 3.0 (or SMB3) – The version used in Windows 8 and Windows Server 2012

值得注意的是:

The SMB 2 Protocol supports Direct TCP, NetBIOS over TCP.

SMB协议支持直接运行在TCP上或封装运行在NetBIOS协议上,上述Psexec.py的SMB协议就是直接运行在TCP上,而net use命令的抓包就是运行在NetBIOS协议,有兴趣的可以抓包看一下每个SMB数据包中都包含NetBIOS Session Service片段。

以SMB2协议为例,其分为会话协商、用户或共享认证、资源访问等过程:

如果起初客户端需要与服务器协商SMB协议的版本,需要进行二次通信:

大致流程解释:

1.客户端发送一个SMB Negotiate Request请求数据包,与服务端协商SMB协议的版本,服务端返回SMB Negotiate Response回应
2.经过协商之后,客户端通过SMB Session Setup Request数据包向服务端发起一个用户或共享认证,由服务器返回SMB Session Setup Response判断允许或拒绝客户端的连接
3.完成协商和认证后,客户端会得到一个SessionId,客户端使用该Id发送SMB Tree Connect Request数据包将其想访问的特定网络资源告诉服务端,默认会先请求\IPC$

备注:关于SMB协议中共享认证和用户认证两种方式的解释

在SMB协议协议中有两种安全模式:

1.共享级的安全模式:这种安全模式需要一个密码访问网络上共享资源,用户通过正确的密码来访问网络资源
2.用户级的安全模式:这是共享级的增强版,必须使用一对登录名/密码来访问共享资源

目前现在默认使用的是用户级的安全模式。

协议中涉及认证的部分就是SMB_Session_Setup Request和Response阶段:

For authentication, the SMB 2 Protocol relies on Simple and Protected GSS-API Negotiation, which in turn may rely on the Kerberos Protocol Extensions or the NT LAN Manager (NTLM) Authentication Protocol.

也就是说,SMB协议通过Kerberos协议或NTLM协议来完成认证:

 

这里重点介绍一下NTLM协议,建议Kerberos协议阅读《深入解读MS14-068漏洞:微软精心策划的后门?》这篇软文。 

0×03 NTLM协议与Hash的关系

早期SMB协议在网络上传输明文口令。后来出现 LAN Manager Challenge/Response 验证机制,它是如此简单以至很容易就被破解,后来微软提出了WindowsNT挑战/响应验证机制,称之为NTLM。

现在已经有了更新的NTLMv2以及Kerberos验证体系。

何为Challenge-Response挑战/响应验证机制呢?我们还是从最简单的密码认证设计思路开始:

1.Client需要向Server证明自己的身份
2.Client和Server都共享一个秘密Secret,而这个Secret可以证明Client 的身份
3.所以Client必须向Server提供这个秘密,但显而易见,Client不能向其它人泄露这个秘密,否则别人就可以伪造它

那么Client和Server怎么进行认证呢?既然Client不能泄露这个秘密,那它们就想了一个办法:

Server先给Client一个Challenge(一个随机数),Client用这个Challenge作为Key加密Secret,然后发送给Server,Server使用Challenge解密得到Secret,就可以验证Client的身份是否合法,如下图:

这里必须保证Challenge的不可预测性和唯一性,才能阻止对该协议的攻击。

后来当人们提出Windows密码使用Hash保存后,就演变出NTLM v1: 

可以看到在SMB Negotiate Protocol Response中,不仅协商了SMB版本,还会将8字节的Challenge返回至Client,Client使用这个Challenge将LM_Hash和NT_Hash加密后发送给Server进行验证。

经过实践得知,如果上述数据包被恶意第三方截获得到Challenge和加密后的Hash值,那么LM_Hash和NT_Hash也容易泄露,所以微软改进后加入了TimeStamp时间戳来防止这种攻击,也就是NTLM v2:

可以看出在Session Setup Request阶段加密时使用了Timestamp时间戳标志。

上述讲的是NTLM协议在Workgroup环境下的认证过程,在域环境下的认证,则需要Client向Domain Controller域控制器请求Challenge,然后使用该Challenge向Server发送加密后的Hash,Server会将收到的加密后的Hash转交给DC域控制器来验证Client身份的真假。

到这里就明白了,NTLM协议果然使用了LM Hash和NT Hash进行身份认证。

BlackHat2010大会介绍了Windows下预测Challenge的攻击方法,有兴趣可以Google之;NTLM的缺陷在于虽然其可以向Server证明Client的真假,但却无法向Client证明Server的真假,所以才出现了后来的Kerberos协议,不再详述。

那Kerberos协议又如何呢?熟悉Kerberos协议的童鞋也知道Kerberos协议也是通过Hash进行身份验证的,不过Kerberos协议默认使用Client本机的缓存证书与Server进行验证,Psexec.py中-k参数也有解释:

Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line

使用Psexec做实验:

C:\>python psexec.py abc.com/administrator@abc.com -k -hashes 5*****E:3***592
Impacket v0.9.14-dev - Copyright 2002-2015 Core Security Technologies
[*] Trying protocol 445/SMB...
[-] Kerberos SessionError: KDC_ERR_PREAUTH_FAILED(Pre-authentication information was invalid)

可以发现默认不成功的,此时只要删除Client机器中的缓存证书即可:

C:\>klist
Current LogonId is 0:0x4a660
Cached Tickets: (4)
#0>     Client: domainuser @ ABC.COM
        Server: krbtgt/ABC.COM @ ABC.COM
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0x40e00000 -> forwardable renewable initial pre_authent
        Start Time: 9/28/2015 15:55:23 (local)
        End Time:   9/29/2015 1:55:23 (local)
        Renew Time: 10/5/2015 15:55:23 (local)
        Session Key Type: RSADSI RC4-HMAC(NT)

删除:

C:\>klist purge
Current LogonId is 0:0x4a660
        Deleting all tickets:
        Ticket(s) purged!

之后再使用Psexec:

C:\>python psexec.py abc.com/administrator@swg.abc.com -k -hashes E*****DA:E*****B6
Impacket v0.9.14-dev - Copyright 2002-2015 Core Security Technologies
 [*] Trying protocol 445/SMB...
 [*] Requesting shares on swg.abc.com.....
[*] Found writable share C$
[*] Uploading file KOFAMWng.exe
[*] Opening SVCManager on swg.abc.com.....
[*] Creating service CpKh on swg.abc.com.....
[*] Starting service CpKh.....
[!] Press help for extra shell commands

可以发现Kerberos协议也可以完美实现Hash传递攻击。

补充:

虽然Kerberos目前已成为域环境下的默认安全认证协议,但当客户端以IP地址访问服务端时,此时仍旧会使用NTLM协议进行身份认证,因为此时没有提供Server的SPN(service principal name)。在域环境下这两种运用方式都可以完成Hash传递攻击:

C:\>python psexec.py abc.com/administrator@swg.abc.com -k -hashes E****DA:E****B6 -c calc.exe [Kerberos]
C:\>python psexec.py administrator@192.168.1.2 -hashes E*****DA:E*****B6 -c calc.exe  [NTLM]

希望您能理解其中所用协议的区别。

0×04 总结

经过上面对NTLM和Kerberos协议的理解,也就证明了一个非常严肃的事实:

微软协议本身就支持Hash传递攻击,并不是什么已经修补的“漏洞”。

再次回到文章开始时的疑问:

既然Hash都不用破解就能登录远程主机,那微软费那么大劲将明文密码存储为NTLM Hash的机制不就是多此一举吗?

这个该如何解释呢?Hash机制是目前比较安全的一种加密,不可能让微软放弃Hash吧,所以企业解决这个疑问的重点不在于Hash的使用,而在于使用之前Hash的获取上:

The best defense against PTH attacks is to prevent the attackers from getting superadmin access in the first place.

也有人提出了更安全的Hash机制:

Vista, Windows 7, and Windows Server 2008 (and later versions), for example, use Kerberos with an AES hash instead of the traditional NT hash. While PTH attackers could ultimately use the AES hashes instead, they don't look for them right now, and none of the publicly available PTH tools work with them.

总结到此,若有纰漏,敬请斧正。

*原创作者:walkerfuz,本文属FreeBuf黑客与极客(FreeBuf.COM)原创文章奖励计划,未经允许禁止转载

这些评论亮了

  • wordexp (1级) 回复
    看了下楼主的文章,你那个LM和NTLM还有NET LM和NET NETLM根本就没说对吧。
    NTLM 其实是取密码的UNICODE,然后算MD4。
    而LM是如果密码不超过14个字符就小写转大写,然后分成两个7字节一组,不足14的补0x00
    然后用str_to_key把两个7字节扩成8字节,然后做为标准DES的密钥加密KGS!@#$%
    而NET NTLM的生成应该是下面这样的吧:
    明文123456,转成UNICODE
    算MD4 32ed87bdb5fdc5e9cba88547376818d4 (这就是NTLM HASH)
    补足21字节 32ed87bdb5fdc5e9cba88547376818d40000000000
    分成如下三组,7字节一组,然后用str_to_key函数,把三组都扩成8字节
    32ed87bdb5fdc5 扩成 327660F6DAAEF68A
    e9cba885473768 扩成 E8E4EA105438DCD0
    18d40000000000 扩成 186A000000000000
    然后把三组数据分别当成DES的KEY加密挑战,E6010BA38D389439为服务器发给客户端的挑战
    327660F6DAAEF68A 加密E6010BA38D389439 得 19C4336ACBBB62DD
    E8E4EA105438DCD0 加密E6010BA38D389439 得 37802C62AD5C6903
    186A000000000000 加密E6010BA38D389439 得 4B68998B807F8A9D
    然后加密数据拼接成
    19C4336ACBBB62DD37802C62AD5C69034B68998B807F8A9D (这就是NET NTLM)
    最后在HASHCAT工具中将下面一行存在ps.txt中
    u4-netntlm::Aaa::19C4336ACBBB62DD37802C62AD5C69034B68998B807F8A9D:E6010BA38D389439
    hashcat的参数弄成hashcat.exe -m 5500 -o 2.txt ps.txt t.txt
    5500表示破解NetNTLMv1-VANILLA / NetNTLMv1-ESS
    -o破解成功保存的结果
    ps.txt存放hash
    t.txt表示字典表
    )20( 亮了
发表评论

已有 7 条评论

取消
Loading...
walkerfuz

我是一个小小的走神™,像风一样分析漏洞、挖漏洞的白帽子。

8 文章数 25 评论数

特别推荐

推荐关注

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php