LM/NTLM验证机制
☆ 概述
☆ 挑战/响应模式
☆ 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" dialect。C注意到这个协商请求,
于是伪装成B向A发送响应报文,encryption key字段中设置成前面保存下来的挑战。
这个响应报文的源IP设置成B的IP地址,需要分析A送往B的SMB_COM_NEGOTIATE(0x72)
请求报文以设置响应报文的th_ack字段。这个伪造的 响应报文必须抢在B的正常响应
报文之前到达A。如果C本来就扮演着A与B之间路由器一类的角色,这不成问题。来自
B的正常响应报文做为重复数据而被丢弃。此时A生成两组24字节响应,向B发送
SMB_COM_SESSION_SETUP_ANDX(0x73)请求报文。C注意到这个请求,获取了A生成的两
组24字节响应,然后C也构造一个SMB_COM_SESSION_SETUP_ANDX(0x73)请求报文,用
这两组24字节响应分别设置CaseInsensitivePassword、CaseSensitivePassword字段。
同时在AccountName字段设置A的用户名。C将这样一个伪造的0x73请求报文通过最初
建立的NBT会话发往B。至此C将获取一条到B的SMB会话,拥有A用户的权限。
如果C扮演着A与B之间路由器一类的角色,整个攻击过程将大大简化。
☆ str_to_key()函数
前面我们多次提到str_to_key()函数,却未解释这个函数如何实现的,因为用自然语
言描述它比较困难,还是先来看它的C语言描述吧。
--------------------------------------------------------------------------
/*
* For x86/FreeBSD 4.5-RELEASE
* gcc -Wall -pipe -O3 -o str_to_key_test str_to_key_test.c
*
* C23413A8A1E7665FAAD3B435B51404EE0000000000
* C21A04748A0E9CCC5ED4B47642ACD4280476800000000000
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* 读取形如"AABBCCDDEEFF"这样的16进制数字串,主调者自己进行形参的边界检查
*/
static void readhexstring ( const unsigned char *src, unsigned char *dst, unsigned int len )
{
unsigned int i;
unsigned char str[3];
str[2] = ‘\0‘;
for ( i = 0; i < len; i++ )
{
str[0] = src[ i * 2 ];
str[1] = src[ i * 2 + 1 ];
dst = ( unsigned char )strtoul( str, NULL, 16 );
}
return;
} /* end of readhexstring */
/*
* from The Samba Team‘s source/libsmb/smbdes.c
*/
static void str_to_key ( const unsigned char *str, unsigned char *key )
{
unsigned int i;
key[0] = str[0] >> 1;
key[1] = ( ( str[0] & 0x01 ) << 6 ) | ( str[1] >> 2 );
key[2] = ( ( str[1] & 0x03 ) << 5 ) | ( str[2] >> 3 );
key[3] = ( ( str[2] & 0x07 ) << 4 ) | ( str[3] >> 4 );
key[4] = ( ( str[3] & 0x0F ) << 3 ) | ( str[4] >> 5 );
key[5] = ( ( str[4] & 0x1F ) << 2 ) | ( str[5] >> 6 );
key[6] = ( ( str[5] &am p; 0x3F ) << 1 ) | ( str[6] >> 7 );
key[7] = str[6] & 0x7F;
for ( i = 0; i < 8; i++ )
{
key = ( key << 1 );
}
return;
} /* end of str_to_key */
int main ( int argc, char * argv[] )
{
unsigned int i;
unsigned char buf_0[21];
unsigned char buf_1[24];
if ( argc != 2 )
{
fprintf( stderr, "Usage: %s <hexadecimal string>\n", argv[0] );
return( EXIT_FAILURE );
}
memset( buf_0, 0, sizeof( buf_0 ) );
memset( buf_1, 0, sizeof( buf_1 ) );
i = strlen( argv[1] ) / 2;
readhexstring( argv[1], buf_0, i );
for ( i = 0; i < sizeof( buf_0 ); i++ )
{
fprintf( stderr, "%02X", buf_0 );
}
fprintf( stderr, "\n" );
str_to_key( buf_0, buf_1 );
str_to_key( buf_0 + 7, buf_1 + 8 );
str_to_key( buf_0 + 14, buf_1 + 16 );
for ( i = 0; i < sizeof( buf_1 ); i++ )
{
fprintf( stderr, "%02X", buf_1 );
}
fprintf( stderr, "\n" );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
☆ 如何从明文口令生成LM Hash
假设明文口令是"Welcome",首先全部转换成大写,再做如下变换
"WELCOME" -> 57454C434F4D4500000000000000
也就是说在明文口令不足14字节的情况下,后面添加0x00补足14字节。有些书上介绍
添加空格(0x20)补足14字节,这是错误的,我不清楚是原作者写错了,还是译者的问
题。
然后切割成两组7字节的数据,分别经str_to_key()函数处理得到两组8字节数据
57454C434F4D45 -str_to_key()-> 56A25288347A348A
00000000000000 -str_to_key()-> 0000000000000000
这两组8字节数据将做为DESKEY对魔术字符串"KGS!@#$%"进行标准DES加密
"KGS!@#$%" -> 4B47532140232425
56A25288347A348A -对4B47532140232425进行标准DES加密-> C23413A8A1E7665F
0000000000000000 -对4B47532140232425进行标准DES加密-> AAD3B435B51404EE
将加密后的这两组数据简单拼接,就得到了最后的LM Hash
LM Hash: C23413A8A1E7665FAAD3B435B51404EE
显然,由于明文口令一开始就全部转换成大写,导致多个明文口令对应一个LM Hash。
反过来,在穷举破解LM Hash时,得到的有可能不是原始口令,因为不可能确定大小
写。仔细观察前述SMB身份验证过程,即使这里得到的不是 原始口令(大小写有差别),
同样可以通过SMB身份验证。这种转换成大写的行为减小了穷举破解强度。
另一个弱点,当明文口令小于8字节时,LM Hash后8字节的计算过程总是这样的
00000000000000 -str_to_key()-> 0000000000000000 -对4B47532140232425进行标准DES加密-> AAD3B435B51404EE
这也将减小穷举破解强度。
IBM设计了这个LM Hash算法,魔术字符串"KGS!@#$%"的意义无从考证。这个算法称之
为"哈希"不怎么妥当,由于是标准DES加密,完全是可逆的。当然,由于要穷举的是
DESKEY本身,与传统所说的可逆有区别。
☆ 标准DES加密
这里不会重复DES的历史,Bruce Schneier所著<<应用密码学(第二版)>>值得一看。
事实上我们在自己编程时使用了书中附录里的DES例子代码。该书英文电子版未在互
联网上正式流传,尤其包含附录代码的配套磁盘被限制在北美地区以外出现,google
还是留下了它们。tombkeeper从google网页快照中恢复了该书英文版全部章节并制做
了一份chm文件,包括所有源代码,只是少了图。我不得不佩服这个变态的精力旺盛,
尽管后来他又从苏联人的地下站点上找到了该书更完整的内容,比如图。
本篇不打算涉及DES算法的C语言描述,microcat(lgx)为我写了这个临时测试程序用
于验证某些概念
--------------------------------------------------------------------------
/*
* For x86/FreeBSD 4.5-RELEASE
* gcc -Wall -pipe -O3 -o des_test des_test.c -lcrypto
*
* key : 01 23 45 67 89 AB CD EF
* cipher : C9 57 44 25 6A 5E D3 1D
* plain : 01 23 45 67 89 AB CD E7
*/
#include <stdio.h>
#include <stdlib.h>
#include <openssl/des.h>
int main ( int argc, char * argv[] )
{
unsigned int i;
des_key_schedule ks;
/*
* typedef unsigned char des_cblock[8];
* typedef unsigned char const_des_cblock[8];
*/
const_des_cblock key =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
};
const_des_cblock plain_0 =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xE7,
};
des_cblock plain_1;
des_cblock cipher;
printf( "key : " );
for ( i = 0; i < 8; i++ )
{
printf( "%02X%c", key, i == 7 ? ‘\n‘ : ‘ ‘ );
}
des_set_key_unchecked( &key, ks );
des_ecb_encrypt( &plain_0, &cipher, ks, DES_ENCRYPT );
printf( "cipher : " );
for ( i = 0; i < 8; i++ )
{
printf( "%02X%c", cipher, i == 7 ? ‘\n‘ : ‘ ‘ );
}
des_ecb_encrypt( &cipher, &plain _1, ks, DES_DECRYPT );
printf( "plain : " );
for ( i = 0; i < 8; i++ )
{
printf( "%02X%c", plain_1, i == 7 ? ‘\n‘ : ‘ ‘ );
}
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
☆ 如何从明文口令生成NTLM Hash
IBM设计的LM Hash算法存在几个弱点,微软在保持向后兼容性的同时提出了自己的挑
战响应机制,NTLM Hash应运而生。
假设明文口令是"123456",首先转换成Unicode字符串,与LM Hash算法不同,这次不
需要添加0x00补足14字节
"123456" -> 310032003300340035003600
从ASCII串转换成Unicode串时,使用little-endian序,微软在设计整个SMB协议时就
没考虑过big-endian序,ntoh*()、hton*()函数不宜用在SMB报文解码中。0x80之前
的标准ASCII码转换成Unicode码,就是简单地从0x??变成0x00??。此类标准ASCII串
按little-endian序转换成Unicode串,就是简单地在原有每个字节之后添加0x00。
对所获取的Unicode串进行标准MD4单向哈希,无论数据源有多少字节,MD4固定产生
128-bit的哈希值,16字节
310032003300340035003600 -进行标准MD4单向哈希-> 32ED87BDB5FDC5E9CBA88547376818D4
就得到了最后的NTLM Hash
NTLM Hash: 32ED87BDB5FDC5E9CBA88547376818D4
与LM Hash算法相比,明文口令大小写敏感,无法根据NTLM Hash判断原始明文口令是
否小于8字节,摆脱了魔术字符串"KGS!@#$%"。
MD4是真正的单向哈希函数,穷举做为数据源出现的明文,难度较大。
问题在于,微软一味强调NTLM Hash的强度高,却避而不谈一个事实,为了保持向后
兼容性,NTLMHash缺省总是与LM Hash一起使用的。这意味着NTLM Hash强调再高也是
无助于安全的,相反潜在损害着安全性。增加NTLM Hash后,首先利用LM Hash的弱点
穷举出原始明文口令的大小写不敏感版本,再利用NTLM Hash修正出原始明文口令的
大小写敏感版本。
Phrack Magazine 50-08(参考资源[10])中提供的源程序根据NTLM Hash挂字典穷举明
文口令。我们推荐LC4。
☆ 标准MD4单向哈希
Ron Rivest设计的MD4算法固定产生128-bit的哈希值。尽管其理论上存在某些弱点,
但那是密码学家、数学家眼中的弱点,或者是NSA(美国国家安全局)所拥有计算能力
下的弱点,当然在分布式计算逐渐盛行的今天,也许还存在其它角度的弱点。除此三
者之外,MD4用来生成NTLM Hash,强度足够了。遗憾的是算法本身的强度不能保证整
个NTLM Hash验证机制的安全性。
Bruce Schneier所著<<应用密码学(第二版)>>中对MD4做了介绍。我们在自己编程时
使用了1999年挖自Tripwire Project的MD4实现代码。本篇不打算涉及MD4算法的C语
言描述,microcat(lgx)为我写了这个临时测试程序用于验证某些概念
--------------------------------------------------------------------------
/*
* For x86/FreeBSD 4.5-RELEASE
* gcc -Wall -pipe -O3 -o md 4_test md4_test.c -lcrypto
*
* plain : 31 00 32 00 33 00 34 00 35 00 36 00
* md4 : 32 ED 87 BD B5 FD C5 E9 CB A8 85 47 37 68 18 D4
*/
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md4.h>
int main ( int argc, char * argv[] )
{
unsigned int i;
unsigned char md4[16];
unsigned char plain[] =
{
0x31, 0x00, 0x32, 0x00, 0x33, 0x00,
0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
};
printf( "plain : " );
for ( i = 0; i < sizeof( plain ); i++ )
{
printf( "%02X%c", plain, i == ( sizeof( plain ) - 1 ) ? ‘\n‘ : ‘ ‘ );
}
MD4( plain, sizeof( plain), md4 );
printf( "md4 : " );
for ( i = 0; i < sizeof( md4 ); i++ )
{
printf( "%02X%c", md4, i == ( sizeof( md4 ) - 1 ) ? ‘\n‘ : ‘ ‘ );
}
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
☆ SMB报文中使用的是DES LM Hash和DES NTLM Hash
大量中英文档在转述L0pht的资料,LC4系列在GUI上没有区分LM Hash、NTLM Hash与
DES LM Hash、DES NTLM Hash,加上转述者表达方式各不相同,引起一些概念上的混
淆。SMB报文中并不直接使用原始的LM Hash、NTLM Hash,而是对之进行了标准DES加
密。
假设有如下原始数据,虽然生成算法不同,但两个Hash值都是16字节长。挑战来自网
络传输,一般出现在SMB_COM_NEGOTIATE(0x72)响应报文的encryption key字段,固
定长8字节。
LM Hash -> 44EFCE164AB921CAAAD3B435B51404EE
NTLM Hash -> 32ED87BDB5FDC5E9CBA88547376818D4
Challenge -> E6010BA38D389439
在LM Hash后添加五个0x00补足21个字节,再用str_to_key()处理成24字节,每8字节
一切割,得到三组DESKEY。利用这三组DESKEY分别对8字节挑战进行标准DES加密
44EFCE164AB921CAAAD3B435B51404EE0000000000
|
str_to_key()
|
V
4476F2C26454E442CA54B47642ACD4280476800000000000
DESKEY1 -> 4476F2C26454E442 -对E6010BA38D389439进行标准DES加密-> 6DA05CC936C0D9B9
DESKEY2 -> CA54B47642ACD428 -对E6010BA38D389439进行标准DES加密-> 37DE29821E728894
DESKEY3 -> 0476800000000000 -对E6010BA38D389439进行标准DES加密-> 368728E66F38669E
将所得三组数据简单拼接就得到了24字 节的DES LM Hash(响应)
DES LM Hash -> 6DA05CC936C0D9B937DE29821E728894368728E66F38669E
出现在SMB_COM_SESSION_SETUP_ANDX(0x73)请求报文的CaseInsensitivePassword字
段中。
在NTLM Hash后添加五个0x00补足21个字节,再用str_to_key()处理成24字节,每8字
节一切割,得到三组DESKEY。利用这三组DESKEY分别对8字节挑战进行标准DES加密
32ED87BDB5FDC5E9CBA88547376818D40000000000
|
str_to_key()
|
V
327660F6DAAEF68AE8E4EA105438DCD0186A000000000000
DESKEY1 -> 327660F6DAAEF68A -对E6010BA38D389439进行标准DES加密-> 19C4336ACBBB62DD
DESKEY2 -> E8E4EA105438DCD0 -对E6010BA38D389439进行标准DES加密-> 37802C62AD5C6903
DESKEY3 -> 186A000000000000 -对E6010BA38D389439进行标准DES加密-> 4B68998B807F8A9D
将所得三组数据简单拼接就得到了24字节的DES NTLM Hash(响应)
DES NTLM Hash -> 19C4336ACBBB62DD37802C62AD5C69034B68998B807F8A9D
出现在SMB_COM_SESSION_SETUP_ANDX(0x73)请求报文的CaseSensitivePassword字段
中。
这实际上是两组24字节响应的生成算法。
☆ 观察一个实例
在192.168.5.150(x86/FreeBSD 4.5-RELEASE)上执行
./smbclient -L "WIN2000-RD" -I 192.168.5.101 -U test (test的口令是123456)
其中"WIN2000-RD"用nbstat -A 192.168.5.101获得
WIN2000-RD <20> UNIQUE Registered
这是来自L0pht/LC4的监听信息
DES LM Hash -> 6DA05CC936C0D9B937DE29821E728894368728E66F38669E
DES NTLM Hash -> 19C4336ACBBB62DD37802C62AD5C69034B68998B807F8A9D
Challenge -> E6010BA38D389439
这是来自"pwdump4.exe 192.168.5.101"的输出,先用Administrator建立SMB会话
net use \\192.168.5.101\IPC$ <password> /user:Administrator
test:1014:44EFCE164AB921CAAAD3B435B51404EE:32ED87BDB5FDC5E9CBA88547376818D4:::
LM Hash -> 44EFCE164AB921CAAAD3B435B51404EE
NTLM Hash -> 32ED87BDB5FDC5E9CBA88547376818D4
192.168.5.101是一台x86/PWindows 2000。
LC4和pwdump4.exe在网上很多,用google一搜就出来了,我测试的时候是tombkeeper
提供的。smbclient就是Samba Team的Samba Project中的那个。
☆ negotiate response解码
192.168.5.8(x86/EWindows XP) 192.1 68.5.101(x86/PWindows 2000 SP3)
------------+--------------- --------------+---------------------
| |
+------------------------------------+
|
| 192.168.5.12(x86/PWindows 2000)
| --------------+----------------
| |
+------------------------------------+
|
------------+---------------------------------------
192.168.5.150(x86/FreeBSD 4.5-RELEASE + samba-2.2.5)
网络结构如上,我们从192.168.5.150上执行如下命令
smbclient -I 192.168.5.12 -L RESEARCH12 -U "RESEARCH12\test"
输入明文口令"123456",成功返回。用Ethereal 0.9.7 For Windows抓包观察
--------------------------------------------------------------------------
TCP层
Source port: 139
Destination port: 1039
Sequence number: 3697001587
Next sequence number: 3697001710
Acknowledgement number: 2853414712
Header length: 32 bytes
Flags: 0x0018 (PSH, ACK)
0... .... =
.0.. .... =
..0. .... = Urgent: Not set
...1 .... = Acknowledgment: Set
.... 1... = Push: Set
.... .0.. = Reset: Not set
.... ..0. = Syn: Not set
.... ...0 = Fin: Not set
Window size: 17276
Checksum: 0x20ce (correct)
Options: (12 bytes)
NOP
NOP
Time stamp: tsval 1357667, tsecr 25400092
NBT层
Message Type: Session message (0x00)
Flags: 0x00
.... ...0 = Add 0 to length
Length: 119 (0x0077)
SMB层 (Server Message Block Protocol)
SMB Header
Server Component: 0xFF SMB
SMB Command: Negotiate Protocol (0x72)
Error Class: Success (0x00)
Reserved: 00
Error Code: No Error
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has n ot been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0x0001
0... .... .... .... = Unicode Strings: Strings are ASCII
.0.. .... .... .... = Error Code Type: Error codes are DOS error codes
..0. .... .... .... = Execute-only Reads: Don‘t permit reads if execute-only
...0 .... .... .... = Dfs: Don‘t resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Reserved: 000000000000000000000000
Tree ID: 0
Process ID: 4225
User ID: 0
Multiplex ID: 1
Negotiate Protocol Response (0x72)
Word Count (WCT): 17 (0x11)
Dialect Index: 7, greater than LANMAN2.1 (索引从0开始,这里对应NT LM 0.12)
Security Mode: 0x03
.... ...1 = Mode: USER security mode
.... ..1. = Password: ENCRYPTED password. Use challenge/response
.... .0.. = Signatures: Security signatures NOT enabled
.... 0... = Sig Req: Security signatures NOT required
Max Mpx Count: 50
Max VCs: 1
Max Buffer Size: 16644
Max Raw Buffer: 65536
Session Key: 0x00000000
Capabilities: 0x0000f3fd
.... .... .... .... .... .... .... ...1 = Raw Mode: Read Raw and Write Raw are supported
.... .... .... .... .... .... .... ..0. = MPX Mode: Read Mpx and Write Mpx are not supported
.... .... .... .... .... .... .... .1.. = Unicode: Unicode strings are supported
.... .... .... .... .... .... .... 1... = Large Files: Large files are supported
.... .... .... .... .... .... ...1 .... = NT SMBs: NT SMBs are supported
.... .... .... .... .... .... ..1. .... = RPC Remote APIs: RP C remote APIs are supported
.... .... .... .... .... .... .1.. .... = NT Status Codes: NT status codes are supported
.... .... .... .... .... .... 1... .... = Level 2 Oplocks: Level 2 oplocks are supported
.... .... .... .... .... ...1 .... .... = Lock and Read: Lock and Read is supported
.... .... .... .... .... ..1. .... .... = NT Find: NT Find is supported
.... .... .... .... ...1 .... .... .... = Dfs: Dfs is supported
.... .... .... .... ..1. .... .... .... = Infolevel Passthru: NT information level request passthrough is supported
.... .... .... .... .1.. .... .... .... = Large ReadX: Large Read andX is supported
.... .... .... .... 1... .... .... .... = Large WriteX: Large Write andX is supported
.... .... 0... .... .... .... .... .... = UNIX: UNIX extensions are not supported
.... ..0. .... .... .... .... .... .... = Reserved: Reserved
..0. .... .... .... .... .... .... .... = Bulk Transfer: Bulk Read and Bulk Write are not supported
.0.. .... .... .... .... .... .... .... = Compressed Data: Compressed data transfer is not supported
0... .... .... .... .... .... .... .... = Extended Security: Extended security exchanges are not supported
System Time: Jul 26, 2002 09:52:52.429138183
Server Time Zone: -480 min from UTC
Key Length: 8 (指明Server Challenge的字节长度)
Byte Count (BCC): 50 (0x32 0x00,SMB层使用little-endian序)
Encryption Key: 46B0F8AB00335086 (这实际上是Server Challenge)
Primary Domain: WORKGROUP
Server: RESEARCH12
0000 00 50 56 41 42 03 00 10 5a 84 7a f0 08 00 45 00 .PVAB...Z.z...E.
0010 00 af fc 02 40 00 80 06 72 53 c0 a8 05 0c c0 a8 ....@...rS......
0020 05 96 00 8b 04 0f dc 5b c4 73 aa 13 a7 38 80 18 .......[.s...8..
0030 43 7c 20 ce 00 00 01 01 08 0a 00 14 b7 63 01 83 C| ..........c..
0040 93 1c 00 00 00 77 ff 53 4d 42 72 00 00 00 00 88 .....w.SMBr.....
0050 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0060 81 10 00 00 01 00 11 07 00 03 32 00 01 00 04 41 ..........2....A
0070 00 00 00 00 01 00 00 00 00 00 fd f3 00 00 40 ad ..............@.
0080 2b 27 47 34 c2 01 20 fe 08 32 00 46 b0 f8 ab 00 +‘G4.. ..2.F....
0090 33 50 86 57 00 4f 00 52 00 4b 00 47 00 52 00 4f 3P.W.O.R.K.G.R.O
00a0 00 55 00 50 00 00 00 52 00 45 00 53 00 45 00 41 .U.P...R.E.S.E.A
00b0 00 52 00 43 00 48 00 31 00 32 00 00 00 .R.C.H.1.2...
--------------------------------------------------------------------------
当使用LM/NTLM验证机制时,negotiate response报文中包含了Server Challenge。
☆ session_setup_andx request解码
--------------------------------------------------------------------------
NBT层
Message Type: Session message (0x00)
Flags: 0x00
.... ...0 = Add 0 to length
Length: 164 (0x00a4)
SMB层 (Server Message Block Protocol)
SMB Header
Server Component: 0xFF SMB
SMB Command: Session Setup AndX (0x73)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don‘t permit reads if execute-only
...0 .... .... .... = Dfs: Don‘t resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Reserved: 000000000000000000000000
Tree ID: 0
Process ID: 4225
User ID: 0
Multiplex ID: 1
Session Setup AndX Request (0x73)
Word Count (WCT): 13
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
Max Buffer: 65535
Max Mpx Count: 2
VC Number: 4225
Session Key: 0x00000000
ANSI Password Length: 24 (指明DES LM Hash的字节长度)
Unicode Password Length: 24 (指明DES NTLM Hash的字节长度)
Reserved: 00000000
Capabilities: 0x00000054
.... .... .... .... .... .... .... ...0 = Raw Mode: Read Raw and Write Raw are not supported
.... .... .... .... .... .... .... ..0. = MPX Mode: Read Mpx and Write Mpx are not supported
.... .... .... .... .... .... .... .1.. = Unicode: Unicode strings are supported
.... .... .... .... .... .... .... 0... = Large Files: Large files are not supported
.... .... .... .... .... .... ...1 .... = NT SMBs: NT SMBs are supported
.... .... .... .... .... .... ..0. .... = RPC Remote APIs: RPC remote APIs are not supported
.... .... .... .... .... .... .1.. .... = NT Status Codes: NT status codes are supported
.... .... .... .... .... .... 0... .... = Level 2 Oplocks: Level 2 oplocks are not supported
.... .... .... .... .... ...0 .... .... = Lock and Read: Lock and Read is not supported
.... .... .... .... .... ..0. .... .... = NT Find: NT Find is not supported
.... .... .... .... ...0 .... .... .... = Dfs: Dfs is not supported
.... .... .... .... ..0. .... .... .... = Infolevel Passthru: NT information level request passthrough is not supported
.... .... .... .... .0.. .... .... .... = Large ReadX: Large Read andX is not supported
.... .... .... .... 0... .... .... .... = Large WriteX: Large Write andX is no t supported
.... .... 0... .... .... .... .... .... = UNIX: UNIX extensions are not supported
.... ..0. .... .... .... .... .... .... = Reserved: Reserved
..0. .... .... .... .... .... .... .... = Bulk Transfer: Bulk Read and Bulk Write are not supported
.0.. .... .... .... .... .... .... .... = Compressed Data: Compressed data transfer is not supported
0... .... .... .... .... .... .... .... = Extended Security: Extended security exchanges are not supported
Byte Count (BCC): 103
ANSI Password: 154E0DE15A54BC54008D80188E37FD9C8CDE93E6961C6915 (DES LM Hash)
Unicode Password: D611B7C5DBE8EA849FDBBAA60A956E95078D16F0B906D509 (DES NTLM Hash)
Account: TEST
Primary Domain: RESEARCH12
Native OS: Unix
Native LAN Manager: Samba
0000 00 10 5a 84 7a f0 00 50 56 41 42 03 08 00 45 00 ..Z.z..PVAB...E.
0010 00 dc d9 d5 40 00 40 06 d4 53 c0 a8 05 96 c0 a8 ....@.@..S......
0020 05 0c 04 0f 00 8b aa 13 a7 38 dc 5b c4 ee 80 18 .........8.[....
0030 82 18 7f 15 00 00 01 01 08 0a 01 83 93 fe 00 14 ................
0040 b7 63 00 00 00 a4 ff 53 4d 42 73 00 00 00 00 08 .c.....SMBs.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0060 81 10 00 00 01 00 0d ff 00 00 00 ff ff 02 00 81 ................
0070 10 00 00 00 00 18 00 18 00 00 00 00 00 54 00 00 .............T..
0080 00 67 00 15 4e 0d e1 5a 54 bc 54 00 8d 80 18 8e .g..N..ZT.T.....
0090 37 fd 9c 8c de 93 e6 96 1c 69 15 d6 11 b7 c5 db 7........i......
00a0 e8 ea 84 9f db ba a6 0a 95 6e 95 07 8d 16 f0 b9 .........n......
00b0 06 d5 09 00 54 00 45 00 53 00 54 00 00 00 52 00 ....T.E.S.T...R.
00c0 45 00 53 00 45 00 41 00 52 00 43 00 48 00 31 00 E.S.E.A.R.C.H.1.
00d0 32 00 00 00 55 00 6e 00 69 00 78 00 00 00 53 00 2...U.n.i.x...S.
00e0 61 00 6d 00 62 00 61 00 00 00 a.m.b.a...
--------------------------------------------------------------------------
当使用LM/NTLM验证机制时,session_setup_andx reque st报文中包含了DES LM Hash
以及DES NTLM Hash。
根据前面的种种分析,现在我们有如下数据可供研究LM/NTLM验证机制
--------------------------------------------------------------------------
Password : 123456
: 313233343536
Password DESKEY1 : 30988C6642A8D800
Password DESKEY2 : 0000000000000000
Magic String : 4B47532140232425
LM Hash : 44EFCE164AB921CAAAD3B435B51404EE
NTLM Hash : 32ED87BDB5FDC5E9CBA88547376818D4
Server Challenge : 46B0F8AB00335086
LM DESKEY1 : 4476F2C26454E442
LM DESKEY2 : CA54B47642ACD428
LM DESKEY3 : 0476800000000000
DES LM Hash : 154E0DE15A54BC54008D80188E37FD9C8CDE93E6961C6915
NTLM DESKEY1 : 327660F6DAAEF68A
NTLM DESKEY2 : E8E4EA105438DCD0
NTLM DESKEY3 : 186A000000000000
DES NTLM Hash : D611B7C5DBE8EA849FDBBAA60A956E95078D16F0B906D509
--------------------------------------------------------------------------
☆ 小结
LM/NTLM验证机制是缺省的、最广泛使用的SMB验证机制。了解这种验证机制有助于拓
展SMB攻击/防御的思路,也为我们后续的SMB DoS、SMB Remote Buffer Overflow研
究做一铺垫。
DES NTLM Hash总是与DES LM Hash一起使用,而且只要这二者之一通过验证即可,这
意味着DES NTLM Hash形同虚设。
NSFocus Security Team的袁哥 <yuange@nsfocus.com>在2000年曾提出一种新的SMB
攻击思路,充分利用LM/NTLM验证机制本身的脆弱性(直接比较DES LM/NTLM Hash)以
及Windows SMB客户端的一个特性(主动发送本机当前登录用户凭证)。具体技术细节
参看袁哥于2000年在NSFocus技术论坛的发言。在SMB系列的后续文章中我们会就一些
类似的攻击技术做一比较、总结。
NTLMv2验证机制将在SMB系列(6)中做详细介绍。它增加了双向验证机制,使得一些常
规会话劫持攻击、中间人攻击更加难以完成。
Kerberos验证机制在实际环境中应用不广,暂时搁在一旁。
出于某些原因,我们刻意省略了对NTLMSSP协议的解码分析过程,将与NTLMv2验证机
制一并介绍。
就SMB协议分析过程来看,MS Network Monitor不可靠,Sniffer Pro略优,Ethereal
最强。由于Ethereal可以打开前两者生成的CAP文件,因此可以结合起来使用。
本文撰写过程中得到RSAS开发小组中lgx以及NSFocus安全研究小组中tombkeeper、
yuange的大力支持,在此表示万分感谢。向参考资源中文章的各位作者顺致敬意,尤
其是[4]。
☆ 参考资源
[1] L0phtcrack 1.5 Lanman / NT password hash cracker
http://www.insecure.org/sploits/l0phtcrack.lanman.problems.html
[2] command line prompts for DES
http://mhonarc. esec.com.au/list-jce/msg00380.html
[3] [VulnWatch] SunPCi II VNC weak authentication scheme vulnerability
http://www.attrition.org/security/advisory/misc/tf20020601.sunpci_ii_vnc
http://www.der-keiler.de/Mailing-Lists/Securiteam/2002-07/0015.html
[4] http://islab.oregonstate.edu/documents/ftpsites/wimsey/DES/triple-DES (cool)
[5] [jcifs] Quick LM Hash question
http://lists.samba.org/pipermail/jcifs/2002-April/002094.html
[7] CIFS: Common Insecurities Fail Scrutiny
http://signaltonoise.net/library/cifs.htm
[8] BoS: Windows NT authentication weakness
http://www.tao.ca/writing/archives/security/0343.html
[9] NT Domain Authentication Protocol
http://bugtraq.inet-one.com/dir.1997-10/msg00008.html
[10] Phrack Magazine 50-08: Cracking NT Passwords
http://www.phrack.com/phrack/50/P50-08
[14] Samba Stuff
http://www.richardsharpe.com/samba-stuff.html
[15] SMB authentication when CAP_EXTENDED_SECURITY negotiated
http://www.iss.net/security_center/static/3325.php
[21] Ethereal User‘s Guide V1.1 for Ethereal 0.9.7
http://www.ethereal.com/docs/user-guide/