☆ 概述 ☆ 挑战/响应模式 ☆ L0pht文档 ☆ Windows NT身份验证机制的脆弱性 ☆ str_to_key()函数 ☆ 如何从明文口令生成LM Hash ☆ 标准DES加密 ☆ 如何从明文口令生成NTLM Hash ☆ 标准MD4单向哈希 ☆ SMB报文中使用的是DES LM Hash和DES NTLM Hash ☆ 观察一个实例 ☆ negotiate response解码 ☆ session_setup_andx request解码 ☆ 小结 ☆ 参考资源
--------------------------------------------------------------------------
☆ 概述
早期SMB协议在网络上传输明文口令。后来出现"LAN Manager Challenge/Response" 验证机制,简称LM,它是如此简单以至很容易被破解。微软提出了WindowsNT挑战/响 应验证机制,称之为NTLM。现在已经有了更新的NTLMv2以及Kerberos验证体系。
微软承认LM Hash的固有特性极大损害了安全性,但他们认为这是最初设计者IBM之过。
☆ 挑战/响应模式
使用明文口令模式时,网络上传输的就是明文口令本身,这很容易被Sniffer捕获。 挑战/响应模式的企图不泄露明文口令本身就能证明客户机确实拥有正确的口令:
1. 服务器随机产生一个8字节的挑战,送往客户机。
2. 服务器、客户机各自使用源自明文口令的DESKEY分别对8字节挑战进行加密。客户 机将计算结果送往服务器,这就是所谓响应(分成三组,总共24字节)。
response = DES( key derived from plaintext password, challenge )
这里使用的就是标准DES算法。任何知道key的人都可以将reponse解密,从而获取 challenge。
3. 如果响应与服务器的计算结果匹配,服务器认为客户机拥有正确的明文口令。
☆ L0pht文档
1997年7月12日,L0pht的Mudge <mudge@l0pht.com>对外发布了一份关于SMB通信中身 份验证的文档(参考资源[1])。
+----------------------------+ | 14bytes Plaintext Password | +----------------------------+
+--------------------------------------------------------------------------+ | first 7bytes of Plaintext Password | second 7bytes of Plaintext Password | +--------------------------------------------------------------------------+
+-----------------+ | 16bytes LM Hash | +-----------------+
+----------------------------------------------------+ | first 8bytes of LM Hash | second 8bytes of LM Hash | +----------------------------------------------------+
+-------------------------+ | 16bytes NTLM Hash (MD4) | +-------------------------+
+------------------+ | 8bytes Challenge | +------------------+
+------------------+ | 24bytes Response | +------------------+
LM Hash的前8字节源自对明文口令前7字节的运算,LM Hash的后8字节源自对明文口 令后7字节的运算。如果明文口令最多7字节,则第二部分LM Hash总是"AA D3 B4 35 B5 14 04 EE"(以后解释这里)。比如以"WELCOME"做为明文口令,则对应的LM Hash是 "C23413A8A1E7665FAAD3B435B51404EE"。
假设服务器B向客户机A发送了一个8字节挑战"0001020304050607"
Server B -- 8bytes Challenge --> Client A
A现在有LM Hash,C23413A8A1E7665FAAD3B435B51404EE,在其后增加5个0x00变成 "C23413A8A1E7665FAAD3B435B51404EE0000000000",然后划分成三组,每组7字节
+----------------+----------------+----------------+ | C23413A8A1E766 | 5FAAD3B435B514 | 04EE0000000000 | +----------------+----------------+----------------+
每组7字节做为形参传递给str_to_key()函数,最终得到三组DESKEY,每组8字节
+--------------------------------------------------------+ | 8bytes DESKEY1 | 8bytes DESKEY2 | 8bytes DESKEY3 | +------------------+------------------+------------------+ | C21A04748A0E9CCC | 5ED4B47642ACD428 | 0476800000000000 | +--------------------------------------------------------+
分别用三组DESKEY对8字节挑战"0001020304050607"进行标准DES加密后得到
C21A04748A0E9CCC -对0001020304050607进行标准DES加密-> CA1200723C41D577 5ED4B47642ACD428 -对0001020304050607进行标准DES加密-> AB18C764C6DEF34F 0476800000000000 -对0001020304050607进行标准DES加密-> A61BFA0671EA5FC8
最终获得一个24字节响应"CA1200723C41D577AB18C764C6DEF34FA61BFA0671EA5FC8", 送往服务器B。在服务器B上进行同样的计算,并将计算结果与来自A的响应进行比较, 如果匹配则身份验证通过。
考虑明文口令不超过7字节的情况。
首先检查明文口令是否少于8字节。用str_to_key()函数处理"04EE0000000000",得 到8字节的DESKEY,"0476800000000000",用它对挑战"0001020304050607"进行标准 DES加密,如果结果与网络上传输的"A61BFA0671EA5FC8"相符,明文口令很可能少于8 字节,当然不能绝对肯定。
接下来用str_to_key()函数处理"??AAD3B435B514",得到8字节DESKEY,用它对挑战 进行标准DES加密,如果与网络上传输的"AB18C764C6DEF34F"相符,则找到匹配,此 时我们可以绝对肯定明文口令少于8字节。这里"??"由循环产生,穷举256种可能。
由于LM Hash的一些固有特性,穷举运算量已大幅下降。
考虑明文口令为8字节或更多,假设最后的LM Hash如下
+----------------+----------------+----------------+ | C23413A8A1E766 | AC435F2DD90417 | CCD60000000000 | +----------------+----------------+----------------+
首先检查明文口令是否少于8字节。用str_to_key()函数处理"04EE0000000000",得 到8字节的DESKEY,"0476800000000000",用它对挑战进行标准DES加密,如果结果与 网络上传输的内容不相符,明文口令必然大于等于8字节。
接下来用str_to_key()函数处理"????0000000000",得到8字节DESKEY,用它对挑战 进行标准DES加密,如果与网络上传输的内容相符,则找到匹配。这里"????"由循环 产生,穷举65536种可能。
上面实际在介绍如何根据Challenge/Response暴力破解获取LM Hash。
即使到了NT4 SP3,DES LM Hash Response还是与DES NTLM Hash Response一起发送, 这种情况下NTLM Hash强度再高也是没有意义的。
如果禁用DES LM Hash Response,Windows 95无法与NT进行正常的SMB通信。
如果你所使用的Windows系统支持口令超过14字节,就尽量使用超过14字节的口令。
☆ Windows NT身份验证机制的脆弱性
1997年2月6日,Dominique Brezinski <dominique.brezinski@CyberSafe.COM>对外 发布了一份关于Windows NT身份验证机制脆弱性的文档(参考资源[8])。
假设有主机B与A
(1) A向B发起连接请求
(2) B向A发送挑战(一组随机数据)
(3) A用源自明文口令的DESKEY对挑战进行标准DES加密得到响应,并发往B
(4) B从SAM中获取A的LM Hash、NTLM Hash,计算出DESKEY,并对前面发往A的挑战进 行标准DES加密
(5) 如果(4)中计算结果与A送过来的响应匹配,A被允许访问B
现在假设一个攻击者C卷入其中
(1) C向B发起连接请求
(2) B向C发送挑战D(一组随机数据)
(3) C等待A向B发起连接请求
(4) 当A向B发起连接请求时,C伪造成B向A发送挑战D
(5) A用源自明文口令的DESKEY对挑战D进行标准DES加密得到响应E,并发往B
(6) C截获到响应E,将它做为针对(2)中挑战D的响应发往B,并声称自己是A
(7) B从SAM中获取A的LM Hash、NTLM Hash,计算出DESKEY,并对挑战D进行标准DES 加密
(8) 如果(7)中计算结果与C送过来的响应匹配,C被允许以A的身份访问B
下面我们详细分析一下这个过程。攻击者C卷入A与B的通信中,C向B建立NBT会话并发 送SMB_COM_NEGOTIATE(0x72)请求报文,指定使用"NT LM 0.12" dialect。在用户级 共享(与之相对的是共享级共享)中"NT LM 0.12"是首选SMB dialect。B将在响应报文 的encryption key(其实应该叫Challenge)字段中返回8字节的挑战。C保存这8字节的 挑战并开始等待,如果B因为超时终止了这次连接,C必须重复前面的步骤。当A试图 连接B时,也会建立NBT会话并发送SMB_COM_NEGOTIATE(0x72)请求报文,就dialect进 行协商。一般最终协商结果都是使用"NT LM 0.12"