// Moderate (7.5)
CVE-2026-11770

Pre-auth LDAP filter injection via CleanAllRUV status check extended operation

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

Summary

A vulnerability in the 389 Directory Server’s replication subsystem allows an unauthenticated remote attacker to extract sensitive server configuration data by injecting arbitrary LDAP search filters into a replication status-check extended operation. The affected handler multisupplier_extop_cleanruv_check_status() lacks any authentication or authorization checks, making it reachable via anonymous bind with default server configuration (nsslapd-allow-anonymous-access: on). The binary response to injected filters creates a boolean oracle that enables character-by-character extraction of 31 configuration attributes from the server’s cn=config subtree, including replication bind DNs, filesystem paths, password storage schemes, and ACI keywords.

Affected Versions

PackageVersionStatus
389-ds-base (upstream)1.3.x through currentVulnerable (confirmed)
389-ds-base (RHEL 7 ELS)1.3.xVulnerable (confirmed, PoC tested)
389-ds-base (RHEL 8)1.4.xVulnerable (code present)
389-ds-base (RHEL 9)2.xVulnerable (code present)
389-ds-base (RHEL 10)3.xVulnerable (code present)
389-ds-base (Fedora 42)3.1.xVulnerable (confirmed, replication bind DN extraction tested)

Affected Products

ProductVersionStatus
389 Directory Server (upstream)All with CleanAllRUVAffected
Red Hat Directory Server 10-1310.x through 13.xAffected
RHEL 7 (IdM/FreeIPA)7.0 through 7.9 ELSAffected
RHEL 8 (IdM/FreeIPA)8.0 through 8.10Affected
RHEL 9 (IdM/FreeIPA)9.0 through 9.6+Affected
RHEL 10 (IdM/FreeIPA)10.0 through 10.1Affected
Fedora39 through 43Affected

Root Cause

File: ldap/servers/plugins/replication/repl_extop.c:1840-1885 Function: multisupplier_extop_cleanruv_check_status()

The function processes a REPL_CLEANRUV_CHECK_STATUS_OID (2.16.840.1.113730.3.6.8) extended operation by decoding a filter string from the BER request payload via decode_cleanruv_payload() and passing it unsanitized to an internal LDAP search against cn=config with the replication plugin’s elevated identity:

if (decode_cleanruv_payload(extop_payload, &filter)) {
    /* error handling */
    goto free_and_return;
}

search_pb = slapi_pblock_new();
slapi_search_internal_set_pb(search_pb, "cn=config", LDAP_SCOPE_SUBTREE,
    filter, NULL, 0, NULL, NULL,
    repl_get_plugin_identity(PLUGIN_MULTISUPPLIER_REPLICATION), 0);
slapi_search_internal_pb(search_pb);

Three design flaws compound the injection:

  1. Missing authentication: The handler performs zero bind DN or authorization checks. Compare with multisupplier_extop_StartNSDS50ReplicationRequest() at lines 838-841, which explicitly calls replica_is_updatedn().

  2. Privileged search identity: The search executes with repl_get_plugin_identity(PLUGIN_MULTISUPPLIER_REPLICATION), bypassing the ACL framework that would normally restrict access to sensitive cn=config attributes.

  3. Boolean oracle response: The function returns CLEANRUV_FINISHED (no entries matched) or CLEANRUV_CLEANING (entries matched), creating a deterministic boolean oracle from the injected filter’s result.

Proof of Concept

Two PoC scripts are provided.

PoC 1: Filter Injection Oracle

poc/021-cleanruv-filter-injection.py

Full 5-phase demonstration of the boolean oracle: baseline confirmation, attribute presence probing, substring extraction, password limitation confirmation, and plugin enumeration. All phases execute without authentication.

pip install ldap3
python3 poc/021-cleanruv-filter-injection.py <host> [port]

PoC 2: Pre-Auth Recon

poc/021-preauth-recon.py

Lightweight PoC demonstrating the BER payload construction and oracle concept. Supports offline demonstration mode (no server required) and live testing.

python3 poc/021-preauth-recon.py              # offline demo
python3 poc/021-preauth-recon.py <host>       # live test

Extractable Information

The oracle enables extraction of 31 configuration attributes from cn=config pre-auth, including:

AttributeAttack Value
nsDS5ReplicaBindDNReplication bind DN, target for credential attacks
nsslapd-rootdnDirectory Manager username
passwordStorageSchemeHash algorithm, determines brute-force viability
nsslapd-localhostServer hostname
nsslapd-certdirCertificate directory path
nsslapd-suffixDatabase suffix (DIT structure)
nsslapd-localuserOS user running ns-slapd
aciACI rule keywords (access control posture)
nsslapd-pluginpathPlugin .so names

Password hash values (nsslapd-rootpw) and replication credentials (nsds5ReplicaCredentials) can be detected via presence checks but resist substring extraction due to their attribute syntax definitions.

Impact

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

ComponentValueJustification
AVNetworkTriggered via LDAP protocol (ports 389/636) over TCP
ACLowDeterministic code path; filter passed through without validation
PRNoneHandler has zero auth checks; anonymous bind suffices with default config
UINoneNo user interaction required
SUnchangedImpact limited to the directory server’s configuration data
CHighComplete read access to 31 string-syntax cn=config attributes via plugin identity (bypassing ACLs)
INoneInjected filter is used in read-only search; no write operations
ANoneSearch does not cause resource exhaustion or crash

Exploit Chain

The oracle enables a multi-step attack against replication infrastructure:

  1. Pre-auth replication detection: (nsDS5ReplicaId=*) confirms replication is configured
  2. Pre-auth bind DN extraction: extract nsDS5ReplicaBindDN character by character (~60 requests, ~2 seconds)
  3. Pre-auth password scheme detection: extract passwordStorageScheme to assess brute-force viability
  4. Online password guessing (theoretical): target the extracted bind DN
  5. Replication channel access (theoretical): if step 4 succeeds, enables access to replication-channel vulnerabilities

Comparable CVEs

CVEDescriptionCVSS
CVE-2022-1949Access control bypass via filter optimizer; unauthenticated read of userPassword hashes7.5
CVE-2020-35518Information disclosure during DN binding; unauthenticated DN existence check5.3
CVE-2016-5416Default ACI readable by anonymous users; leakage of access control configuration7.5

Workaround

  1. Disable anonymous access (most effective, raises PR from None to Low):

    dn: cn=config
    changetype: modify
    replace: nsslapd-allow-anonymous-access
    nsslapd-allow-anonymous-access: rootdse
  2. Network segmentation: Restrict LDAP port access (389/636) to trusted networks.

  3. Monitor for exploitation: Alert on REPL_CLEANRUV_CHECK_STATUS_OID extended operations:

    grep "EXT oid=\"2.16.840.1.113730.3.6.8\"" /var/log/dirsrv/slapd-<instance>/access
  4. Rotate replication credentials and use strong replication passwords.

Proposed Fix

Replace peer-supplied filter with server-side filter construction:

if (decode_cleanruv_payload(extop_payload, &replica_id)) {
    goto free_and_return;
}

if (replica_id < 1 || replica_id > 65534) {
    slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
                  "multisupplier_extop_cleanruv_check_status - "
                  "invalid replica ID: %d\n", replica_id);
    goto free_and_return;
}

filter = slapi_ch_smprintf("(&(nsds5replicaid=%d)(objectclass=nstombstone))", replica_id);

Add replica_is_updatedn() authentication checks to all four CleanRUV handlers:

  • multisupplier_extop_cleanruv_check_status() (this finding)
  • multisupplier_extop_cleanruv()
  • multisupplier_extop_abort_cleanruv()
  • multisupplier_extop_cleanruv_get_maxcsn()

Exploitation in the Wild

No evidence of exploitation in the wild was found.

Timeline

DateEvent
2026-04-15Discovered during 389-ds-base security assessment
2026-04-22Full exploitation assessment completed
2026-04-22Reported to vendor
2026-07-07Public disclosure

References

Credits

Discovered by Ian Murphy