Bug 2478915 (CVE-2026-104040) - CVE-2026-104040 sssd: sssd: Information disclosure via OData injection in Entra ID lookups
Summary: CVE-2026-104040 sssd: sssd: Information disclosure via OData injection in Ent...
Keywords:
Status: NEW
Alias: CVE-2026-104040
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On: 2546255
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 03:49 UTC by OSIDB Bzimport
Modified: 2026-10-06 00:48 UTC (History)
18 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-18 03:49:30 UTC
AI_ONLY_REPORT
package: sssd-2.12.0-1.el10
------
Summary: OData Injection in Entra ID Lookup via Unescaped Name Input  
(`entra_id_lookup`): crafted lookup names containing a single quote can  
alter Microsoft Graph OData `$filter` semantics, broadening Entra user or  
group queries and causing unintended directory objects to be fetched,  
processed, and cached.
Requirements to exploit: A deployment of `sssd-2.12.0-1.el10` using the IdP  
provider for Entra ID lookups, an IdP client that can read user or group  
data from Microsoft Graph, and a low-privileged actor who can trigger a  
name-based lookup through SSSD with crafted input that reaches  
`entra_id_lookup()`.
Component affected: `sssd-2.12.0-1.el10` IdP provider code in  
`src/oidc_child/oidc_child_id.c`, `entra_id_lookup()`, with name-based  
input passed from `src/providers/idp/idp_id.c` and returned objects  
processed by `src/providers/idp/idp_id_eval.c`.
Version affected: `sssd-2.12.0-1.el10`, when the IdP provider is used for  
Entra ID lookups, for example with `id_provider = idp` and `idp_type =  
entra_id`
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L - 4.4 (MEDIUM)
AV:L - The vulnerable path is reached through local SSSD account lookup  
activity rather than a directly remote network interface.
AC:L - A single quote in the lookup name is sufficient to break OData  
string literal context.
PR:L - A low-privileged local user who can trigger lookups is sufficient  
in affected deployments.
UI:N - No separate victim interaction is required once the lookup is  
initiated.
S:U - The impact remains within the SSSD and configured IdP lookup  
security scope.
C:L - Successful injection can broaden directory reads beyond the  
intended lookup, subject to the configured Graph client's permissions.
I:N - The available evidence shows no direct write or modification  
primitive.
A:L - Broadened queries can return larger result sets, increasing  
processing and cache population work.
Impact: Moderate. This issue can expose additional directory objects and  
create denial-of-service-like load in affected deployments, but it depends  
on the Entra ID IdP provider being configured and on the permissions  
already granted to the configured Graph client. The established outcome is  
limited to unintended read scope expansion and increased processing; there  
is no evidence of code execution, direct privilege escalation, or direct  
data modification. Under Red Hat's severity guidance, this is better  
characterized as a configuration-dependent confidentiality and availability  
issue with Moderate impact than an Important or Critical system compromise.
Embargo: no
Reason: The issue is configuration-dependent, has limited demonstrated  
impact, and can be addressed by a small escaping change, so public  
coordinated release with a fix is appropriate.
Acknowledgement: Aisle Research
Vulnerability Details: `entra_id_lookup()` builds OData `$filter`  
expressions by interpolating the externally influenced lookup name into  
single-quoted OData string literals and only URL-encoding the finished  
expression afterward. URL encoding at that stage does not escape OData  
string literal context, so a single quote in the name can terminate the  
literal and append additional operators or conditions.
```c
if (sep == NULL || sep == input) {
filter =  
talloc_asprintf(rest_ctx, "startsWith(userPrincipalName,'%s@')", input);
} else {
filter = talloc_asprintf(rest_ctx,
"mail eq '%s' or userPrincipalName eq '%s'",
input, input);
}
...
filter_enc = url_encode_string(rest_ctx, filter);
```
Name-based lookups are forwarded into this path through the IdP provider's  
`--name` argument handling:
```c
extra_args[c] = talloc_asprintf(extra_args, "--name=%s",
search_name != NULL ? search_name
: filter_value);
```
The response handling path then iterates over every returned object and  
stores it without re-applying the original query intent after the Graph  
response is received:
```c
json_array_foreach(data, index, obj) {
ret = store_func(idp_id_ctx, obj, name);
if (ret != EOK) {
tmp = json_dumps(obj, 0);
DEBUG(SSSDBG_OP_FAILURE, "Failed to store JSON %s [%s].\n", type,
tmp);
free(tmp);
}
}
```
As a result, a crafted lookup name can broaden the filter used for Entra  
user or group searches, leading to over-fetching of directory data within  
the configured application's existing read permissions, additional  
processing, and cache pollution. The exact breadth of returned objects  
depends on the Graph permissions granted to the configured IdP client and  
on the specific lookup branch reached, but the available code paths support  
confidentiality and availability impact. The available evidence does not  
support direct integrity impact.
Steps to reproduce:
1. Configure a test domain with `id_provider = idp`, `idp_type = entra_id`,  
and valid `idp_client_id`, `idp_client_secret`, `idp_token_endpoint`, and  
`idp_id_scope` values, using an application that can read users or groups  
from Microsoft Graph.
2. Trigger a name-based user or group lookup via NSS or another SSSD  
account lookup path that causes SSSD to pass the requested name into the  
Entra lookup path.
3. Use a crafted lookup name containing a single quote, for example `a') or  
userPrincipalName ne ('`. Depending on the exact lookup flow, a UPN-style  
variant of the payload may be needed when the name is propagated internally.
4. Enable verbose SSSD or libcurl debugging and inspect the outbound Graph  
request URL.
5. Observe that the generated `$filter` no longer represents only the  
intended exact or prefix lookup. For example, if the  
`startsWith(userPrincipalName,'%s@')` branch receives the payload above,  
the resulting filter becomes logically equivalent to  
`startsWith(userPrincipalName,'a') or userPrincipalName ne ('@')`.
6. Confirm that the returned array is accepted by the IdP evaluation path  
and that each returned object is processed and stored, demonstrating  
broadened read scope and added processing work.
Mitigation: Until a fix is available, restrict untrusted users from  
triggering IdP-backed name lookups in deployments using the Entra ID  
provider path, and keep the configured Graph application permissions as  
narrow as possible. If operationally acceptable, reject or sanitize lookup  
names containing single quotes before they reach the Entra lookup path.  
Increased SSSD or libcurl debug logging can help identify unexpectedly  
broadened `$filter` requests during monitoring.
Proposed Fix: Escape single quotes for OData string literal context before  
interpolating `input` or `short_name` into the filter, then continue  
URL-encoding the completed expression.
```diff
diff --git a/src/oidc_child/oidc_child_id.c b/src/oidc_child/oidc_child_id.c
— a/src/oidc_child/oidc_child_id.c
+++ b/src/oidc_child/oidc_child_id.c
@@
#include "oidc_child/oidc_child_util.h"
#include "util/util.h"
+static char *odata_escape_quotes(TALLOC_CTX *mem_ctx, const char *in)
+{
+    const char *p;
+    char *out;
+
+    if (in == NULL) return NULL;
+    out = talloc_strdup(mem_ctx, "");
+    if (out == NULL) return NULL;
+
+    for (p = in; *p != '\0'; p++) {
+        out = (*p == '\'') ? talloc_asprintf_append(out, "''")
+                           : talloc_asprintf_append(out, "%c", *p);
+        if (out == NULL) return NULL;
+    }
+    return out;
+}
+
errno_t entra_id_lookup(...)
{
@@
   char *short_name;
+    char *short_name;
+    char *escaped_input;
+    char *escaped_short_name;
@@
+    escaped_input = odata_escape_quotes(rest_ctx, input);
+    if (escaped_input == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
@@

           filter =  
talloc_asprintf(rest_ctx, "startsWith(userPrincipalName,'%s@')", input);
+            filter =  
talloc_asprintf(rest_ctx, "startsWith(userPrincipalName,'%s@')",  
escaped_input);
@@

                                    input, input);
+                                     escaped_input, escaped_input);
@@

           filter = talloc_asprintf(rest_ctx, "displayName eq '%s'",  
input);
+            filter = talloc_asprintf(rest_ctx, "displayName eq '%s'",  
escaped_input);
@@

               filter = talloc_asprintf(rest_ctx, "displayName eq '%s'",  
input);
+                filter = talloc_asprintf(rest_ctx, "displayName eq '%s'",  
escaped_input);
              } else {
+                escaped_short_name = odata_escape_quotes(rest_ctx,  
short_name);
+                if (escaped_short_name == NULL) {
+                    ret = ENOMEM;
+                    goto done;
+                }
                  filter = talloc_asprintf(rest_ctx,
                                           "displayName eq '%s' or  
displayName eq '%s'",

                                        input, short_name);
+                                         escaped_input,  
escaped_short_name);
              }
```


------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.