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); 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) public static MessageTypeName GetMessageType(byte[] messageBytes)
{ {
return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8); return (MessageTypeName)LittleEndianConverter.ToUInt32(messageBytes, 8);

View file

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

View file

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