Bug 2546244
| Summary: | CVE-2026-92821 sssd: SSSD: Access control bypass via premature LDAP access rule evaluation [fedora-all] | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Marco Benatto <mbenatto> |
| Component: | sssd | Assignee: | Sumit Bose <sbose> |
| Status: | POST --- | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | rawhide | CC: | abokovoy, atikhono, lslebodn, pbrezina, sbose, ssorce, sssd-maintainers |
| Target Milestone: | --- | Keywords: | Security, SecurityTracking |
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | {"flaws": ["1603e740-4eb3-4129-9f28-e8e7e71bde68"]} | ||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 2479031 | ||
Upstream PR: https://github.com/SSSD/sssd/pull/9393 (In reply to Sumit Bose from comment #1) > Upstream PR: https://github.com/SSSD/sssd/pull/9393 Fixed upstream: https://github.com/SSSD/sssd/commit/e83a29ceaffb1cb106696f24213a1ed6851f6baf |
Disclaimer: Community trackers are created by Red Hat Product Security team on a best effort basis. Package maintainers are required to ascertain if the flaw indeed affects their package, before starting the update process. 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