From 914b19c9511d55183d97d18ae6e0648e0766738d Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Thu, 24 Feb 2022 17:48:27 +0100 Subject: [PATCH 1/3] CVE-2022-2127: s3:winbind: Move big NTLMv2 blob checks to parent process The winbindd_dual_pam_auth_crap() function will be converted to a local RPC call handler and it won't receive a winbindd_cli_state struct. Move the checks accessing this struct to the parent. Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison (cherry picked from commit 74a511a8eab72cc82940738a1e20e63e12b81374) --- source3/winbindd/winbindd_pam.c | 12 ------------ source3/winbindd/winbindd_pam_auth_crap.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index e600ad27e54f..e77673bf1733 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2671,18 +2671,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, name_domain, name_user)); - if (state->request->data.auth_crap.lm_resp_len > sizeof(state->request->data.auth_crap.lm_resp) - || state->request->data.auth_crap.nt_resp_len > sizeof(state->request->data.auth_crap.nt_resp)) { - if (!(state->request->flags & WBFLAG_BIG_NTLMV2_BLOB) || - state->request->extra_len != state->request->data.auth_crap.nt_resp_len) { - DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", - state->request->data.auth_crap.lm_resp_len, - state->request->data.auth_crap.nt_resp_len)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - } - lm_resp = data_blob_talloc(state->mem_ctx, state->request->data.auth_crap.lm_resp, state->request->data.auth_crap.lm_resp_len); diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index a6f13806df97..fdb8120a6fe7 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -140,6 +140,18 @@ struct tevent_req *winbindd_pam_auth_crap_send( fstrcpy(request->data.auth_crap.workstation, lp_netbios_name()); } + if (request->data.auth_crap.lm_resp_len > sizeof(request->data.auth_crap.lm_resp) + || request->data.auth_crap.nt_resp_len > sizeof(request->data.auth_crap.nt_resp)) { + if (!(request->flags & WBFLAG_BIG_NTLMV2_BLOB) || + request->extra_len != request->data.auth_crap.nt_resp_len) { + DBG_ERR("Invalid password length %u/%u\n", + request->data.auth_crap.lm_resp_len, + request->data.auth_crap.nt_resp_len); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + } + subreq = wb_domain_request_send(state, global_event_context(), domain, request); if (tevent_req_nomem(subreq, req)) { -- 2.41.0 From c49caa7a8d4abf4185ec1a07ebfeb57d0bdc5754 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 20 May 2022 10:55:23 +0200 Subject: [PATCH 2/3] CVE-2022-2127: winbindd: Fix WINBINDD_PAM_AUTH_CRAP length checks With WBFLAG_BIG_NTLMV2_BLOB being set plus lm_resp_len too large you can crash winbind. We don't independently check lm_resp_len sufficiently. Discovered via Coverity ID 1504444 Out-of-bounds access BUG: https://bugzilla.samba.org/show_bug.cgi?id=15072 Signed-off-by: Volker Lendecke --- source3/winbindd/winbindd_pam_auth_crap.c | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index fdb8120a6fe7..651d54b01d33 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -42,6 +42,9 @@ struct tevent_req *winbindd_pam_auth_crap_send( struct winbindd_pam_auth_crap_state *state; struct winbindd_domain *domain; const char *auth_domain = NULL; + bool lmlength_ok = false; + bool ntlength_ok = false; + bool pwlength_ok = false; req = tevent_req_create(mem_ctx, &state, struct winbindd_pam_auth_crap_state); @@ -140,16 +143,24 @@ struct tevent_req *winbindd_pam_auth_crap_send( fstrcpy(request->data.auth_crap.workstation, lp_netbios_name()); } - if (request->data.auth_crap.lm_resp_len > sizeof(request->data.auth_crap.lm_resp) - || request->data.auth_crap.nt_resp_len > sizeof(request->data.auth_crap.nt_resp)) { - if (!(request->flags & WBFLAG_BIG_NTLMV2_BLOB) || - request->extra_len != request->data.auth_crap.nt_resp_len) { - DBG_ERR("Invalid password length %u/%u\n", - request->data.auth_crap.lm_resp_len, - request->data.auth_crap.nt_resp_len); - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - return tevent_req_post(req, ev); - } + lmlength_ok = (request->data.auth_crap.lm_resp_len <= + sizeof(request->data.auth_crap.lm_resp)); + + ntlength_ok = (request->data.auth_crap.nt_resp_len <= + sizeof(request->data.auth_crap.nt_resp)); + + ntlength_ok |= + ((request->flags & WBFLAG_BIG_NTLMV2_BLOB) && + (request->extra_len == request->data.auth_crap.nt_resp_len)); + + pwlength_ok = lmlength_ok && ntlength_ok; + + if (!pwlength_ok) { + DBG_ERR("Invalid password length %u/%u\n", + request->data.auth_crap.lm_resp_len, + request->data.auth_crap.nt_resp_len); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } subreq = wb_domain_request_send(state, global_event_context(), domain, -- 2.41.0 From c056d948646f5b7a4fbeb607872ee64fa2d1a26e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 16 Jun 2023 12:28:47 +0200 Subject: [PATCH 3/3] CVE-2022-2127: ntlm_auth: cap lanman response length value We already copy at most sizeof(request.data.auth_crap.lm_resp) bytes to the lm_resp buffer, but we don't cap the length indicator. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15072 Signed-off-by: Ralph Boehme --- source3/utils/ntlm_auth.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index ceb22e597f7b..8ce453f4b924 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -576,10 +576,14 @@ NTSTATUS contact_winbind_auth_crap(const char *username, memcpy(request.data.auth_crap.chal, challenge->data, MIN(challenge->length, 8)); if (lm_response && lm_response->length) { + size_t capped_lm_response_len = MIN( + lm_response->length, + sizeof(request.data.auth_crap.lm_resp)); + memcpy(request.data.auth_crap.lm_resp, lm_response->data, - MIN(lm_response->length, sizeof(request.data.auth_crap.lm_resp))); - request.data.auth_crap.lm_resp_len = lm_response->length; + capped_lm_response_len); + request.data.auth_crap.lm_resp_len = capped_lm_response_len; } if (nt_response && nt_response->length) { -- 2.41.0