Bug 2479031 (CVE-2026-92821) - CVE-2026-92821 sssd: SSSD: Access control bypass via premature LDAP access rule evaluation
Summary: CVE-2026-92821 sssd: SSSD: Access control bypass via premature LDAP access ru...
Keywords:
Status: NEW
Alias: CVE-2026-92821
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: 2546244
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 03:53 UTC by OSIDB Bzimport
Modified: 2026-10-06 00:14 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:53:12 UTC
AI_ONLY_REPORT
package: sssd-2.12.0-1.el10
------
Summary: LDAP Access Control Bypass When `pwd_expire_policy_warn` Precedes  
Restrictive Rules in `ldap_access_order`: an expired-password warning is  
converted into a successful PAM result before later LDAP access rules run,  
allowing configured `filter`, `host`, or similar restrictive checks to be  
bypassed.
Requirements to exploit: A valid LDAP-backed account whose password is  
expired, an LDAP deployment using `access_provider = ldap` with a  
compatible password-expiration policy, `ldap_access_order` placing  
`pwd_expire_policy_warn` before restrictive rules, and a non-password  
authentication path such as SSH public key that still invokes SSSD  
account/access checks.
Component affected: `sssd-2.12.0-1.el10`, LDAP access-control evaluation in  
`src/providers/ldap/sdap_access.c` (`sdap_access_check_next_rule()`) and  
success mapping in `src/providers/ldap/ldap_access.c`  
(`sdap_pam_access_handler_done()`).
Version affected: `sssd-2.12.0-1.el10` in LDAP deployments where  
`ldap_access_order` places `pwd_expire_policy_warn` before restrictive  
rules.
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N - 6.8 (MEDIUM)
AV:N - reachable over the network through services that rely on SSSD  
LDAP account/access checks, such as SSH.
AC:H - exploitation depends on a specific non-default rule ordering, an  
expired-password state, and a compatible non-password authentication path.
PR:L - the attacker needs a valid account that can authenticate to the  
target service.
UI:N - no separate victim interaction is required once the attacker  
initiates authentication.
S:U - the impact remains within the vulnerable service's own security  
scope.
C:H - a successful bypass can expose data on systems or services that  
should have remained inaccessible under `filter`, `host`, or `rhost`  
restrictions.
I:H - the same bypass can permit unauthorized actions within those  
protected systems or services.
A:N - the flaw does not inherently reduce availability.
Impact: Moderate. This is a real authorization bypass with meaningful  
confidentiality and integrity consequences where LDAP access rules are used  
as security boundaries, but exploitation requires a valid account, an  
expired-password condition, and a specific non-default `ldap_access_order`  
configuration. That fits a security flaw that can compromise resources  
under certain circumstances, while being less easily exploitable than a  
default-path or broadly reachable access-control failure.
Embargo: no
Reason: the issue is configuration-dependent, requires an already valid  
account, and can be mitigated immediately by reordering or removing  
`pwd_expire_policy_warn` from the front of `ldap_access_order`.
Acknowledgement: Aisle Research
Vulnerability Details: The documented purpose of `pwd_expire_policy_warn`  
is to warn while still allowing login. The issue here is narrower: in the  
LDAP access path, that warning state terminates ordered rule evaluation  
before later restrictive checks are reached. In  
`sdap_access_check_next_rule()`, rule processing only continues while `ret  
== EOK`; when `LDAP_ACCESS_EXPIRE_POLICY_WARN` converts an expired password  
into `ERR_PASSWORD_EXPIRED_WARN`, the loop stops and returns that non-`EOK`  
status.
```c
while (ret == EOK) {
...
case LDAP_ACCESS_EXPIRE_POLICY_WARN:
ret = perform_pwexpire_policy(state, state->domain, state->pd,
state->access_ctx->type,
state->access_ctx->id_ctx->opts);
if (ret == ERR_PASSWORD_EXPIRED) {
ret = ERR_PASSWORD_EXPIRED_WARN;
}
break;
...
}
state->current_rule++;
}
return ret;
```
That returned status is then treated as success in  
`sdap_pam_access_handler_done()`, which maps both `EOK` and  
`ERR_PASSWORD_EXPIRED_WARN` to `PAM_SUCCESS`. In deployments using an  
ordered configuration such as `pwd_expire_policy_warn,filter,host`, later  
`filter`, `host`, or `rhost` checks are skipped entirely, so an  
expired-password user can be accepted by the warning path before the  
restrictive rules run.
Steps to reproduce:
1. Configure an LDAP-backed SSSD domain with `access_provider = ldap`,  
`ldap_pwd_policy = shadow` (or `mit_kerberos`), `ldap_access_order =  
pwd_expire_policy_warn,filter,host`, and a restrictive `ldap_access_filter`  
or host rule that should deny the test user.
2. Ensure the test user's password is marked expired in the LDAP attributes  
used by the selected password policy.
3. Authenticate through a non-password method that still invokes  
account/access checks, such as SSH public key login.
4. Expected result: a later `filter` or `host` rule denies access. Actual  
result: the warning path returns `ERR_PASSWORD_EXPIRED_WARN`, the handler  
maps it to `PAM_SUCCESS`, and the later restrictive rules are not evaluated.
Mitigation: Until a fix is available, do not place `pwd_expire_policy_warn`  
before restrictive entries in `ldap_access_order`. If warning behavior is  
still required, place it after `filter`, `host`, `rhost`, or other  
denial-capable rules, or use `pwd_expire_policy_reject` where expired  
accounts should not continue through the access chain.
Proposed Fix: Record the warning state, continue evaluating the remaining  
ordered rules, and only return `ERR_PASSWORD_EXPIRED_WARN` after all  
configured access rules have passed.
```diff
diff --git a/src/providers/ldap/sdap_access.c  
b/src/providers/ldap/sdap_access.c
— a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@
struct sdap_access_req_ctx {
@@
size_t current_rule;
enum sdap_access_control_type ac_type;
+    bool pw_expire_warn_seen;
};
@@
state->conn = conn;
state->current_rule = 0;
+    state->pw_expire_warn_seen = false;
@@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx  
*state,
case LDAP_ACCESS_EMPTY:
           /* we are done with no errors */

           return EOK;
+            /* all rules passed; preserve warn semantics if seen */
+            return state->pw_expire_warn_seen ?  
ERR_PASSWORD_EXPIRED_WARN : EOK;
@@
          case LDAP_ACCESS_EXPIRE_POLICY_WARN:
              ret = perform_pwexpire_policy(state, state->domain, state->pd,
                                            state->access_ctx->type,
                                            state->access_ctx->id_ctx->opts);
              if (ret == ERR_PASSWORD_EXPIRED) {

               ret = ERR_PASSWORD_EXPIRED_WARN;
+                state->pw_expire_warn_seen = true;
+                ret = EOK;
              }
              break;
```


------
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.