Bug 2529332 (CVE-2026-86345)

Summary: CVE-2026-86345 389-ds-base: 389-ds-base: StartTLS plaintext-buffer retention allows on-path attacker to forge an LDAP client's authentication result
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: aadhikar, bsmejkal, jachapma, lryznaro, mreynolds, msauton, progier, rhel-process-autobot, security-response-team, snegrini, spichugi, tbordaz, vashirov, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in 389-ds-base. The server does not discard plaintext bytes already buffered from a client connection when negotiating StartTLS, allowing an on-path attacker to inject a crafted LDAP message that is processed after the TLS upgrade and whose response is delivered to the client in place of the client's own pending operation's response, due to messageID collision. This can cause a client application to treat a failed authentication (bind) attempt as successful.
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: 2544691    
Bug Blocks:    
Deadline: 2026-10-01   

Description OSIDB Bzimport 2026-09-07 09:22:53 UTC
A flaw was found in 389-ds-base. When a client negotiates StartTLS, the server (start_tls_io_enable() in start_tls_extop.c) replaces the connection's underlying socket with a TLS-wrapped one but does not discard or invalidate plaintext bytes already buffered from the socket (c_buffer_bytes/c_buffer_offset in connection.c), which are otherwise only reset on a BER parse error or after a fresh read -- neither of which occurs during the StartTLS transport switch. An on-path (man-in-the-middle) attacker can place a second LDAP message in the same TCP segment as the client's StartTLS request; after the server switches to TLS, it parses this smuggled message out of the stale plaintext buffer (openldap_read_function() in connection.c serves bytes from c_buffer regardless of which underlying descriptor is active) and writes the response inside the new TLS session. By stamping the smuggled message with the messageID the client's next operation (its bind) will use, the attacker's smuggled BindResponse (e.g. an anonymous bind, which always succeeds) is delivered to the client in place of the real bind response, which the connection's turbo-mode single-operation guard does not catch because the smuggled bytes are not yet a tracked Operation object. This causes the client to believe an authentication attempt succeeded when the directory actually rejected it. The default configuration is affected (nsslapd-connection-buffer defaults on; nsslapd-minssf defaults to 0); no misconfiguration is required. Independently reproduced against the real, shipping 389-ds-base-2.6.1-6.el9_6 build: a wrong-password LDAP bind is forged into a reported success, and separately, using a custom PAM test harness exercising the real pam_authenticate/pam_acct_mgmt/pam_open_session lifecycle against real libldap, a full PAM login session is opened for an existing account with a definitively wrong password. Server-side, 389-ds-base itself suffers no privilege escalation or data exfiltration -- the attacker's own smuggled operation runs anonymous and the client's own subsequent (failing) bind resets the connection to anonymous immediately after. The impact is realized entirely in client-side applications that trust the LDAP bind result (e.g. PAM/nss-pam-ldapd), and the affected clients are not required to have any particular parsing flaw of their own -- both a smuggled BindRequest (any LDAP client) and, per a related but separately-reported OpenLDAP client issue, a smuggled SearchRequest are viable. StartTLS on port 389 is affected; ldaps:// (636) has no cleartext prefix and is not affected.