samba/backport-0002-CVE-2020-25722-dsdb-Restrict-the-setting-of-privileg.patch
haochenstar 8378df4821 fix CVE-2020-25717,CVE-2020-25718,CVE-2020-25719,CVE-2020-25721,CVE-2020-25722,CVE-2016-2124,CVE-2021-3738
(cherry picked from commit aee849c6c0708056f62f6445e3b5274d1cec6408)
2022-01-19 11:41:35 +08:00

236 lines
7.4 KiB
Diff

From 448585950bda2c1daab8ffeb3971870ed0416634 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
Date: Fri, 13 Aug 2021 17:42:23 +1200
Subject: [PATCH 057/266] CVE-2020-25722 dsdb: Restrict the setting of
privileged attributes during LDAP add/modify
The remaining failures in the priv_attrs (not the strict one) test are
due to missing objectclass constraints on the administrator which should
be addressed, but are not a security issue.
A better test for confirming constraints between objectclass and
userAccountControl UF_NORMAL_ACCONT/UF_WORKSTATION_TRUST values would
be user_account_control.py.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14703
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14778
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14775
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Conflict:remove test
Reference:https://gitlab.com/samba-team/samba/-/commit/448585950bda2c1daab8ffeb3971870ed0416634
---
source4/dsdb/samdb/ldb_modules/samldb.c | 148 +++++++++++++++++++++---
1 files changed, 129 insertions(+), 19 deletions(-)
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 4da8564c77a..cb5fda324a4 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1976,6 +1976,29 @@ static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac,
return ret;
}
+static int samldb_get_domain_secdesc(struct samldb_ctx *ac,
+ struct security_descriptor **domain_sd)
+{
+ const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL};
+ struct ldb_result *res;
+ struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
+ int ret = dsdb_module_search_dn(ac->module, ac, &res,
+ domain_dn,
+ sd_attrs,
+ DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (res->count != 1) {
+ return ldb_module_operr(ac->module);
+ }
+
+ return dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module),
+ ac, res->msgs[0], domain_sd);
+
+}
+
/**
* Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured
*
@@ -1987,12 +2010,8 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
{
int i, ret = 0;
bool need_acl_check = false;
- struct ldb_result *res;
- const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL};
struct security_token *user_token;
struct security_descriptor *domain_sd;
- struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
- struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
const struct uac_to_guid {
uint32_t uac;
uint32_t priv_to_change_from;
@@ -2078,21 +2097,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
}
- ret = dsdb_module_search_dn(ac->module, ac, &res,
- domain_dn,
- sd_attrs,
- DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
- ac->req);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- if (res->count != 1) {
- return ldb_module_operr(ac->module);
- }
-
- ret = dsdb_get_sd_from_ldb_message(ldb,
- ac, res->msgs[0], &domain_sd);
-
+ ret = samldb_get_domain_secdesc(ac, &domain_sd);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -2154,6 +2159,8 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
return ldb_module_operr(ac->module);
}
if (map[i].guid) {
+ struct ldb_dn *domain_dn
+ = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
dsdb_acl_debug(domain_sd, acl_user_token(ac->module),
domain_dn,
true,
@@ -3486,7 +3493,98 @@ static char *refer_if_rodc(struct ldb_context *ldb, struct ldb_request *req,
return NULL;
}
+/*
+ * Restrict all access to sensitive attributes.
+ *
+ * We don't want to even inspect the values, so we can use the same
+ * routine for ADD and MODIFY.
+ *
+ */
+
+static int samldb_check_sensitive_attributes(struct samldb_ctx *ac)
+{
+ struct ldb_message_element *el = NULL;
+ struct security_token *user_token = NULL;
+ int ret;
+
+ if (dsdb_module_am_system(ac->module)) {
+ return LDB_SUCCESS;
+ }
+
+ user_token = acl_user_token(ac->module);
+ if (user_token == NULL) {
+ return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ }
+
+ el = ldb_msg_find_element(ac->msg, "sidHistory");
+ if (el) {
+ /*
+ * sidHistory is restricted to the (not implemented
+ * yet in Samba) DsAddSidHistory call (direct LDB access is
+ * as SYSTEM so will bypass this).
+ *
+ * If you want to modify this, say to merge domains,
+ * directly modify the sam.ldb as root.
+ */
+ ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
+ "sidHistory "
+ "(entry %s) cannot be created "
+ "or changed over LDAP!",
+ ldb_dn_get_linearized(ac->msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+ el = ldb_msg_find_element(ac->msg, "msDS-SecondaryKrbTgtNumber");
+ if (el) {
+ struct security_descriptor *domain_sd;
+ /*
+ * msDS-SecondaryKrbTgtNumber allows the creator to
+ * become an RODC, this is trusted as an RODC
+ * account
+ */
+ ret = samldb_get_domain_secdesc(ac, &domain_sd);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ ret = acl_check_extended_right(ac, domain_sd,
+ user_token,
+ GUID_DRS_DS_INSTALL_REPLICA,
+ SEC_ADS_CONTROL_ACCESS,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
+ "msDS-SecondaryKrbTgtNumber "
+ "(entry %s) cannot be created "
+ "or changed without "
+ "DS-Install-Replica extended right!",
+ ldb_dn_get_linearized(ac->msg->dn));
+ return ret;
+ }
+ }
+
+ el = ldb_msg_find_element(ac->msg, "msDS-AllowedToDelegateTo");
+ if (el) {
+ /*
+ * msDS-AllowedToDelegateTo is incredibly powerful,
+ * given that it allows a server to become ANY USER on
+ * the target server only listed by SPN so needs to be
+ * protected just as the userAccountControl
+ * UF_TRUSTED_FOR_DELEGATION is.
+ */
+
+ bool have_priv = security_token_has_privilege(user_token,
+ SEC_PRIV_ENABLE_DELEGATION);
+ if (have_priv == false) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
+ "msDS-AllowedToDelegateTo "
+ "(entry %s) cannot be created "
+ "or changed without SePrivEnableDelegation!",
+ ldb_dn_get_linearized(ac->msg->dn));
+ return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ }
+ }
+ return LDB_SUCCESS;
+}
/* add */
static int samldb_add(struct ldb_module *module, struct ldb_request *req)
{
@@ -3533,6 +3631,12 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
return ldb_operr(ldb);
}
+ ret = samldb_check_sensitive_attributes(ac);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
+ return ret;
+ }
+
el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
if (el != NULL) {
ret = samldb_fsmo_role_owner_check(ac);
@@ -3740,6 +3844,12 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
return ldb_operr(ldb);
}
+ ret = samldb_check_sensitive_attributes(ac);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
+ return ret;
+ }
+
if (is_undelete == NULL) {
el = ldb_msg_find_element(ac->msg, "primaryGroupID");
if (el != NULL) {
--
2.23.0