IsNTLMv1ExtendedSecurity and IsNTLMv2NTResponse methods added to AuthenticationMessageUtils

This commit is contained in:
Tal Aloni 2017-01-19 22:05:08 +02:00
parent f6feaced77
commit 6772c0c33e
4 changed files with 65 additions and 25 deletions

View file

@ -58,6 +58,36 @@ namespace SMBLibrary.Authentication
return (signature == AuthenticateMessage.ValidSignature);
}
/// <summary>
/// If NTLM v1 Extended Security is used, LMResponse starts with 8-byte challenge, followed by 16 bytes of padding (set to zero).
/// </summary>
/// <remarks>
/// LMResponse is 24 bytes for NTLM v1, NTLM v1 Extended Security and NTLM v2.
/// </remarks>
public static bool IsNTLMv1ExtendedSecurity(byte[] lmResponse)
{
if (lmResponse.Length == 24)
{
if (ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 0, 8), new byte[8]))
{
// Challenge not present, cannot be NTLM v1 Extended Security
return false;
}
return ByteUtils.AreByteArraysEqual(ByteReader.ReadBytes(lmResponse, 8, 16), new byte[16]);
}
return false;
}
/// <remarks>
/// NTLM v1 / NTLM v1 Extended Security NTResponse is 24 bytes.
/// </remarks>
public static bool IsNTLMv2NTResponse(byte[] ntResponse)
{
return (ntResponse.Length >= 48 &&
ntResponse[16] == NTLMv2ClientChallenge.StructureVersion &&
ntResponse[17] == NTLMv2ClientChallenge.StructureVersion);
}
public static MessageTypeName GetMessageType(byte[] messageBytes)
{
return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8);

View file

@ -96,7 +96,7 @@ namespace SMBLibrary.Server
return this[index];
}
if (ntResponse.Length >= 48)
if (AuthenticationMessageUtils.IsNTLMv2NTResponse(ntResponse))
{
byte[] clientNTProof = ByteReader.ReadBytes(ntResponse, 0, 16);
byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntResponse, 16, ntResponse.Length - 16);
@ -161,8 +161,12 @@ namespace SMBLibrary.Server
User user;
if ((message.NegotiateFlags & NegotiateFlags.ExtendedSecurity) > 0)
{
user = AuthenticateV1Extended(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
if (user == null)
if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(message.LmChallengeResponse))
{
// NTLM v1 Extended Security:
user = AuthenticateV1Extended(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
}
else
{
// NTLM v2:
user = AuthenticateV2(message.DomainName, message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);

View file

@ -183,7 +183,8 @@ namespace SMBLibrary.Server.SMB1
NegotiateFlags.Version |
NegotiateFlags.Use128BitEncryption |
NegotiateFlags.Use56BitEncryption;
if (ntChallengeResponse.Length >= 48)
if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(lmChallengeResponse) ||
AuthenticationMessageUtils.IsNTLMv2NTResponse(ntChallengeResponse))
{
authenticateMessage.NegotiateFlags |= NegotiateFlags.ExtendedSecurity;
}

View file

@ -82,32 +82,37 @@ namespace SMBLibrary.Server.Win32
if ((message.NegotiateFlags & NegotiateFlags.ExtendedSecurity) > 0)
{
// NTLM v1 extended security:
byte[] clientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 0, 8);
byte[] emptyPasswordNTLMv1Response = NTAuthentication.ComputeNTLMv1ExtendedSecurityResponse(m_serverChallenge, clientChallenge, String.Empty);
if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv1Response, message.NtChallengeResponse))
if (AuthenticationMessageUtils.IsNTLMv1ExtendedSecurity(message.LmChallengeResponse))
{
return true;
}
// NTLM v2:
byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 16, 8);
byte[] emptyPasswordLMv2Response = NTAuthentication.ComputeLMv2Response(m_serverChallenge, _LMv2ClientChallenge, String.Empty, message.UserName, message.DomainName);
if (ByteUtils.AreByteArraysEqual(emptyPasswordLMv2Response, message.LmChallengeResponse))
{
return true;
}
if (message.NtChallengeResponse.Length >= 48)
{
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))
// NTLM v1 extended security:
byte[] clientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 0, 8);
byte[] emptyPasswordNTLMv1Response = NTAuthentication.ComputeNTLMv1ExtendedSecurityResponse(m_serverChallenge, clientChallenge, String.Empty);
if (ByteUtils.AreByteArraysEqual(emptyPasswordNTLMv1Response, message.NtChallengeResponse))
{
return true;
}
}
else
{
// NTLM v2:
byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(message.LmChallengeResponse, 16, 8);
byte[] emptyPasswordLMv2Response = NTAuthentication.ComputeLMv2Response(m_serverChallenge, _LMv2ClientChallenge, String.Empty, message.UserName, message.DomainName);
if (ByteUtils.AreByteArraysEqual(emptyPasswordLMv2Response, message.LmChallengeResponse))
{
return true;
}
if (AuthenticationMessageUtils.IsNTLMv2NTResponse(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;
}
}
}
}
else
{