REDHAT-BUG-2511388: 389 Project 389 Directory Server (389-ds-base) vulnerability
A flaw was found in 389 Directory Server (389-ds-base). During SASL PLAIN authentication, the idssaslcanonuser() function writes the resolved bind DN into a Cyrus SASL auxiliary property (propset) on every canonicalization attempt, including failed ones. A failed one-shot PLAIN exchange does not trigger SASL-context recreation in idssaslcheckbind() -- that only happens when CONNFLAGSASLCOMPLETE or continuing is already set. A subsequent successful SASL bind on the same connection retrieves the auxiliary property via propgetnames() and unconditionally trusts only the first stored value (dnval[0].values[0]), with no check on which SASL mechanism completed the second exchange and no check that the value corresponds to the identity actually just authenticated.
An unprivileged remote attacker can exploit this with zero valid credentials: first send a SASL PLAIN bind as cn=Directory Manager with an incorrect password (fails as expected, but leaves the Directory Manager DN in slot 0 of the auxiliary property), then complete a SASL ANONYMOUS bind on the same connection. The server installs the stale Directory Manager identity instead of the anonymous identity, granting full Directory Manager authority. This was independently confirmed by Red Hat Product Security in an isolated, network-disconnected sandbox against 389-ds-base-2.9.0: "Who Am I?" returned "cn=directory manager", and the Directory-Manager-only cn=config attribute nsslapd-rootdn became readable. The same stale-identity mechanism also allows escalation via a valid low-privileged account's own successful second bind (originally reported variant, requiring one valid account), independently reproduced against the reporter's own PoC.
Root cause: ldap/servers/slapd/saslbind.c, idssaslcanonuser() (identity write, unconditional per mechanism) and idssaslcheckbind() (identity read-back and installation, no mechanism check, no freshness check). Verified directly against commit 33c0e0115c03017ba94ee02f144383704de32a25; unchanged since a September 2024 logging-format cleanup.