php-ntlm
php-ntlm copied to clipboard
Simple NTLMv2 without hash/auth/verify
I am a longtime user of your original NTLM script in my workflow application. I just need to pull the Windows username from a Type 3 response, and I don't care about secure authentication, hashes, etc.
I am hearing from coworkers that our Win10 upgrade will only allow NTLMv2 in an HTTP session, and that your original script won't work. I don't see in the ntlm.html protocol document how the Type 3 message in HTTP auth differs from v1 to v2. I have read elsewhere that the Type 3 is encrypted with the client's password hash (unsure on this).
Can I simply extract the username in v2 without using your setuid binary or otherwise involving an Active Directory server?
Many, many thanks for any information you might provide.
I pulled your Type 2 message from the new code and put it in the old version. It works on Win7.
However, under Win10, it fails completely with "WWW-Authenticate: NTLM" - I do get a Type 1 message with "WWW-Authenticate: Negotiate" but it fails after I send any Type 2.
Yes you should be able to use the v2 code for getting the username without verifying the password. I haven't got Win 10, so I can't test and see what's wrong with it. It's been a while since I touched the script but I suspect win 10 might be using a new hashing method that the script doesn't support. When I get a bit of time, I might install win 10 on a VM and test it out.
My webapps were tested in Win10 with your original code several months ago, and everything worked. Then I got a helpful message that "There is a policy setting for minimum session security for NTLM SSP based clients, and [my app] doesn’t meet the NTLMv2 session security requirement... [Our] advice would be to either ensure it’s using NTLMv2 and compatible with security requirements or upgrade to SPNEGO, which is a more current protocol."
It is pretty annoying that PHP still uses HTTP/1.0 in plenty of places, but I'm getting the NTLM rug ripped out from underneath me.
I've written a replacement that forces the user to provide their NT login and password, then checks it as an LDAP login against the local domain controller. This is inconvenient because I need TLS everywhere now. Here is that basic code, in case anybody finds it useful:
# cat /var/www/html/ntlm.php
<?php
if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') // stunnel
die('App must now be accessed over https/TLS.');
if(!session_start()) die('App cookie error.');
if(!isset($_SESSION['NTLM_user']))
{
error_reporting(0);
function auth () {
header('WWW-Authenticate: Basic realm="MyApp"');
header('HTTP/1.0 401 Unauthorized');
die('Your windows account and password are now required.');
}
if(!isset($_SERVER['PHP_AUTH_USER'])) auth();
if(!$ds = ldap_connect('127.0.0.1', 12485)) auth();
if(!$r = ldap_bind($ds,
$_SERVER['PHP_AUTH_USER'] . '@mydomain.com',
$_SERVER['PHP_AUTH_PW'])) auth();
$_SESSION['NTLM_user'] = strtoupper($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
ldap_unbind($ds);
}
$NTLM_user = $_SESSION['NTLM_user'];
?>
I'm using stunnel on all sides (the verify options are really flexible, and it can chroot() the TLS engine). Here is the stunnel conf that goes to the domain controller:
# cat /etc/stunnel/ms-ldap-ssl.conf
sslVersion = TLSv1.2
FIPS = no
debug = debug
options = NO_SSLv2
options = NO_SSLv3
curve = secp521r1
options = SINGLE_DH_USE
options = SINGLE_ECDH_USE
options = CIPHER_SERVER_PREFERENCE
; UNIX-only high-security isolation, not available on MS-Windows
setuid = nobody
setgid = nobody
chroot = /var/empty
; Under inetd mode, no accept rules or service definitions, just a connect.
client = yes
connect = domaincontroller.mydomain.com:636
verify = 2
CAfile = /etc/stunnel/mydomain.pem
; best ciphers https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ciphers=ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
Hi @loune , I'm using your original NTLM Script like orachas, to get the Windows username. And it worked fine, thanks! Now Win10 is coming, and it doesn't work. Did you find a way to get only the username from a Win10 Client?