From 85e49aa601fa4c7b582704878fdae6b0e1a4298b Mon Sep 17 00:00:00 2001 From: Martin Haimberger Date: Wed, 15 Apr 2020 11:43:45 +0200 Subject: [PATCH] fix: server side ntlmv2 implementation - in the case no mic was present, but the user was found, the enterd password was ignored and the user authenticated --- winpr/libwinpr/sspi/NTLM/ntlm.h | 1 + winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 11 +++++----- winpr/libwinpr/sspi/NTLM/ntlm_message.c | 28 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index 48bd33cc9..c6216ea41 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -261,6 +261,7 @@ struct _NTLM_CONTEXT SecBuffer NtChallengeResponse; SecBuffer LmChallengeResponse; NTLMv2_RESPONSE NTLMv2Response; + BYTE NtProofString[16]; BYTE Timestamp[8]; BYTE ChallengeTimestamp[8]; BYTE ServerChallenge[8]; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index 6d2945498..173accecf 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -415,7 +415,6 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; - BYTE nt_proof_str[WINPR_MD5_DIGEST_LENGTH]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; @@ -454,8 +453,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); winpr_HMAC(WINPR_MD_MD5, (BYTE*)context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, - (BYTE*)ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, (BYTE*)nt_proof_str, - WINPR_MD5_DIGEST_LENGTH); + (BYTE*)ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, + (BYTE*)context->NtProofString, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -463,12 +462,12 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) return -1; blob = (BYTE*)context->NtChallengeResponse.pvBuffer; - CopyMemory(blob, nt_proof_str, 16); + CopyMemory(blob, context->NtProofString, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (BYTE*)context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, - (BYTE*)nt_proof_str, WINPR_MD5_DIGEST_LENGTH, (BYTE*)context->SessionBaseKey, - WINPR_MD5_DIGEST_LENGTH); + (BYTE*)context->NtProofString, WINPR_MD5_DIGEST_LENGTH, + (BYTE*)context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c index 80eb4ff22..af10bc8f8 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -1180,6 +1180,34 @@ SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context) return SEC_E_MESSAGE_ALTERED; } } + else + { + /* no mic message was present + + https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/f9e6fbc4-a953-4f24-b229-ccdcc213b9ec + the mic is optional, as not supported in Windows NT, Windows 2000, Windows XP, and + Windows Server 2003 and, as it seems, in the NTLMv2 implementation of Qt5. + + now check the NtProofString, to detect if the entered client password matches the + expected password. + */ + +#ifdef WITH_DEBUG_NTLM + WLog_DBG(TAG, "No MIC present, using NtProofString for verification."); +#endif + + if (memcmp(context->NTLMv2Response.Response, context->NtProofString, 16) != 0) + { + WLog_ERR(TAG, "NtProofString verification failed!"); +#ifdef WITH_DEBUG_NTLM + WLog_ERR(TAG, "Expected NtProofString:"); + winpr_HexDump(TAG, WLOG_ERROR, context->NtProofString, 16); + WLog_ERR(TAG, "Actual NtProofString:"); + winpr_HexDump(TAG, WLOG_ERROR, context->NTLMv2Response.Response, 16); +#endif + return SEC_E_LOGON_DENIED; + } + } /* Generate signing keys */ ntlm_generate_client_signing_key(context);