NTLM authentication in PHP – Now with NTLMv2 hash checking

A few years ago, I investigated NTLM and PHP and managed to write a simple PHP script that can retrieve the current windows username. However, it was only partly finished as it did not authenticate the user. Inspired by a recent comment, I’ve decided to revisit this problem and solve the authentication issue. For the better part of the afternoon, I wrestled with the NTLMv2 hash checking as detailed here.

It turns out that NT passwords are stored as a MD4 hash of the UTF16LE password string. So once we have this hash, we can begin verifying passwords. Obtaining this hash for a user is relatively easy with Samba, but seems to pose a challenge on Windows. In a later blog post I will detail how to integrate PHP authentication with Samba. For now, the code will assume you have already obtained a database of your users MD4 hashed passwords.

The crux of the NTLMv2 authentication involves using HMAC-MD5 on challenges and nonces using the MD4 hashed password as the key. The result is a 150 line source code that perform authentication on clients supporting NTLMv2. On the support NTLMv2, Internet Explorer supports it fine. Firefox on the other hand only has limited support for NTLMv2. In Firefox on Windows, if you have whitelisted your server with network.automatic-ntlm-auth.trusted-uris, Firefox will attempt to use Windows’ SSPI support (sys-ntlm) to perform single sign on. The SSPI module supports NTLMv2 fine. However, if you are using Firefox’s own cross platform NTLM module, you’re out of luck, it only supports the legacy NTLM and LM hashes. Perhaps it will support NTLMv2 in the future.

For Internet Explorer 8, intranet settings are now off by default, which means single sign on won’t automatically activate. To fix this, you should see a yellow bar prompting you whether to apply intranet settings.

The php ntlm authentication library is available here: PHP NTLM Github

To use it just put

include('ntlm.php');

function get_ntlm_user_hash($user) {
	$userdb = array('loune'=>'test', 'you'=>'gg', 'a'=> 'a');

	if (!isset($userdb[strtolower($user)]))
		return false;
	return mhash(MHASH_MD4, ntlm_utf8_to_utf16le($userdb[strtolower($user)]));
}

session_start();
$auth = ntlm_prompt("testwebsite", "testdomain", "mycomputer", "testdomain.local", "mycomputer.local", "get_ntlm_user_hash");

if ($auth['authenticated']) {
	print "You are authenticated as $auth[username] from $auth[domain]/$auth[workstation]";
}

You need to provide your own implementation of the callback function get_ntlm_user_hash($user) which should return the MD4/Unicode hashed password of the requested $user. You can get that by doing mhash(MHASH_MD4, ntlm_utf8_to_utf16le("password")). You also need session_start() as the script needs to persist challenge information across http requests.

Next time, I will blog about the best way to integrate it with Samba on Linux.

58 thoughts on “NTLM authentication in PHP – Now with NTLMv2 hash checking

  1. SH4RK

    Experiences:

    In soapUI it only works with this:
    $auth = ntlm_prompt(“DOMAIN”, “DOMAIN”, “SERVER”, “domain.com”, “server.domain.com”, “get_ntlm_user_hash”);

    Apache require
    RewriteRule .* – [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    in .htaccess

  2. Chetan

    Thanks!!
    I have been trying this code for NTML authentication.
    Each time it popups window but inspite of provide correct password its shows me
    “Authentication Required : Incorrect username or password.”
    error.

  3. Kushal

    Hey first of all i want to say thanks to you. Actually i need to integrated this library in my project. I have a windows server 2008 R2. I host my PHP code on this server. Now i want to know the about parameters detail which you pass in the function of ntml_prompt(). Please can you provide me detail So i can implement this into my project.

  4. gggeek

    I have the same question as Justin (I think):
    I want to run the php application in a unix server, which is normally not connected to the AD domain except via LDAP.
    The solution proposed by the author does not seem to work in my case, as the php app can not retrieve the password of the users, and hence it can not verify the ntlmv2 hashes it receives from the browsers.
    Does anyone have a solution for this?
    Am I doing it completely wrong?

  5. gggeek

    PS: I just found this tool, which seems like a possible candidate: ntlm_auth
    (manpage: http://www.manpagez.com/man/1/ntlm_auth/osx-10.5.php)
    – it needs to have samba installed
    – is is used by squid when integration with AD is desired
    – if samba is configured to be part of the AD domain, I hope that it “might” be used to validate the NTLM challenge response…

Leave a Reply

Your email address will not be published. Required fields are marked *