Resolves: RHEL-168415 - [Addition] Crash in 'sss_client/autofs/sss_autofs.c' [rhel-8.10.z]
Resolves: RHEL-168363 - sss_override does not work on AD UPN [rhel-8.10.z] Resolves: RHEL-192053 - CVE-2026-14474: sudo LDAP provider searches entire directory tree for sudoRole objects by default, enabling privilege escalation [rhel-8.10.z] Resolves: RHEL-192076 - CVE-2026-14476: GPO cache path traversal via unsanitized gPCFileSysPath allows Kerberos authentication bypass [rhel-8.10.z]
This commit is contained in:
parent
4e0e69dcf7
commit
fbc22ccc53
36
0027-Add-missing-include.patch
Normal file
36
0027-Add-missing-include.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From a41b84d7bf42846aa2b5f265741edba9a1f7e0c1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Date: Wed, 15 Apr 2026 09:42:34 +0200
|
||||
Subject: [PATCH] Add missing include
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Original patch f3af8c89af656767333410b0e94da9288dd8ade8 didn't include
|
||||
"config.h" that provides `HAVE_PTHREAD_EXT`
|
||||
It works in some branches accidentally because of transitive include
|
||||
via "sss_cli.h" but that's fragile (and in some branches "sss_cli.h"
|
||||
doesn't include "config.h")
|
||||
|
||||
Reviewed-by: Tomáš Halman <thalman@redhat.com>
|
||||
(cherry picked from commit a809b9236250e6f20e9a9ff1452708cd288b705f)
|
||||
---
|
||||
src/sss_client/autofs/sss_autofs.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/sss_client/autofs/sss_autofs.c b/src/sss_client/autofs/sss_autofs.c
|
||||
index f5986767f..45e2ce460 100644
|
||||
--- a/src/sss_client/autofs/sss_autofs.c
|
||||
+++ b/src/sss_client/autofs/sss_autofs.c
|
||||
@@ -18,6 +18,8 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
+#include "config.h"
|
||||
+
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
--
|
||||
2.54.0
|
||||
|
||||
88
0028-sysdb-add-sysdb_search_user_by_upn_with_view_res.patch
Normal file
88
0028-sysdb-add-sysdb_search_user_by_upn_with_view_res.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From 5ca4b84efd03d6b2add6d82d92cea7ef58bc4ca9 Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Thu, 12 Jun 2025 19:49:10 +0200
|
||||
Subject: [PATCH 28/32] sysdb: add sysdb_search_user_by_upn_with_view_res()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The new call will apply overrides to a user object which was searched by
|
||||
UPN or email address before returning it.
|
||||
|
||||
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
||||
(cherry picked from commit 794e80f4f155cd5d97e70ee015909cd9f3b918b3)
|
||||
---
|
||||
src/db/sysdb.h | 7 +++++++
|
||||
src/db/sysdb_ops.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 44 insertions(+)
|
||||
|
||||
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
|
||||
index cedbd4eab..3a0259ec9 100644
|
||||
--- a/src/db/sysdb.h
|
||||
+++ b/src/db/sysdb.h
|
||||
@@ -1047,6 +1047,13 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
|
||||
const char **attrs,
|
||||
struct ldb_result **out_res);
|
||||
|
||||
+int sysdb_search_user_by_upn_with_view_res(TALLOC_CTX *mem_ctx,
|
||||
+ struct sss_domain_info *domain,
|
||||
+ bool domain_scope,
|
||||
+ const char *upn,
|
||||
+ const char **attrs,
|
||||
+ struct ldb_result **out_res);
|
||||
+
|
||||
int sysdb_search_user_by_upn(TALLOC_CTX *mem_ctx,
|
||||
struct sss_domain_info *domain,
|
||||
bool domain_scope,
|
||||
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
|
||||
index 744e6e879..b0e8060f9 100644
|
||||
--- a/src/db/sysdb_ops.c
|
||||
+++ b/src/db/sysdb_ops.c
|
||||
@@ -712,6 +712,43 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int sysdb_search_user_by_upn_with_view_res(TALLOC_CTX *mem_ctx,
|
||||
+ struct sss_domain_info *domain,
|
||||
+ bool domain_scope,
|
||||
+ const char *upn,
|
||||
+ const char **attrs,
|
||||
+ struct ldb_result **out_res)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct ldb_result *orig_obj = NULL;
|
||||
+
|
||||
+ /* The UPN or the email address cannot be overwritten and we can search
|
||||
+ * directly the original object. */
|
||||
+ ret = sysdb_search_user_by_upn_res(mem_ctx, domain, domain_scope, upn,
|
||||
+ attrs, &orig_obj);
|
||||
+ if (ret != EOK) {
|
||||
+ DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE,
|
||||
+ "Failed to find UPN [%s] in cache [%d][%s].\n",
|
||||
+ upn, ret, sss_strerror(ret));
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* If there are views we have to check if override values must be added to
|
||||
+ * the original object. */
|
||||
+ if (DOM_HAS_VIEWS(domain)) {
|
||||
+ ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], NULL,
|
||||
+ attrs);
|
||||
+ if (ret != EOK && ret != ENOENT) {
|
||||
+ talloc_free(orig_obj);
|
||||
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ *out_res = orig_obj;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int sysdb_search_user_by_upn(TALLOC_CTX *mem_ctx,
|
||||
struct sss_domain_info *domain,
|
||||
bool domain_scope,
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
From 5f53949d3fcc3bd8b02b2d79327a3cf303c76d38 Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Thu, 12 Jun 2025 19:49:42 +0200
|
||||
Subject: [PATCH 29/32] cache_req: use sysdb_search_user_by_upn_with_view_res()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
To make sure any overrides are applied to the user even when searched by
|
||||
UPN or email address sysdb_search_user_by_upn_with_view_res() is now
|
||||
used in the cache request code.
|
||||
|
||||
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
||||
(cherry picked from commit 43f22b968a48c4e1f1e7cb885e68428baa7cc7be)
|
||||
---
|
||||
.../cache_req/plugins/cache_req_user_by_upn.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c
|
||||
index 037994c8c..cfcaf4916 100644
|
||||
--- a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c
|
||||
+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c
|
||||
@@ -84,13 +84,14 @@ cache_req_user_by_upn_lookup(TALLOC_CTX *mem_ctx,
|
||||
struct sss_domain_info *domain,
|
||||
struct ldb_result **_result)
|
||||
{
|
||||
- if (data->attrs == NULL) {
|
||||
- return sysdb_getpwupn(mem_ctx, domain, true, data->name.lookup, _result);
|
||||
- }
|
||||
-
|
||||
- return sysdb_search_user_by_upn_res(mem_ctx, domain, true,
|
||||
- data->name.lookup, data->attrs,
|
||||
- _result);
|
||||
+ static const char *def_attrs[] = SYSDB_PW_ATTRS;
|
||||
+
|
||||
+ return sysdb_search_user_by_upn_with_view_res(mem_ctx, domain, true,
|
||||
+ data->name.lookup,
|
||||
+ data->attrs == NULL
|
||||
+ ? def_attrs
|
||||
+ : data->attrs,
|
||||
+ _result);
|
||||
}
|
||||
|
||||
static struct tevent_req *
|
||||
--
|
||||
2.54.0
|
||||
|
||||
95
0030-sysdb-remove-sysdb_getpwupn.patch
Normal file
95
0030-sysdb-remove-sysdb_getpwupn.patch
Normal file
@ -0,0 +1,95 @@
|
||||
From 9937664e29e45706100b2b6ea5fd6570b848089b Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Thu, 12 Jun 2025 19:52:10 +0200
|
||||
Subject: [PATCH 30/32] sysdb:: remove sysdb_getpwupn()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
||||
(cherry picked from commit fe61b85b440380bd88d5859819a1111878ca36ea)
|
||||
---
|
||||
src/db/sysdb.h | 6 ------
|
||||
src/db/sysdb_search.c | 30 --------------------------
|
||||
src/tests/cmocka/test_sysdb_ts_cache.c | 6 ------
|
||||
3 files changed, 42 deletions(-)
|
||||
|
||||
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
|
||||
index 3a0259ec9..8c030bd07 100644
|
||||
--- a/src/db/sysdb.h
|
||||
+++ b/src/db/sysdb.h
|
||||
@@ -852,12 +852,6 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
|
||||
uid_t uid,
|
||||
struct ldb_result **res);
|
||||
|
||||
-int sysdb_getpwupn(TALLOC_CTX *mem_ctx,
|
||||
- struct sss_domain_info *domain,
|
||||
- bool domain_scope,
|
||||
- const char *upn,
|
||||
- struct ldb_result **res);
|
||||
-
|
||||
int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
|
||||
struct sss_domain_info *domain,
|
||||
struct ldb_result **res);
|
||||
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
|
||||
index f59312b72..49362beb0 100644
|
||||
--- a/src/db/sysdb_search.c
|
||||
+++ b/src/db/sysdb_search.c
|
||||
@@ -598,36 +598,6 @@ static char *enum_filter(TALLOC_CTX *mem_ctx,
|
||||
return filter;
|
||||
}
|
||||
|
||||
-int sysdb_getpwupn(TALLOC_CTX *mem_ctx,
|
||||
- struct sss_domain_info *domain,
|
||||
- bool domain_scope,
|
||||
- const char *upn,
|
||||
- struct ldb_result **_res)
|
||||
-{
|
||||
- TALLOC_CTX *tmp_ctx;
|
||||
- struct ldb_result *res;
|
||||
- static const char *attrs[] = SYSDB_PW_ATTRS;
|
||||
- errno_t ret;
|
||||
-
|
||||
- tmp_ctx = talloc_new(NULL);
|
||||
- if (tmp_ctx == NULL) {
|
||||
- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
|
||||
- return ENOMEM;
|
||||
- }
|
||||
-
|
||||
- ret = sysdb_search_user_by_upn_res(tmp_ctx, domain, domain_scope, upn, attrs, &res);
|
||||
- if (ret != EOK && ret != ENOENT) {
|
||||
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn_res() failed.\n");
|
||||
- goto done;
|
||||
- }
|
||||
-
|
||||
- *_res = talloc_steal(mem_ctx, res);
|
||||
-
|
||||
-done:
|
||||
- talloc_free(tmp_ctx);
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
errno_t sysdb_search_ts_matches(TALLOC_CTX *mem_ctx,
|
||||
struct sysdb_ctx *sysdb,
|
||||
const char *attrs[],
|
||||
diff --git a/src/tests/cmocka/test_sysdb_ts_cache.c b/src/tests/cmocka/test_sysdb_ts_cache.c
|
||||
index f349b7061..531de72ab 100644
|
||||
--- a/src/tests/cmocka/test_sysdb_ts_cache.c
|
||||
+++ b/src/tests/cmocka/test_sysdb_ts_cache.c
|
||||
@@ -1303,12 +1303,6 @@ static void test_user_byupn(void **state)
|
||||
TEST_NOW_2);
|
||||
assert_int_equal(ret, EOK);
|
||||
|
||||
- ret = sysdb_getpwupn(test_ctx, test_ctx->tctx->dom, false, TEST_USER_UPN, &res);
|
||||
- assert_int_equal(ret, EOK);
|
||||
- assert_int_equal(res->count, 1);
|
||||
- assert_ts_attrs_res(res, TEST_NOW_2 + TEST_CACHE_TIMEOUT, TEST_NOW_2);
|
||||
- talloc_free(res);
|
||||
-
|
||||
ret = sysdb_search_user_by_upn_res(test_ctx, test_ctx->tctx->dom,
|
||||
false, TEST_USER_UPN, pw_fetch_attrs,
|
||||
&res);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From a13fcb20a9b8d1d0e7727d7793c7a6d2f0a696dd Mon Sep 17 00:00:00 2001
|
||||
From: Sumit Bose <sbose@redhat.com>
|
||||
Date: Mon, 5 Jan 2026 10:17:27 +0100
|
||||
Subject: [PATCH 32/32] sysdb: do not treat missing id-override as an error
|
||||
|
||||
In sysdb_search_user_by_upn_with_view_res()
|
||||
sysdb_add_overrides_to_object() can return ENOENT if there is no
|
||||
id-override for the given user. This is expected and should not be
|
||||
treated as an error.
|
||||
|
||||
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
(cherry picked from commit 72a42d5cbb969f61698f7403fe6e7cf6a8abf957)
|
||||
---
|
||||
src/db/sysdb_ops.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
|
||||
index b0e8060f9..dec1572f5 100644
|
||||
--- a/src/db/sysdb_ops.c
|
||||
+++ b/src/db/sysdb_ops.c
|
||||
@@ -743,6 +743,7 @@ int sysdb_search_user_by_upn_with_view_res(TALLOC_CTX *mem_ctx,
|
||||
DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
|
||||
return ret;
|
||||
}
|
||||
+ ret = EOK;
|
||||
}
|
||||
|
||||
*out_res = orig_obj;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
From 8b58a80ffedf80ff44f9fe003db5a76bdba88a0d Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Date: Fri, 3 Jul 2026 13:25:08 +0200
|
||||
Subject: [PATCH] sudo: warn when ldap_sudo_search_base falls back to root DN
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When ldap_sudo_search_base is not explicitly configured, SSSD falls back
|
||||
to the domain's naming context (root DN) and searches the entire LDAP
|
||||
directory tree for sudoRole objects. Any LDAP principal with write access
|
||||
to any subtree can inject a sudoRole granting arbitrary sudo privileges
|
||||
on every enrolled host.
|
||||
|
||||
This patch adds a warning log when the fallback occurs, alerting
|
||||
administrators that their configuration searches the entire directory
|
||||
tree for sudo rules. A future hardening step would be to default to
|
||||
ou=sudoers,<base_dn> instead of the root DN.
|
||||
|
||||
The warning approach preserves backwards compatibility while ensuring
|
||||
administrators are aware of the security implications.
|
||||
|
||||
Based on the patch by: Ian Murphy <imurphy@redhat.com>
|
||||
Amended by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
|
||||
:fixes: CVE-2026-14474
|
||||
|
||||
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
||||
Reviewed-by: Tomáš Halman <thalman@redhat.com>
|
||||
(cherry picked from commit ff8c1b19bcdbf79b733b052a7d926bd920b1205d)
|
||||
---
|
||||
src/providers/ldap/sdap.c | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
|
||||
index 956eba93a..1dd5182bf 100644
|
||||
--- a/src/providers/ldap/sdap.c
|
||||
+++ b/src/providers/ldap/sdap.c
|
||||
@@ -1309,6 +1309,25 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
|
||||
|
||||
/* Sudo */
|
||||
if (!sdom->sudo_search_bases) {
|
||||
+ /* At some point make this option mandatory,
|
||||
+ * i.e. disable sudo rules lookup if 'sudo_search_bases' not set.
|
||||
+ */
|
||||
+ DEBUG(SSSDBG_IMPORTANT_INFO,
|
||||
+ "`ldap_sudo_search_base` is not set. SSSD will search the entire "
|
||||
+ "directory tree (%s) for sudoRole objects. This may allow any "
|
||||
+ "LDAP principal with write access to any subtree to inject "
|
||||
+ "sudo rules granting arbitrary privileges. Set "
|
||||
+ "`ldap_sudo_search_base` to restrict the search scope "
|
||||
+ "(e.g., 'ou=sudoers,dc=example,dc=com').\n",
|
||||
+ sdom->naming_context);
|
||||
+ sss_log(SSS_LOG_ALERT,
|
||||
+ "`ldap_sudo_search_base` is not set. SSSD will search the entire "
|
||||
+ "directory tree (%s) for sudoRole objects. This may allow any "
|
||||
+ "LDAP principal with write access to any subtree to inject "
|
||||
+ "sudo rules granting arbitrary privileges. Set "
|
||||
+ "`ldap_sudo_search_base` to restrict the search scope "
|
||||
+ "(e.g., 'ou=sudoers,dc=example,dc=com').",
|
||||
+ sdom->naming_context);
|
||||
ret = sdap_set_search_base(opts, sdom,
|
||||
SDAP_SUDO_SEARCH_BASE,
|
||||
sdom->naming_context);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
176
0033-gpo-reject-path-traversal-in-gPCFileSysPath.patch
Normal file
176
0033-gpo-reject-path-traversal-in-gPCFileSysPath.patch
Normal file
@ -0,0 +1,176 @@
|
||||
From 080693ec86737ce3748aff4164b502de3f5d518f Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Tikhonov <atikhono@redhat.com>
|
||||
Date: Thu, 2 Jul 2026 17:29:51 +0200
|
||||
Subject: [PATCH] gpo: reject path traversal in gPCFileSysPath
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The gPCFileSysPath LDAP attribute from AD Group Policy Objects is parsed
|
||||
by ad_gpo_extract_smb_components() which converts backslashes to forward
|
||||
slashes but does not reject ".." path traversal sequences. The resulting
|
||||
smb_path is used directly in gpo_cache_store_file() to construct a local
|
||||
filesystem path under GPO_CACHE_PATH, allowing an attacker with GPO
|
||||
write access to write files outside the cache directory.
|
||||
|
||||
Due to differential path resolution between libsmbclient (which clamps
|
||||
".." at the SMB share root) and the kernel (which resolves ".." fully),
|
||||
the SMB download succeeds while the local file write escapes the cache.
|
||||
On systems with SELinux enforcing, this enables Kerberos configuration
|
||||
injection via /var/lib/sss/pubconf/krb5.include.d/ (sssd_public_t,
|
||||
writable by sssd_t). On systems without SELinux, this enables arbitrary
|
||||
file writes including cron job injection for root code execution.
|
||||
|
||||
This patch adds two layers of defense:
|
||||
|
||||
1. Reject ".." as a path component in smb_path at parse time in
|
||||
ad_gpo_extract_smb_components(). Uses component-aware validation
|
||||
that checks for "/..", "../", and exact ".." — not substring matching
|
||||
which would false-positive on legitimate names containing "..".
|
||||
|
||||
2. Validate the resolved cache path stays within GPO_CACHE_PATH in
|
||||
gpo_cache_store_file() using realpath(), with a trailing-slash
|
||||
prefix check to prevent prefix-collision attacks (e.g.,
|
||||
/var/lib/sss/gpo_cache_evil/ matching /var/lib/sss/gpo_cache).
|
||||
|
||||
Based on the patch by: Ian Murphy <imurphy@redhat.com>
|
||||
Amended by: Alexey Tikhonov <atikhono@redhat.com>
|
||||
|
||||
:fixes: CVE-2026-14476
|
||||
|
||||
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
||||
Reviewed-by: Tomáš Halman <thalman@redhat.com>
|
||||
(cherry picked from commit ba207eab76ff5253662a763b9b6e9ea42f03d31b)
|
||||
---
|
||||
src/providers/ad/ad_gpo.c | 47 +++++++++++++++++++++++++++++++
|
||||
src/providers/ad/ad_gpo_child.c | 49 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 96 insertions(+)
|
||||
|
||||
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
|
||||
index 4e2f06b0d..c4988e6a7 100644
|
||||
--- a/src/providers/ad/ad_gpo.c
|
||||
+++ b/src/providers/ad/ad_gpo.c
|
||||
@@ -3838,6 +3838,43 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Check whether a path contains ".." as a path component.
|
||||
+ * Returns true if traversal is detected, false if the path is safe.
|
||||
+ *
|
||||
+ * Checks for:
|
||||
+ * - "/.." anywhere in the path (component starting with ..)
|
||||
+ * - "../" at the start of the path
|
||||
+ * - exact match ".." (path is just "..")
|
||||
+ * - "/.." at the end of the path
|
||||
+ *
|
||||
+ * Does NOT match ".." as a substring of a longer component
|
||||
+ * (e.g., "my..file" is allowed).
|
||||
+ */
|
||||
+static bool gpo_path_has_traversal(const char *path)
|
||||
+{
|
||||
+ const char *p;
|
||||
+
|
||||
+ if (path == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Exact match */
|
||||
+ if (strcmp(path, "..") == 0) return true;
|
||||
+
|
||||
+ /* Starts with ../ */
|
||||
+ if (strncmp(path, "../", 3) == 0) return true;
|
||||
+
|
||||
+ /* Contains /../ or ends with /.. */
|
||||
+ p = path;
|
||||
+ while ((p = strstr(p, "/..")) != NULL) {
|
||||
+ if (p[3] == '/' || p[3] == '\0') return true;
|
||||
+ p += 3;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* This function parses the input_path into its components, replaces each
|
||||
* back slash ('\') with a forward slash ('/'), and populates the output params.
|
||||
@@ -3914,6 +3951,16 @@ ad_gpo_extract_smb_components(TALLOC_CTX *mem_ctx,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ /* Reject path traversal. See function comment for what is matched. */
|
||||
+ if (gpo_path_has_traversal(smb_path)) {
|
||||
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||||
+ "gPCFileSysPath contains path traversal component '..': "
|
||||
+ "[%s]. Rejecting to prevent cache directory escape.\n",
|
||||
+ smb_path);
|
||||
+ ret = EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
*_smb_server = talloc_asprintf(mem_ctx, "%s%s",
|
||||
SMB_STANDARD_URI,
|
||||
server_hostname);
|
||||
diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c
|
||||
index 2f2807bec..3a72a05b4 100644
|
||||
--- a/src/providers/ad/ad_gpo_child.c
|
||||
+++ b/src/providers/ad/ad_gpo_child.c
|
||||
@@ -320,6 +320,55 @@ static errno_t gpo_cache_store_file(const char *smb_path,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ /* Defense-in-depth: verify the resolved path stays within the cache
|
||||
+ * directory (when updating existing files). This catches any bypass
|
||||
+ * of the ".." check in the parser, including encoding tricks, symlink
|
||||
+ * attacks, or future regressions.
|
||||
+ *
|
||||
+ * The trailing-slash comparison prevents prefix-collision attacks:
|
||||
+ * without it, a path resolving to "/var/lib/sss/gpo_cache_evil/"
|
||||
+ * would incorrectly match the prefix "/var/lib/sss/gpo_cache".
|
||||
+ */
|
||||
+ {
|
||||
+ char *resolved = realpath(filename, NULL);
|
||||
+ if (resolved != NULL) {
|
||||
+ /* Resolve GPO_CACHE_PATH too so the comparison works
|
||||
+ * even when the cache path contains symlinks. */
|
||||
+ char *resolved_cache = realpath(GPO_CACHE_PATH, NULL);
|
||||
+ if (resolved_cache == NULL) {
|
||||
+ ret = errno;
|
||||
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||||
+ "realpath(\"%s\") failed: [%d][%s]\n",
|
||||
+ GPO_CACHE_PATH, ret, strerror(ret));
|
||||
+ free(resolved);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Check that resolved path starts with resolved cache + "/" */
|
||||
+ size_t cache_len = strlen(resolved_cache);
|
||||
+ bool inside = ((strlen(resolved) >= cache_len) &&
|
||||
+ (strncmp(resolved, resolved_cache, cache_len) == 0) &&
|
||||
+ (resolved[cache_len] == '/' || resolved[cache_len] == '\0'));
|
||||
+ if (!inside) {
|
||||
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||||
+ "GPO cache path escapes cache directory: [%s] "
|
||||
+ "resolves to [%s] which is outside [%s]. "
|
||||
+ "Rejecting.\n",
|
||||
+ filename, resolved, resolved_cache);
|
||||
+ free(resolved_cache);
|
||||
+ free(resolved);
|
||||
+ ret = EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ free(resolved_cache);
|
||||
+ free(resolved);
|
||||
+ }
|
||||
+ /* If realpath returns NULL, the path doesn't exist yet.
|
||||
+ * prepare_gpo_cache() will create it — the mkdir calls
|
||||
+ * are validated by SELinux MAC policy.
|
||||
+ */
|
||||
+ }
|
||||
+
|
||||
tmp_name = talloc_asprintf(tmp_ctx, "%sXXXXXX", filename);
|
||||
if (tmp_name == NULL) {
|
||||
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
|
||||
--
|
||||
2.54.0
|
||||
|
||||
15
sssd.spec
15
sssd.spec
@ -19,7 +19,7 @@
|
||||
|
||||
Name: sssd
|
||||
Version: 2.9.4
|
||||
Release: 5%{?dist}.4
|
||||
Release: 5%{?dist}.5
|
||||
Group: Applications/System
|
||||
Summary: System Security Services Daemon
|
||||
License: GPLv3+
|
||||
@ -53,6 +53,13 @@ Patch0023: 0023-sbus-defer-notification-callbacks.patch
|
||||
Patch0024: 0024-cache_req-allow-cache_first-mode-only-if-there-is-mo.patch
|
||||
Patch0025: 0025-RESPONDER-use-proper-context-for-getDomains.patch
|
||||
Patch0026: 0026-Enumerate-object-with-escaped-characters-in-name.patch
|
||||
Patch0027: 0027-Add-missing-include.patch
|
||||
Patch0028: 0028-sysdb-add-sysdb_search_user_by_upn_with_view_res.patch
|
||||
Patch0029: 0029-cache_req-use-sysdb_search_user_by_upn_with_view_res.patch
|
||||
Patch0030: 0030-sysdb-remove-sysdb_getpwupn.patch
|
||||
Patch0031: 0031-sysdb-do-not-treat-missing-id-override-as-an-error.patch
|
||||
Patch0032: 0032-sudo-warn-when-ldap_sudo_search_base-falls-back-to-r.patch
|
||||
Patch0033: 0033-gpo-reject-path-traversal-in-gPCFileSysPath.patch
|
||||
|
||||
### Downstream Patches ###
|
||||
|
||||
@ -1237,6 +1244,12 @@ fi
|
||||
%systemd_postun_with_restart sssd.service
|
||||
|
||||
%changelog
|
||||
* Wed Jul 8 2026 Alexey Tikhonov <atikhono@redhat.com> - 2.9.4-5.5
|
||||
- Resolves: RHEL-168415 - [Addition] Crash in 'sss_client/autofs/sss_autofs.c' [rhel-8.10.z]
|
||||
- Resolves: RHEL-168363 - sss_override does not work on AD UPN [rhel-8.10.z]
|
||||
- Resolves: RHEL-192053 - CVE-2026-14474: sudo LDAP provider searches entire directory tree for sudoRole objects by default, enabling privilege escalation [rhel-8.10.z]
|
||||
- Resolves: RHEL-192076 - CVE-2026-14476: GPO cache path traversal via unsanitized gPCFileSysPath allows Kerberos authentication bypass [rhel-8.10.z]
|
||||
|
||||
* Mon Jan 26 2026 Alexey Tikhonov <atikhono@redhat.com> - 2.9.4-5.4
|
||||
- Resolves: RHEL-143731 - Crash in 'sss_client/autofs/sss_autofs.c' [rhel-8.10.z]
|
||||
- Resolves: RHEL-133476 - 'sssd_nss' hangs when looking up an object by ID that has expired cache entry and filtered out by name [rhel-8.10.z]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user