Bug 2479271 (CVE-2026-104033) - CVE-2026-104033 sssd: sssd: Access control bypass via improper LDAP shadow expiration check
Summary: CVE-2026-104033 sssd: sssd: Access control bypass via improper LDAP shadow ex...
Keywords:
Status: NEW
Alias: CVE-2026-104033
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: 2546235
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 04:01 UTC by OSIDB Bzimport
Modified: 2026-10-05 23:45 UTC (History)
18 users (show)

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


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-18 04:01:04 UTC
AI_ONLY_REPORT
package: sssd-2.12.0-1.el10
------
Summary: Access-Control Bypass: `shadowExpire=0` Not Treated as Expired in  
LDAP Shadow Expire Check: an LDAP account marked with `shadowExpire=0` can  
still pass SSSD's shadow-based expiration check and continue authenticating  
in affected configurations.
Requirements to exploit: The attacker needs valid credentials for the  
affected LDAP account, and the deployment must explicitly enable the LDAP  
shadow-expire path with `access_provider = ldap`, `ldap_access_order`  
including `expire`, and `ldap_account_expire_policy = shadow`;  
directory-side controls that independently reject the account would reduce  
or prevent the observed impact.
Component affected: `sssd-2.12.0-1.el10`, LDAP access-control expire path  
in `src/providers/ldap/sdap_access.c`, `sdap_account_expired_shadow()`
Version affected: `sssd-2.12.0-1.el10` when configured with  
`access_provider = ldap`, `ldap_access_order` including `expire`, and  
`ldap_account_expire_policy = shadow`
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:L/PR:L/UI:N/S:U/C:L/I:L/A:N - 5.4 (MEDIUM)
AV:N - Reachable through remote authentication services that rely on  
PAM/SSSD in affected deployments.
AC:L - The bypass follows directly from a single comparison in the  
shadow-expire check.
PR:L - Exploitation requires valid credentials for the expired account.
UI:N - No separate user interaction is required once the attacker  
attempts authentication.
S:U - The flaw affects the same authorization scope that evaluates  
account expiry.
C:L - It can preserve unauthorized access to information available to  
the expired account.
I:L - It bypasses intended account-expiration enforcement and can  
preserve access that should have been revoked.
A:N - No direct service outage or denial-of-service condition is  
established.
Impact: Moderate. This is a real access-control bypass that can allow  
continued use of an account after administrators intended it to be expired,  
but it is configuration-dependent, requires valid account credentials, and  
does not demonstrate unauthenticated compromise, code execution, or  
privilege escalation beyond the affected account. Under Red Hat's severity  
guidance, that is more consistent with Moderate than Important.
Embargo: no
Reason: The issue depends on a specific LDAP shadow-expiry  
configuration and an already valid account, and affected deployments can  
mitigate immediately by avoiding `shadowExpire=0` or enforcing expiry on  
the directory side.
Acknowledgement: Aisle Research
Vulnerability Details: In the LDAP access-control expire path,  
`sdap_account_expired_shadow()` only denies the account when `sp_expire >  
0`:
```c
today = (long) (time(NULL) / (60 * 60 * 24));
if (sp_expire > 0 && today >= sp_expire) {
ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO,
sizeof(SHADOW_EXPIRE_MSG),
(const uint8_t *) SHADOW_EXPIRE_MSG);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
}
return ERR_ACCOUNT_EXPIRED;
}
```
`string_to_shadowpw_days()` accepts `0` as a valid parsed value and uses  
`-1` as the no-expiration sentinel, so `0` is not filtered out as an unset  
value. Because the access check only expires values strictly greater than  
`0`, `shadowExpire=0` falls through and access is granted instead of  
denied. A related LDAP authentication path checks `sp_expire != -1`, which  
treats `0` as expired and highlights the inconsistency in how the shadow  
expiration value is handled.
Steps to reproduce:
1. Configure an SSSD domain with `access_provider = ldap`,  
`ldap_access_order = expire`, and `ldap_account_expire_policy = shadow`.
2. Ensure the target LDAP user has `shadowExpire: 0` and otherwise valid  
authentication credentials.
3. Authenticate to a PAM service backed by SSSD as that user.
4. Observe that access is granted in the affected configuration instead of  
failing with an expired-account result such as `ERR_ACCOUNT_EXPIRED` or  
`PAM_ACCT_EXPIRED`.
Mitigation: Until a fix is available, do not rely on `shadowExpire=0` to  
expire accounts in deployments using `ldap_account_expire_policy = shadow`.  
Use a positive past day value for `shadowExpire`, or enforce account  
disablement or expiration through directory-side controls that do not  
depend solely on this client-side check.
Proposed Fix: The minimal correction is to treat `0` as expired and keep  
`-1` as the only non-expiring sentinel in this code path.
```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
@@ -420,7 +420,7 @@ static errno_t sdap_account_expired_shadow(struct  
pam_data *pd,
   if (sp_expire > 0 && today >= sp_expire) {
+    if (sp_expire >= 0 && today >= sp_expire) {
          ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO,
                                 sizeof(SHADOW_EXPIRE_MSG),
                                 (const uint8_t *) SHADOW_EXPIRE_MSG);
```


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