- A+
前一阵子遇到了一个NTLM认证的问题,解决问题的同时就顺带了解了一下NTLM的认证过程。
顺便也把我遇到的问题写出来。
正常情况下NTLM的认证过程:
1: C –> S GET/POST …
2: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
3: C –> S GET/POST …
Authorization: NTLM
4: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
5: C –> S GET/POST …
Authorization: NTLM
6: C <—S Ok
以下以一台PC直接登陆,且成功登陆为例:
1: C –> S POST …
客户端发请求访问
2: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
服务器拒绝,返回401.2,提示不可匿名访问,需要认证,并声明是NTLM认证
3: C –> S POST …
Authorization: NTLM
客户端将自己的NTLM代码发给服务器,其中代码中包含加密的用户名和密码
4: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
服务器返回401.1,发起Chanllenge,使用保存在服务器端的用户名密码生成加密的代码发给客户端,请求客户端解析
5: C –> S GET …
Authorization: NTLM
客户端使用服务器发起的Chanllenge代码与自己的认证信息进行回应(如果回应正确则认证通过)
6: C <– S Ok
认证通过,服务器返回302跳转,页面跳转至网站内部,整个认证过程结束。
按照服务器的提示,整个流程为:
1: C –> S POST …
2: C <– S 401.2 Unauthorized
WWW-Authenticate: NTLM
3: C –> S POST…
Authorization: NTLM
4: C <– S 401.1 Unauthorized
WWW-Authenticate: NTLM
5: C –> S POST…
Authorization: NTLM
6: C <—S 302
我在工作中遇到的问题是,过代理之后无法通过服务器的NTLM认证。
也就是说,我在PC上配置了一个代理,通过代理访问一个需要NTLM认证的网站。
首先,按照正常情况下NTLM的认证过程模板
1: C –> S GET …
2: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
3: C –> S GET …
Authorization: NTLM
4: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
5: C –> S GET …
Authorization: NTLM
6: C <– S Ok(出错就在这一步)
从抓包分析(以下仅分析从代理到服务器的数据包,未分析PC到代理的数据包):
1: C –> S GET …
客户端发请求访问
2: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
服务器拒绝,返回401.2,提示不可匿名访问,需要认证,并声明是NTLM认证
3: C –> S GET …
Authorization: NTLM
客户端将自己的NTLM代码发给服务器,其中代码中包含加密的用户名和密码
4: C <– S 401 Unauthorized
WWW-Authenticate: NTLM
服务器返回401.1,发起Chanllenge,使用保存在服务器端的用户名密码生成加密的代码发给客户端,请求客户端解析
5: C –> S GET …
Authorization: NTLM
客户端使用服务器发起的Chanllenge代码与自己的认证信息进行回应(如果回应正确则认证通过)
6: C <– S
认证失败!
整个流程,直通和代理都没有区别。
唯一的几点区别以及NTLM的特性:
1、 网上的资料说,NTLM认证的关键在于“Connection: Keep-Alive”。每次会话生成的认证信息都是不同的。
即:第三步,客户端生成的均为“NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==”,每次都相同
服务器则是:
“TlRMTVNTUAACAAAAEAAQADgAAAAFgomi2NVi54k850UAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”
“TlRMTVNTUAACAAAAEAAQADgAAAAFgomiEMrdcmTWLkwAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”
“TlRMTVNTUAACAAAAEAAQADgAAAAFgomieRl6vsRLLukAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”
每次都不同,也就是说不同的会话有不同的认证信息。(微软的认证系统靠抓包回放是攻不破了)
2、 不经过代理的时候,整个认证过程只有一条连接:
这条连接一直持续到整个认证过程结束都没有断。
而经过代理时,整个过程被分成了很多条连接:
每一条连接都仅完成一次POST,即12、34、56。整个流程从正常的一段,被分解成了3段。
虽然我们的请求里都包含“keep-alive”(不过是小写的!),但是每条连接之后都被reset了
分析:
首先由于NTLM的认证需要Keep-Alive,所以如果在第4步被reset了,就会导致第四步由服务器生成的WWW-Authenticate失效,这样第五步发出的Authorization就是过期的,进而导致认证失败。
那么,代理的会话被reset就是罪魁祸首,如果代理能和pc直通一样,与服务器保持Keep-Alive,问题就能解决。
检查了代理引擎关于NTLM的代码,发现这个代理引擎在访问需要NTLM认证服务器的时候,会自己把链接断开,也就是说上面的分析是正确的。
改写了代码让代理引擎保证Keep-Alive,问题修复。
参考资料:http://www.blogjava.net/security/archive/2008/11/18/38717.html
与本文不同的是,资料上都是GET,本文都是POST。不影响分析逻辑。
FROM:
https://blog.catscarlet.com/201305161297.html
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫