Get username using NT Challenge (NTLM)Tag(s): Security


Even if the application server do not support NTLM protocol, it is possible to use it to extract the Windows username. From the server, we ask the browser to identify the current user, and "by hand", we extract the response from the answer.

The browser client must support NT Challenge authentification mechanism (IE does).

This is a quick HACK to extract the username! There is no security into this. Beware...

[username.jsp]

<%@ page import="sun.misc.BASE64Encoder" %>
<p><h1>Network Windows USERNAME without any login (ie)</h1></p>
<%
String auth = request.getHeader("Authorization");
if (auth == null) {
        response.setStatus(response.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM");
        return;
}
if (auth.startsWith("NTLM ")) { 
        byte[] msg = 
           new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
        int off = 0, length, offset;
        String s;

        if (msg[8] == 1) { 
            off = 18;

            byte z = 0;
            byte[] msg1 =
                {(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S',
                (byte)'S', (byte)'P', z,
                (byte)2, z, z, z, z, z, z, z,
                (byte)40, z, z, z, (byte)1, (byte)130, z, z,
                z, (byte)2, (byte)2, (byte)2, z, z, z, z, // 
                z, z, z, z, z, z, z, z};
            // 
            response.setStatus(response.SC_UNAUTHORIZED);
            response.setHeader("WWW-Authenticate", "NTLM " 
               + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
            return;
        } 
        else if (msg[8] == 3) { 
                off = 30;
                length = msg[off+17]*256 + msg[off+16];
                offset = msg[off+19]*256 + msg[off+18];
                s = new String(msg, offset, length);
                //out.println(s + " ");
        } 
        else
                return;

        length = msg[off+1]*256 + msg[off];
        offset = msg[off+3]*256 + msg[off+2];
        s = new String(msg, offset, length);
        //out.println(s + " ");
        length = msg[off+9]*256 + msg[off+8];
        offset = msg[off+11]*256 + msg[off+10];
        s = new String(msg, offset, length);
        out.println("Hello  <span style='position:relative; width:190;" 
            + " height:10;filter:glow(Color=#009966,Strength=1)'>");
        out.println(s + "</SPAN>");
        }
%></BODY>

NOTES:
A comment from Weijun Ji : This technique only works if a user has its IE browser security setting set at middle/low (or if the server is trusted like in an intranet environment). With this setting, browser will grab login username automatically. If the security setting is at high, then a window will prompt user for input. At that time, whatever username the user put in will be passed to the "NTLM program". Since the user is not authenticated, you have no way to know if this user is a true user or not. In this way, any user can pretend to be anybody else as long as he has his security level set as high.

A comment from A. Santana : It didn't work for Firefox, so I did a silly workaround in the midtime. I removed everything is not a word or space... look: s.replaceAll("[^a-zA-Z\s]","");


You want to deeper into this subject, take a look at these sites :
http://www.innovation.ch/java/ntlm.html
http://free.tagish.net/jaas/index.jsp
http://www.luigidragone.com/networking/ntlm.html

Starting from jdk1.4.2, Sun provides support for NTLM, see http://java.sun.com/j2se/1.4.2/changes.html#networking

For a complete solution see JCIFS (for Tomcat and others) at http://jcifs.samba.org



blog comments powered by Disqus