From 0d1f4ebfc59eebab959a83117ed59f8d4e115067 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Sep 2020 12:48:21 -0700 Subject: [PATCH 1/2] s3: rpc_server: Fix mem leak onto p->mem_ctx in error path of _netr_ServerPasswordSet2(). Signed-off-by: Jeremy Allison --- source3/rpc_server/netlogon/srv_netlog_nt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 2a2e2d0ac6e..0c068c6ef17 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1387,6 +1387,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, 516); } if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } -- 2.25.1 From f3dfb223508c546ef2038e72f7b7b024cab8f6c1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Sep 2020 12:53:50 -0700 Subject: [PATCH 2/2] s3: rpc: Netlogon. Back-port of Metze's netr_ServerPasswordSet2() protection. Signed-off-by: Jeremy Allison --- source3/rpc_server/netlogon/srv_netlog_nt.c | 93 +++++++++++++++++++-- 1 file changed, 87 insertions(+), 6 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 0c068c6ef17..f716413d538 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1345,9 +1345,13 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, { NTSTATUS status; struct netlogon_creds_CredentialState *creds = NULL; - DATA_BLOB plaintext; + DATA_BLOB plaintext = data_blob_null; + DATA_BLOB new_password = data_blob_null; + DATA_BLOB dec_blob = data_blob_null; + DATA_BLOB enc_blob = data_blob_null; struct samr_CryptPassword password_buf; struct _samr_Credentials_t cr = { CRED_TYPE_PLAIN_TEXT, {0}}; + bool ok; become_root(); status = netr_creds_server_step_check(p, p->mem_ctx, @@ -1391,17 +1395,94 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, return status; } - if (!decode_pw_buffer(p->mem_ctx, - password_buf.data, - (char**) &plaintext.data, - &plaintext.length, - CH_UTF16)) { + if (!extract_pw_from_buffer(p->mem_ctx, password_buf.data, &new_password)) { DEBUG(2,("_netr_ServerPasswordSet2: unable to extract password " "from a buffer. Rejecting auth request as a wrong password\n")); TALLOC_FREE(creds); return NT_STATUS_WRONG_PASSWORD; } + /* + * Make sure the length field was encrypted, + * otherwise we are under attack. + */ + if (new_password.length == r->in.new_password->length) { + DBG_WARNING("Length[%zu] field not encrypted\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + /* + * Make sure the CryptPassword buffer was encrypted, + * otherwise we are under attack. + */ + enc_blob = data_blob_const(r->in.new_password->data, 512); + dec_blob = data_blob_const(password_buf.data, 512); + if (data_blob_cmp(&dec_blob, &enc_blob) == 0) { + DBG_WARNING("CryptPassword buffer not encrypted Length[%zu]\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + /* + * We don't allow empty passwords for machine accounts. + */ + if (new_password.length < 2) { + DBG_WARNING("Empty password Length[%zu]\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + /* + * Check that the password part was actually encrypted, + * otherwise we are under attack. + */ + + memcpy(password_buf.data, r->in.new_password->data, 512); + SIVAL(password_buf.data, 512, new_password.length); + + if (!extract_pw_from_buffer(p->mem_ctx, password_buf.data, &enc_blob)) { + DBG_WARNING("Failed extract encrypted password Length[%zu]\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + if (data_blob_cmp(&new_password, &enc_blob) == 0) { + DBG_WARNING("Password buffer not encrypted Length[%zu]\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + /* Convert from UTF16 -> plaintext. */ + ok = convert_string_talloc(p->mem_ctx, + CH_UTF16, + CH_UNIX, + new_password.data, + new_password.length, + (void *)&plaintext.data, + &plaintext.length); + if (!ok) { + DBG_WARNING("unable to extract password from a buffer. " + "Rejecting auth request as a wrong password\n"); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + + /* + * We don't allow empty passwords for machine accounts. + */ + if (plaintext.length < 2) { + DBG_WARNING("Empty password Length[%zu]\n", + new_password.length); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + cr.creds.password = (const char*) plaintext.data; status = netr_set_machine_account_password(p->mem_ctx, p->session_info, -- 2.25.1