NTLM认证协议学习笔记(一)
zhao_rong 2011-06-15关于IE,需要看设置,工具>Internet选项>安全>自动定义级别,滚动框拉到最下面,用户登录有四个选项,一般都是选择在intranet中自动登录,这是正常的,一般只有内网站点的认证信息才会和你的用户名密码有关,我们现在为了学习实验,可以它设置为自动使用当前用户名和密码登录。
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession();
boolean unauthenticated = true;
if (!httpRequest.getRequestURI().endsWith("login.jsp")) {
if (session.getAttribute("username") == null || "".equals(session.getAttribute("username"))) {
String authStr = httpRequest.getHeader("authorization");
if (authStr != null) {
authStr = (authStr.split("\\s"))[1];
authStr = new String(new BASE64Decoder().decodeBuffer(authStr));
System.out.println(authStr);
String[] params = authStr.split(":");
if (params != null && params.length == 2) {
if ("rong_zhao".equals(params[0]) && "123456".equals(params[1])) {
System.out.println("pass, username=[" + params[0] + "], password=[" + params[1] + "]");
unauthenticated = false;
}
}
}
}
}
if (unauthenticated) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.setHeader("www-Authenticate", "Basic realm=\"rong.com\"");
return;
}
else{
session.setAttribute("username", "rong_zhao");
}
这段待码是用Basic方式认证,加入这段代码以后,
访问http://localhost:8084/NTLM, 可以看到浏览器弹框,如果输入的用户名和密码是“rong_zhao” 和 "123456",那么就会通过认证,否则就会不停的弹框让你输入用户名和密码。
Basic认证方式是由代码:
httpResponse.setHeader("www-Authenticate", "Basic realm=\"rong.com\"");
代码确定的,后面realm指定域名,这个牵扯到LDAP相关知识,这里就不再罗嗦其他话题,我们可以直接忽略他,也可以不写它。
ok,这种方式的缺点就是用户名和密码等同于是明文传输的,因为他是Base64编码的,任何人抓包可以获得用户名和密码。如下图所示:
只要知道了这个base64编码的字符串就能直接得到用户名和密码,很明显,这是极度不安全的。
那么如果使用NTLM认证协议会怎么样呢?
把
httpResponse.setHeader("www-Authenticate", "Basic realm=\"rong.com\"");
写成
httpResponse.setHeader("www-Authenticate", "NTLM");
然后再运行,用IE访问http://localhost:8084/NTLM,抓包可以看到下面的数据包:
GET /NTLM/ HTTP/1.1
Host: localhost:8084
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=154FDACF04E51C847E8B80AFD41E0841
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
www-Authenticate: NTLM
Content-Type: text/html;charset=utf-8
Content-Length: 954
Date: Fri, 10 Jun 2011 12:12:19 GMT
.......
.......
.......
Host: localhost:8084
Connection: keep-alive
Cache-Control: max-age=0
Authorization: NTLM NTLM TlRMTVNTUAABAAAAB7IIogkACQAzAAAACwALACgAAAAFAs4OAAAAD1JPTkctV0lOMkszV09SS0dST1VQ
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=154FDACF04E51C847E8B80AFD41E0841
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
www-Authenticate: NTLM
Content-Type: text/html;charset=utf-8
Content-Length: 954
Date: Fri, 10 Jun 2011 12:12:19 GMT
很容易看到第一次浏览器发送请求,server返回401并指出可以用NTLM认证协议,这时请注意,我们没有输入任何信息就看到了第二次请求,并且有如下一行:
Authorization: NTLM NTLM TlRMTVNTUAABAAAAB7IIogkACQAzAAAACwALACgAAAAFAs4OAAAAD1JPTkctV0lOMkszV09SS0dST1VQ
这是Chrome看到server支持NTLM认证自动发送的,与Server进行NTLM协商,可以通过Base64解码来查看具体信息是什么,很幸运的是wireshark帮我们解析了,见下图:
4E,54,4C,4D,53,53,50,00,01,00,00,00,07,B2,08,A2,09,00,09,00,33,00,00,00,0B,00,0B,00,28,00,00,00,
05,02,CE,0E,00,00,00,0F,52,4F,4E,47,2D,57,49,4E,32,4B,33,57,4F,52,4B,47,52,4F,55,50
1 |
Unicode协商 |
是否支持unicode字符串 |
2 |
OEM协商 |
是否支持OEM字符串,这里的OEM不是贴牌生产,是一种字符串表示形式,即字符串中的每一个字符用一个8bit的值表示,该值表示该机器code page上的一个字符,比如一般简体中文的windows的code page是936 |
3 |
Request Target |
告诉服务器在第二次NTLM协商的时候要将认证域名发过来 |
4 |
未定义 |
未定义 |
5 |
Negotiate Sign |
在已经通过认证的通信过程中,信息应该带上一个数字签名,以便验证信息的完整性 |
6 |
Negotiate Seal |
在已经通过认证的通信过程中,信息应该被加密,以保证信息的保密性 |
7 |
Negotiate Datagram Style |
是否使用Datagram认证,Datagram是一种NTLM协议使用的认证方式,主要意思是NTLM三次握手的过程中不使用一个连接,从而增加攻击难度 |
8 |
Negotiate Lan Manager Key |
LAN Manager session key 是不是用在上面第5、6位规定的通信方式,就是说这个key是不是用做签名和加密的密钥 |
9 |
Negotiate Netware |
未定义 |
10 |
Negotiate NTLM |
是否正在用NTLM认证,这一位当然是1了,不然还算是NTLM认证吗? |
11 |
未定义 |
未定义 |
12 |
未定义 |
未定义 |
13 |
Negotiate Domain Supplied |
第一次NTLM协商握手时是不是带上client机器所在的范围(这个范围有可能是workgroup,有可能是域名) |
14 |
Negotiate Workstation Supplied |
第一次NTLM协商握手时是不是带上client机器的机器名 |
15 |
Negotiate Local Call |
服务器向client说,你和我是一台机器,直接用本地的凭据吧,不要再协商了 |
16 |
Negotiate Always Sign |
服务器和通过认证的通信是不是总是签名的,好吧,这个我也不知道具体啥意思。。。虽然字面意思很简单 |
17 |
Target Type Domain |
服务器告诉client,client发过来的范围(workgroup或者域名)是不是个域名 |
18 |
Target Type Server |
第二次NTLM握手的时候,server告诉client,认证服务器是一台机器 |
19 |
Target Type Share |
第二次NTLM握手的时候,server告诉client,认证服务器是一个共享服务,用途不明。。。一般都是用第17位,这两个基本可以忽略了 |
20 |
Negotiate NTLM2 Key |
是否用NTLM2签名和加密scheme来保护认证通信 |
21 |
Request Init Response |
未定义 |
22 |
Request Accept Response |
未定义 |
23 |
Request Non-NT Session Key |
未定义 |
24 |
Negotiate Target Info |
第二次NTLM握手时,server告诉client,这次的消息体中是否包含target information, 这个target information包括域名,服务器名,DNS中域名和服务器名信息 |
25 |
未定义 |
未定义 |
26 |
未定义 |
未定义 |
27 |
未定义 |
未定义 |
28 |
未定义 |
未定义 |
29 |
未定义 |
未定义 |
30 |
Negotiate 128 |
是否支持128bit密钥的加密强度 |
31 |
Negotiate Key Exchange |
Client在第三次握手时会提供一个加密的session key,这个密钥会用来做通过认证的通信签名和加密 |
32 |
Negotiate 56 |
是否支持56bit密钥的加密强度(其实也就是DES啦,一般都支持的) |
开始8个字节当然还是(16进制):4E,54,4C,4D,53,53,50,00
接着标识这是第二次握手(16进制):02,00,00,00
来源:oschina
链接:https://my.oschina.net/u/116774/blog/23898