当发送一个HTTP的请求,收到服务器返回407的时候,我们检查Proxy-Authenticate字段。这个字段可能出现多次,常见的出现三次,参数分别为Negotiate, Kerberos、NTLM。Negotiate是一个ssp(Security Support Provider),它会根据用户的环境选择其它合适的具体SSP:NTLM或者kerberos。 NTLM 是一个比较老的SSP,但支持广泛,Kerberos是新的比较好的SSP,但不支持NT4.0以及之前版本。用户一般不直接调用NTLM或者 Kerberos,而是调用Negotiate。Negotiate的策略是,如果用户系统不支持Kerberos,或者没有提供支持Kerberos的 信息,则Negotiate会默认返回NTLM给客户端。
我们还需要检查Connect字段,如果给出Close,客户端应该关闭原来的TCP连接,在新的TCP连接中给出下一个消息。假设我们选择了NTLM作为认证的算法,客户端收到407后,将第一个HTTP请求增加认证内容重新发送一次,即将NTLM type1 Message,并经过base64的扰码放置在Proxy-Authorization: Negotiate %s中。下面讨论NTLM type1 Message的构造。如果希望详细资料,推荐 http://davenport.sourceforge.net/ntlm.html 。对于开发而言,还是本着实用主义,不求甚解,只求怎用。NTLM还是比较麻烦,即使你确实使用NTLM算法,还需要和服务器通过NTLM flag来确定具体使用NTLMv1还是v2还是v2 session等等。这么多不确定性,完全符合IT人力求的简单复杂化,清楚的也给你弄迷糊的一贯原则。
client发送携带type1 message的请求给服务器,服务器再次返回407,携带type2 Message,中间含有挑战值,client根据挑战值计算response,封装在type3 message中,再次向服务器发送请求,如果认证通过,服务器,返回200 OK。
NTLM type1消息有三个输入:
-
- 客户端所在的DOMAIN
- 主机的名字HOSTNAME,注意这个不是登陆PROXY的用户帐号,而是你的机器workstation在网络中的名字。
- OS操作系统的版本,可选,不填最省事。
这里给出一个数据结构。
0-7字节: char protocol[8] 表明属于NTLMSSP协议,依次位'N', 'T', 'L', 'M', 'S', 'S', 'P', '/0' |
8-11字节:int type 其中第8字节NTLM的类型即type1,填入0x01,后三个字节为0,4字节依次为0x01 00 00 00。由于我们的操作系统是little_endian,本应是0x00 00 00 01表示1,由于高位在前面,故顺序反过来。通过ethreal工具抓包的时候,可以看得非常清楚。 |
12-15字节:unsigned int flags NTLM的flags,是个很麻烦的东西。
|
16-19字节:
short domain_len;
无论是domain的长度,还是domain分配的长度,都是一样的,如果域名为“DOMAIN”,就为0x07000700。short domain_allocation_len; |
20-23字节:int domain_offset 放置domain位置的偏移量,即开始存放domain信息的位置 |
24-27字节 short hostname_len; short hostname_allocation_len; 无论是hostname的长度,还是分配的长度,都是一样的,名字为“WORKSTATION”,就为0x0b000b00。 |
28-31字节:int hostname_offset 放置hostname得偏移量,如果没有可选8字节os_version信息,从32字节开始给出hostname得信息,即为0x20000000,如果含有则从40字节开始,为0x28000000。 |
32字节开始:内容存放
|
对于NTLM v1,type1 message中flags我们给出0xb201,在NTLM v2,给出0x0280b205,在NTLM session中给出0x0288b201,如果在Type2消息中协商成功,那么在type3消息中的flags是同样的值。
相关链接:我的网络通信相关文章
NTLM的实现:
-
- 实现PROXY穿越(16):NTLM的PROXY穿越
- 实现PROXY穿越(15):NTLM Session Security
- 实现PROXY穿越(14):NTLM type3 Message
- 实现PROXY穿越(13):NTLM type2 Message
- 实现PROXY穿越(12):NTLM type1 Message
- 实现PROXY穿越(11):NTLMv2 session response
- 实现PROXY穿越(10):NTLMv2 response
- 实现PROXY穿越(9):NTLMv1 response
- 实现PROXY穿越(8):NT-Hash的实现
- 实现PROXY穿越(7):MD4和MD5
- 实现PROXY穿越(6):LM-Hash的实现
- 实现PROXY穿越(5):DES算法之三
- 实现PROXY穿越(4):DES算法之二
- 实现PROXY穿越(3):DES算法之一
- 实现PROXY穿越(2):Base64算法
- 实现PROXY穿越(1):流程和NTLM算法