From 530f0d1ee1c714b352cbac566821a7b9a45a8e61 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Nov 2015 09:31:35 +0100 Subject: [PATCH] CVE-2016-2110: libcli/auth: pass server_timestamp to SMBNTLMv2encrypt_hash() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=11644 Signed-off-by: Stefan Metzmacher Reviewed-by: Günther Deschner --- auth/credentials/credentials.h | 1 + auth/credentials/credentials_ntlm.c | 2 +- libcli/auth/proto.h | 1 + libcli/auth/smbencrypt.c | 36 +++++++++++++++++++++-------- source4/auth/ntlm/auth_util.c | 4 +++- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index f56a1213145..6c5c2c88f58 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -22,6 +22,7 @@ #ifndef __CREDENTIALS_H__ #define __CREDENTIALS_H__ +#include "../lib/util/time.h" #include "../lib/util/data_blob.h" #include "librpc/gen_ndr/misc.h" diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c index 5928305e821..c1d0c00de59 100644 --- a/auth/credentials/credentials_ntlm.c +++ b/auth/credentials/credentials_ntlm.c @@ -104,7 +104,7 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred user, domain, nt_hash->hash, &challenge, - &target_info, + server_timestamp, &target_info, &lm_response, &nt_response, NULL, &session_key)) { return NT_STATUS_NO_MEMORY; diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 0c319d32e7b..e7689e2cfc7 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -144,6 +144,7 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx, bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, const char *user, const char *domain, const uint8_t nt_hash[16], const DATA_BLOB *server_chal, + const NTTIME *server_timestamp, const DATA_BLOB *names_blob, DATA_BLOB *lm_response, DATA_BLOB *nt_response, DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) ; diff --git a/libcli/auth/smbencrypt.c b/libcli/auth/smbencrypt.c index ec819cd4db3..6edcaa3d08f 100644 --- a/libcli/auth/smbencrypt.c +++ b/libcli/auth/smbencrypt.c @@ -387,14 +387,13 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx, return names_blob; } -static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob) +static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, + NTTIME nttime, + const DATA_BLOB *names_blob) { uint8_t client_chal[8]; DATA_BLOB response = data_blob(NULL, 0); uint8_t long_date[8]; - NTTIME nttime; - - unix_to_nt_time(&nttime, time(NULL)); generate_random_buffer(client_chal, sizeof(client_chal)); @@ -417,6 +416,7 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx, const uint8_t ntlm_v2_hash[16], const DATA_BLOB *server_chal, + NTTIME nttime, const DATA_BLOB *names_blob) { uint8_t ntlmv2_response[16]; @@ -433,7 +433,7 @@ static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx, /* NTLMv2 */ /* generate some data to pass into the response function - including the hostname and domain name of the server */ - ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, names_blob); + ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, nttime, names_blob); /* Given that data, and the challenge from the server, generate a response */ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response); @@ -479,6 +479,7 @@ static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx, bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, const char *user, const char *domain, const uint8_t nt_hash[16], const DATA_BLOB *server_chal, + const NTTIME *server_timestamp, const DATA_BLOB *names_blob, DATA_BLOB *lm_response, DATA_BLOB *nt_response, DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) @@ -494,8 +495,19 @@ bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, } if (nt_response) { + const NTTIME *nttime = server_timestamp; + NTTIME _now = 0; + + if (nttime == NULL) { + struct timeval tv_now = timeval_current(); + _now = timeval_to_nttime(&tv_now); + nttime = &_now; + } + *nt_response = NTLMv2_generate_response(mem_ctx, - ntlm_v2_hash, server_chal, + ntlm_v2_hash, + server_chal, + *nttime, names_blob); if (user_session_key) { *user_session_key = data_blob_talloc(mem_ctx, NULL, 16); @@ -509,8 +521,13 @@ bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, /* LMv2 */ if (lm_response) { - *lm_response = LMv2_generate_response(mem_ctx, - ntlm_v2_hash, server_chal); + if (server_timestamp != NULL) { + *lm_response = data_blob_talloc_zero(mem_ctx, 24); + } else { + *lm_response = LMv2_generate_response(mem_ctx, + ntlm_v2_hash, + server_chal); + } if (lm_session_key) { *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16); @@ -535,7 +552,8 @@ bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx, E_md4hash(password, nt_hash); return SMBNTLMv2encrypt_hash(mem_ctx, - user, domain, nt_hash, server_chal, names_blob, + user, domain, nt_hash, + server_chal, NULL, names_blob, lm_response, nt_response, lm_session_key, user_session_key); } diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c index 16977fa00a3..3e5a0da59c2 100644 --- a/source4/auth/ntlm/auth_util.c +++ b/source4/auth/ntlm/auth_util.c @@ -350,7 +350,9 @@ NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth4_context *auth_conte if (!SMBNTLMv2encrypt_hash(user_info_temp, user_info_in->client.account_name, user_info_in->client.domain_name, - user_info_in->password.hash.nt->hash, &chall_blob, + user_info_in->password.hash.nt->hash, + &chall_blob, + NULL, /* server_timestamp */ &names_blob, &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { -- 2.47.2