229 lines
13 KiB
Diff
229 lines
13 KiB
Diff
From eb4123b5caed6c5cbfe8ef050f198e2d5a03f8b7 Mon Sep 17 00:00:00 2001
|
|
From: Alexander Bokovoy <ab@samba.org>
|
|
Date: Wed, 11 Nov 2020 14:42:55 +0200
|
|
Subject: [PATCH 032/266] CVE-2020-25717 auth_sam: use pdb_get_domain_info to
|
|
look up DNS forest information
|
|
|
|
When Samba is used as a part of FreeIPA domain controller, Windows
|
|
clients for a trusted AD forest may try to authenticate (perform logon
|
|
operation) as a REALM\name user account.
|
|
|
|
Fix auth_sam plugins to accept DNS forest name if we are running on a DC
|
|
with PASSDB module providing domain information (e.g. pdb_get_domain_info()
|
|
returning non-NULL structure). Right now, only FreeIPA or Samba AD DC
|
|
PASSDB backends return this information but Samba AD DC configuration is
|
|
explicitly ignored by the two auth_sam (strict and netlogon3) modules.
|
|
|
|
Detailed logs below:
|
|
|
|
[2020/11/11 09:23:53.281296, 1, pid=42677, effective(65534, 65534), real(65534, 0), class=rpc_parse] ../../librpc/ndr/ndr.c:482(ndr_print_function_debug)
|
|
netr_LogonSamLogonWithFlags: struct netr_LogonSamLogonWithFlags
|
|
in: struct netr_LogonSamLogonWithFlags
|
|
server_name : *
|
|
server_name : '\\master.ipa.test'
|
|
computer_name : *
|
|
computer_name : 'AD1'
|
|
credential : *
|
|
credential: struct netr_Authenticator
|
|
cred: struct netr_Credential
|
|
data : 529f4b087c5f6546
|
|
timestamp : Wed Nov 11 09:23:55 AM 2020 UTC
|
|
return_authenticator : *
|
|
return_authenticator: struct netr_Authenticator
|
|
cred: struct netr_Credential
|
|
data : 204f28f622010000
|
|
timestamp : Fri May 2 06:37:50 AM 1986 UTC
|
|
logon_level : NetlogonNetworkTransitiveInformation (6)
|
|
logon : *
|
|
logon : union netr_LogonLevel(case 6)
|
|
network : *
|
|
network: struct netr_NetworkInfo
|
|
identity_info: struct netr_IdentityInfo
|
|
domain_name: struct lsa_String
|
|
length : 0x0010 (16)
|
|
size : 0x01fe (510)
|
|
string : *
|
|
string : 'IPA.TEST'
|
|
parameter_control : 0x00002ae0 (10976)
|
|
0: MSV1_0_CLEARTEXT_PASSWORD_ALLOWED
|
|
0: MSV1_0_UPDATE_LOGON_STATISTICS
|
|
0: MSV1_0_RETURN_USER_PARAMETERS
|
|
0: MSV1_0_DONT_TRY_GUEST_ACCOUNT
|
|
1: MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT
|
|
1: MSV1_0_RETURN_PASSWORD_EXPIRY
|
|
1: MSV1_0_USE_CLIENT_CHALLENGE
|
|
0: MSV1_0_TRY_GUEST_ACCOUNT_ONLY
|
|
1: MSV1_0_RETURN_PROFILE_PATH
|
|
0: MSV1_0_TRY_SPECIFIED_DOMAIN_ONLY
|
|
1: MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
|
|
0: MSV1_0_DISABLE_PERSONAL_FALLBACK
|
|
1: MSV1_0_ALLOW_FORCE_GUEST
|
|
0: MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED
|
|
0: MSV1_0_USE_DOMAIN_FOR_ROUTING_ONLY
|
|
0: MSV1_0_ALLOW_MSVCHAPV2
|
|
0: MSV1_0_S4U2SELF
|
|
0: MSV1_0_CHECK_LOGONHOURS_FOR_S4U
|
|
0: MSV1_0_SUBAUTHENTICATION_DLL_EX
|
|
logon_id : 0x0000000000884ef2 (8933106)
|
|
account_name: struct lsa_String
|
|
length : 0x000e (14)
|
|
size : 0x000e (14)
|
|
string : *
|
|
string : 'idmuser'
|
|
workstation: struct lsa_String
|
|
length : 0x0000 (0)
|
|
size : 0x0000 (0)
|
|
string : *
|
|
string : ''
|
|
challenge : 417207867bd33c74
|
|
nt: struct netr_ChallengeResponse
|
|
length : 0x00c0 (192)
|
|
size : 0x00c0 (192)
|
|
data : *
|
|
data: ARRAY(192)
|
|
[0000] A5 24 62 6E 31 DF 69 66 9E DC 54 D6 63 4C D6 2F .$bn1.if ..T.cL./
|
|
[0010] 01 01 00 00 00 00 00 00 50 37 D7 60 0C B8 D6 01 ........ P7.`....
|
|
[0020] 15 1B 38 4F 47 95 4D 62 00 00 00 00 02 00 0E 00 ..8OG.Mb ........
|
|
[0030] 57 00 49 00 4E 00 32 00 30 00 31 00 36 00 01 00 W.I.N.2. 0.1.6...
|
|
[0040] 06 00 41 00 44 00 31 00 04 00 18 00 77 00 69 00 ..A.D.1. ....w.i.
|
|
[0050] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e.
|
|
[0060] 73 00 74 00 03 00 20 00 61 00 64 00 31 00 2E 00 s.t... . a.d.1...
|
|
[0070] 77 00 69 00 6E 00 32 00 30 00 31 00 36 00 2E 00 w.i.n.2. 0.1.6...
|
|
[0080] 74 00 65 00 73 00 74 00 05 00 18 00 77 00 69 00 t.e.s.t. ....w.i.
|
|
[0090] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e.
|
|
[00A0] 73 00 74 00 07 00 08 00 50 37 D7 60 0C B8 D6 01 s.t..... P7.`....
|
|
[00B0] 06 00 04 00 02 00 00 00 00 00 00 00 00 00 00 00 ........ ........
|
|
lm: struct netr_ChallengeResponse
|
|
length : 0x0018 (24)
|
|
size : 0x0018 (24)
|
|
data : *
|
|
data : 000000000000000000000000000000000000000000000000
|
|
validation_level : 0x0006 (6)
|
|
flags : *
|
|
flags : 0x00000000 (0)
|
|
0: NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT
|
|
0: NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP
|
|
0: NETLOGON_SAMLOGON_FLAG_RODC_TO_OTHER_DOMAIN
|
|
0: NETLOGON_SAMLOGON_FLAG_RODC_NTLM_REQUEST
|
|
|
|
In such case checks for a workgroup name will not match the DNS forest
|
|
name used in the username specification:
|
|
|
|
[2020/11/11 09:23:53.283055, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:200(auth_check_ntlm_password)
|
|
check_ntlm_password: Checking password for unmapped user [IPA.TEST]\[idmuser]@[] with the new password interface
|
|
[2020/11/11 09:23:53.283073, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:203(auth_check_ntlm_password)
|
|
check_ntlm_password: mapped user is: [IPA.TEST]\[idmuser]@[]
|
|
[2020/11/11 09:23:53.283082, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:213(auth_check_ntlm_password)
|
|
check_ntlm_password: auth_context challenge created by fixed
|
|
[2020/11/11 09:23:53.283091, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:216(auth_check_ntlm_password)
|
|
challenge is:
|
|
[2020/11/11 09:23:53.283099, 5, pid=42677, effective(65534, 65534), real(65534, 0)] ../../lib/util/util.c:678(dump_data)
|
|
[0000] 41 72 07 86 7B D3 3C 74 Ar..{.<t
|
|
[2020/11/11 09:23:53.283113, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth_sam.c:209(auth_sam_netlogon3_auth)
|
|
auth_sam_netlogon3_auth: Check auth for: [IPA.TEST]\[idmuser]
|
|
[2020/11/11 09:23:53.283123, 5, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth_sam.c:234(auth_sam_netlogon3_auth)
|
|
auth_sam_netlogon3_auth: IPA.TEST is not our domain name (DC for IPA)
|
|
[2020/11/11 09:23:53.283131, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:249(auth_check_ntlm_password)
|
|
auth_check_ntlm_password: sam_netlogon3 had nothing to say
|
|
|
|
and overall authentication attempt will fail: auth_winbind will complain
|
|
that this domain is not a trusted one and refuse operating on it:
|
|
|
|
[2020/11/11 09:23:53.283784, 10, pid=42663, effective(0, 0), real(0, 0), class=winbind] ../../source3/winbindd/winbindd.c:742(process_request_send)
|
|
process_request_send: process_request: Handling async request smbd(42677):PAM_AUTH_CRAP
|
|
[2020/11/11 09:23:53.283796, 3, pid=42663, effective(0, 0), real(0, 0), class=winbind] ../../source3/winbindd/winbindd_pam_auth_crap.c:110(winbindd_pam_auth_crap_send)
|
|
[42677]: pam auth crap domain: [IPA.TEST] user: idmuser
|
|
[2020/11/11 09:23:53.283810, 3, pid=42663, effective(0, 0), real(0, 0), class=winbind] ../../source3/winbindd/winbindd_pam.c:409(find_auth_domain)
|
|
Authentication for domain [IPA.TEST] refused as it is not a trusted domain
|
|
[2020/11/11 09:23:53.283825, 10, pid=42663, effective(0, 0), real(0, 0), class=winbind] ../../source3/winbindd/winbindd.c:810(process_request_done)
|
|
process_request_done: [smbd(42677):PAM_AUTH_CRAP]: NT_STATUS_NO_SUCH_USER
|
|
[2020/11/11 09:23:53.283844, 10, pid=42663, effective(0, 0), real(0, 0), class=winbind] ../../source3/winbindd/winbindd.c:855(process_request_written)
|
|
process_request_written: [smbd(42677):PAM_AUTH_CRAP]: delivered response to client
|
|
|
|
Signed-off-by: Alexander Bokovoy <ab@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556
|
|
|
|
(cherry picked from commit 2a8b672652dcbcf55ec59be537773d76f0f14d0a)
|
|
---
|
|
source3/auth/auth_sam.c | 45 +++++++++++++++++++++++++++++++++++++----
|
|
1 file changed, 41 insertions(+), 4 deletions(-)
|
|
|
|
Conflict:NA
|
|
Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=eb4123b5caed6c5cbfe8ef050f198e2d5a03f8b7
|
|
|
|
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
|
|
index 3c12f959faf..e8e0d543f8c 100644
|
|
--- a/source3/auth/auth_sam.c
|
|
+++ b/source3/auth/auth_sam.c
|
|
@@ -22,6 +22,7 @@
|
|
|
|
#include "includes.h"
|
|
#include "auth.h"
|
|
+#include "passdb.h"
|
|
|
|
#undef DBGC_CLASS
|
|
#define DBGC_CLASS DBGC_AUTH
|
|
@@ -142,10 +143,28 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
|
|
break;
|
|
case ROLE_DOMAIN_PDC:
|
|
case ROLE_DOMAIN_BDC:
|
|
- if ( !is_local_name && !is_my_domain ) {
|
|
- DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
|
|
- effective_domain));
|
|
- return NT_STATUS_NOT_IMPLEMENTED;
|
|
+ if (!is_local_name && !is_my_domain) {
|
|
+ /* If we are running on a DC that has PASSDB module with domain
|
|
+ * information, check if DNS forest name is matching the domain
|
|
+ * name. This is the case of FreeIPA domain controller when
|
|
+ * trusted AD DCs attempt to authenticate FreeIPA users using
|
|
+ * the forest root domain (which is the only domain in FreeIPA).
|
|
+ */
|
|
+ struct pdb_domain_info *dom_info = NULL;
|
|
+
|
|
+ dom_info = pdb_get_domain_info(mem_ctx);
|
|
+ if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
|
|
+ is_my_domain = strequal(user_info->mapped.domain_name,
|
|
+ dom_info->dns_forest);
|
|
+ }
|
|
+
|
|
+ TALLOC_FREE(dom_info);
|
|
+ if (!is_my_domain) {
|
|
+ DEBUG(6,("check_samstrict_security: %s is not one "
|
|
+ "of my local names or domain name (DC)\n",
|
|
+ effective_domain));
|
|
+ return NT_STATUS_NOT_IMPLEMENTED;
|
|
+ }
|
|
}
|
|
|
|
break;
|
|
@@ -230,6 +249,24 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
|
|
}
|
|
|
|
is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup());
|
|
+ if (!is_my_domain) {
|
|
+ /* If we are running on a DC that has PASSDB module with domain
|
|
+ * information, check if DNS forest name is matching the domain
|
|
+ * name. This is the case of FreeIPA domain controller when
|
|
+ * trusted AD DCs attempt to authenticate FreeIPA users using
|
|
+ * the forest root domain (which is the only domain in FreeIPA).
|
|
+ */
|
|
+ struct pdb_domain_info *dom_info = NULL;
|
|
+ dom_info = pdb_get_domain_info(mem_ctx);
|
|
+
|
|
+ if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
|
|
+ is_my_domain = strequal(user_info->mapped.domain_name,
|
|
+ dom_info->dns_forest);
|
|
+ }
|
|
+
|
|
+ TALLOC_FREE(dom_info);
|
|
+ }
|
|
+
|
|
if (!is_my_domain) {
|
|
DBG_INFO("%s is not our domain name (DC for %s)\n",
|
|
effective_domain, lp_workgroup());
|
|
--
|
|
2.23.0
|
|
|