«

»

May 16 2013

NTLM认证过程分析,以及过某些代理后无法认证问题解决方法。

前一阵子遇到了一个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 …

wps_clip_image-31929

客户端发请求访问

 

2: C <– S 401 Unauthorized

WWW-Authenticate: NTLM

wps_clip_image-7549

服务器拒绝,返回401.2,提示不可匿名访问,需要认证,并声明是NTLM认证

 

3: C –> S POST …

Authorization: NTLM

wps_clip_image-12420

客户端将自己的NTLM代码发给服务器,其中代码中包含加密的用户名和密码

 

4: C <– S 401 Unauthorized

WWW-Authenticate: NTLM

wps_clip_image-11752

服务器返回401.1,发起Chanllenge,使用保存在服务器端的用户名密码生成加密的代码发给客户端,请求客户端解析

 

5: C –> S GET …

Authorization: NTLM

wps_clip_image-3846

客户端使用服务器发起的Chanllenge代码与自己的认证信息进行回应(如果回应正确则认证通过)

 

6: C <– S Ok

wps_clip_image-10687

认证通过,服务器返回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 …

image002

客户端发请求访问

2: C <– S 401 Unauthorized

WWW-Authenticate: NTLM

image004

服务器拒绝,返回401.2,提示不可匿名访问,需要认证,并声明是NTLM认证

3: C –> S GET …

Authorization: NTLM

image006

客户端将自己的NTLM代码发给服务器,其中代码中包含加密的用户名和密码

4: C <– S 401 Unauthorized

WWW-Authenticate: NTLM

image008

服务器返回401.1,发起Chanllenge,使用保存在服务器端的用户名密码生成加密的代码发给客户端,请求客户端解析

5: C –> S GET …

Authorization: NTLM

image010

客户端使用服务器发起的Chanllenge代码与自己的认证信息进行回应(如果回应正确则认证通过)

6: C <– S

image012

认证失败!

 

整个流程,直通和代理都没有区别。

唯一的几点区别以及NTLM的特性:

1、 网上的资料说,NTLM认证的关键在于“Connection: Keep-Alive”。每次会话生成的认证信息都是不同的。

即:第三步,客户端生成的均为“NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==”,每次都相同

服务器则是:

“TlRMTVNTUAACAAAAEAAQADgAAAAFgomi2NVi54k850UAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”

“TlRMTVNTUAACAAAAEAAQADgAAAAFgomiEMrdcmTWLkwAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”

“TlRMTVNTUAACAAAAEAAQADgAAAAFgomieRl6vsRLLukAAAAAAAAAAIoAigBIAAAABQLODgAAAA9DAE4ATwBPAEMARwBBAFMAAgAQAEMATgBPAE8AQwBHAEEAUwABAAwATQBPAFMAUwAtADEABAAYAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAMAJgBNAE8AUwBTAC0AMQAuAGMAbgBvAG8AYwBnAGEAcwAuAGMAbwBtAAUAGABjAG4AbwBvAGMAZwBhAHMALgBjAG8AbQAAAAAA”

每次都不同,也就是说不同的会话有不同的认证信息。(微软的认证系统靠抓包回放是攻不破了

2、 不经过代理的时候,整个认证过程只有一条连接:

image002[4]

这条连接一直持续到整个认证过程结束都没有断。

而经过代理时,整个过程被分成了很多条连接:

image004[4]

每一条连接都仅完成一次POST,即12、34、56。整个流程从正常的一段,被分解成了3段。

虽然我们的请求里都包含“keep-alive”(不过是小写的!),但是每条连接之后都被reset了

image006[4]

 

分析:

首先由于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。不影响分析逻辑。

 

8 comments

Skip to comment form

  1. 兄弟,你第3步:3: C –> S POST … 描述的有问题啊,(这一步是不会将域用户密码等信息加密发给服务端的) 这一步发送的只是一个BASE64的字符串,服务端接受到这个字符串后,会回发一个code给客户端,这是第四步,客户端接收到服务端回传的这个code后再用code和用户名密码等加密再次发送给服务端,最后服务端会用接受到的信息进行校验是否正确。(校验的操作是服务端去完成的,你说的在客户端校验也是有问题的)

    1. 石樱灯笼

      嗯,你说得对,第三步那里描述是有问题,服务端其实给的就是半块盐。另外我没找到你说的“在客户端校验”是哪一段。

      1. 额,文章里的这段:“客户端使用服务器发起的Chanllenge代码与自己的认证信息进行回应(如果回应正确则认证通过)”

        1. 石樱灯笼

          这句哪里有问题了?

          1. 应该是客户端接收到服务端回发过来的质询码,客户端接收到该code后,使用该code加密用户信息,发送给服务端,服务端进行校验,并不是在客户端进行校验的,校验通过了返回请求的资源给客户端。

  2. jeffer

    你好,请问你用的是什么代理软件?
    我在工作中也遇到这个问题。通过nginx代理访问需要ntlm认证的网站,每个请求都要输入用户名和密码。
    请问有好的办法解决吗?

    1. 石樱灯笼

      公司自己开发的

    2. yadsun

      同问,兄弟问题解决了吗

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据