NTAuthentication: Will use ComputeNTLMv2Proof (instead of ComputeNTLMv2Response) to improve compatibility with clients

Xubuntu 16.04 will not add the necessary padding to
ClientChallengeStructure
This commit is contained in:
Tal Aloni 2017-01-19 00:44:50 +02:00
parent d66208cfb8
commit 4bd6bbd882
4 changed files with 19 additions and 20 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -48,18 +48,17 @@ namespace SMBLibrary.Authentication
}
/// <summary>
/// [MS-NLMP] page 60
/// 'temp' is the same as ClientChallengeStructure with 4 zero bytes padding
/// [MS-NLMP] https://msdn.microsoft.com/en-us/library/cc236700.aspx
/// </summary>
public static byte[] ComputeNTLMv2Response(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain)
/// <param name="clientChallengeStructurePadded">ClientChallengeStructure with 4 zero bytes padding, a.k.a. temp</param>
public static byte[] ComputeNTLMv2Proof(byte[] serverChallenge, byte[] clientChallengeStructurePadded, string password, string user, string domain)
{
byte[] key = NTOWFv2(password, user, domain);
byte[] temp = clientChallengeStructurePadded;
HMACMD5 hmac = new HMACMD5(key);
byte[] _NTProof = hmac.ComputeHash(ByteUtils.Concatenate(serverChallenge, temp), 0, serverChallenge.Length + temp.Length);
return ByteUtils.Concatenate(_NTProof, temp);
return _NTProof;
}
/// <summary>

View file

@ -98,11 +98,11 @@ namespace SMBLibrary.Server
if (ntlmResponse.Length > 24)
{
NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(ntlmResponse, 16);
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
byte[] expectedNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth);
byte[] clientNTProof = ByteReader.ReadBytes(ntlmResponse, 0, 16);
byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntlmResponse, 16, ntlmResponse.Length - 16);
byte[] expectedNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth);
if (ByteUtils.AreByteArraysEqual(expectedNTLMv2Response, ntlmResponse))
if (ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof))
{
return this[index];
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -76,11 +76,10 @@ namespace SMBLibrary
DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server");
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
byte[] response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
byte[] expectedHash = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c };
byte[] expected = ByteUtils.Concatenate(expectedHash, clientChallengeStructurePadded);
bool success = ByteUtils.AreByteArraysEqual(response, expected);
byte[] expectedNTProof = new byte[] { 0x68, 0xcd, 0x0a, 0xb8, 0x51, 0xe5, 0x1c, 0x96, 0xaa, 0xbc, 0x92, 0x7b, 0xeb, 0xef, 0x6a, 0x1c };
bool success = ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof);
return success;
}
@ -135,6 +134,7 @@ namespace SMBLibrary
DateTime time = DateTime.FromFileTimeUtc(0); // same as new byte[8]
NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(time, clientChallenge, "Domain", "Server");
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
byte[] clientNTProof = NTAuthentication.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
AuthenticateMessage message = new AuthenticateMessage();
message.EncryptedRandomSessionKey = sessionKey;
@ -144,7 +144,7 @@ namespace SMBLibrary
message.WorkStation = "COMPUTER";
message.UserName = "User";
message.LmChallengeResponse = NTAuthentication.ComputeLMv2Response(serverChallenge, clientChallenge, "Password", "User", "Domain");
message.NtChallengeResponse = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, "Password", "User", "Domain");
message.NtChallengeResponse = ByteUtils.Concatenate(clientNTProof, clientChallengeStructurePadded);
byte[] messageBytes = message.GetBytes();
// The payload entries may be distributed differently so we use cmp.GetBytes()

View file

@ -100,10 +100,10 @@ namespace SMBLibrary.Server.Win32
if (message.NtChallengeResponse.Length > 24)
{
NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(message.NtChallengeResponse, 16);
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
byte[] emptyPasswordNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv2Response, message.NtChallengeResponse))
byte[] clientNTProof = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(message.NtChallengeResponse, 16, message.NtChallengeResponse.Length - 16);
byte[] emptyPasswordNTProof = NTAuthentication.ComputeNTLMv2Proof(m_serverChallenge, clientChallengeStructurePadded, String.Empty, message.UserName, message.DomainName);
if (ByteUtils.AreByteArraysEqual(clientNTProof, emptyPasswordNTProof))
{
return true;
}