Heap buffer overflow in audit log password masking
- CVE ID
- CVE-2026-11792
- Product
- 389-ds-base
- Severity
- Low (3.3)
- CVSS Vector
- CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:L
- CWE
- CWE-122
- Red Hat CVE
- Red Hat CVE page
Summary
A heap buffer overflow exists in 389 Directory Server’s audit log password masking feature. When audit logging is enabled and a short cleartext password reaches the audit log via an LDAP ADD operation, the server writes a fixed-length mask string past the end of a precisely-sized heap buffer. Exploiting this requires non-default, explicitly discouraged configuration (cleartext password storage) or a compromised replication peer, making real-world impact low.
Affected Versions
| Component | Version | Status |
|---|---|---|
| 389-ds-base (upstream) | 3.2.0+ (post-commit bfeaa8d) | Vulnerable (confirmed — source review) |
| 389-ds-base (upstream) | Pre-July 2025 (before Issue 6884) | Not affected — create_masked_entry_string() does not exist |
| Fedora 43 | 389-ds-base-3.1.4-7.fc43 | Vulnerable (confirmed — live server test) |
| Fedora 42 | 389-ds-base-3.1.2-4.fc42 | Not affected — pre-dates Issue 6884 introduction |
| RHEL 10 / CentOS Stream 10 | 389-ds-base-3.1.3-4.el10+ | Vulnerable (code present — RHEL-107035 backported the password masking feature) |
| RHEL 9.6 | 389-ds-base-2.6.1-11.el9_6+ | Vulnerable (code present — RHEL-109954 backported the password masking feature) |
| RHEL 9.0 - 9.5 | 389-ds-base-2.0.x - 2.5.x | Not affected — pre-dates Issue 6884 backport |
| RHEL 8 | 389-ds-base-1.4.x | Not affected — create_masked_entry_string() does not exist in 1.4.x |
| RHEL 7 | 389-ds-base-1.3.x | Not affected — create_masked_entry_string() does not exist in 1.3.x |
| Red Hat Directory Server 12.6 | 389-ds-base-2.6.x | Vulnerable (RHDS 12.6 = RHEL 9.6 AppStream; same 2.6.1-11 backport) |
| Red Hat IdM (RHEL 9.6+) | Depends on 389-ds-base | Vulnerable (IdM/FreeIPA uses 389-ds-base as its LDAP backend) |
| Red Hat IdM (RHEL 10) | Depends on 389-ds-base | Vulnerable (IdM/FreeIPA uses 389-ds-base as its LDAP backend) |
Version boundary: The vulnerable function create_masked_entry_string() was introduced
upstream by commit bfeaa8d (Issue 6884, PR #6885) in July 2025 and first shipped in
upstream releases 2.8.0 and 3.2.0. It was backported to RHEL 9.6 (RHBA-2025:15534)
and RHEL 10 (389-ds-base-3.1.3-4.el10) as a fix for
CWE-532 (password hashes visible in audit logs).
Architecture note: This vulnerability is architecture-independent. The overflow is a
fixed-size strcpy of 24 bytes into a variable-size buffer slot determined by the password
value length. No pointer size, alignment, or endianness factors affect triggering. Confirmed
on aarch64 (ASan PoC on macOS arm64e and Fedora 42 aarch64).
Root Cause
File: ldap/servers/slapd/auditlog.c:109
Function: create_masked_entry_string()
Verified against: 389-ds-base source at commit b019653 on test system, 2026-04-22
The create_masked_entry_string() function masks password attribute values in audit log
entries for LDAP ADD operations. It receives a buffer from slapi_entry2str() that is
allocated with exact sizing (no padding or slack), then iterates through the LDIF lines
looking for password attributes:
/* auditlog.c line 108-110 */
if (is_password_attribute(line_start)) {
strcpy(colon_pos + 1, " **********************"); /* 23 bytes + NUL = 24 bytes */
}
The mask string is 23 characters plus a NUL terminator (24 bytes total). If the password
value after the colon is shorter than 23 characters, the strcpy writes past the allocated
buffer boundary. For example, userPassword: x has 2 bytes after the colon (" x"), but
strcpy writes 24 bytes, overflowing 22 bytes past the value position.
The buffer comes from slapi_entry2str() (entry.c:1658), which computes elen by summing
the exact byte counts of all attributes and allocates via slapi_ch_malloc(elen) with no
padding.
Why only ADD operations are affected: The MODIFY path (auditlog.c:836-842) uses
addlenstr(), which dynamically grows the buffer. The ADD path (auditlog.c:864-877)
calls create_masked_entry_string(), which modifies the exactly-sized buffer in-place.
Why cleartext passwords are required: For non-replicated ADDs, pw_encodevals_ext()
(add.c:679) hashes the password before the audit log runs, producing ~450-char values
that are always longer than the 23-byte mask. For replicated ADDs (repl_op=1), the
hashing branch (add.c:641-693) is entirely skipped (add.c:628-640), so the password
retains whatever value the replication supplier sent.
All line numbers verified against actual source on test system at
/home/user/src/389-ds-base-src/ on 2026-04-22. strcpy at line 109 confirmed.
ADD path create_masked_entry_string call at line 868 confirmed. repl_op branch at
add.c:628-640 confirmed.
Proof of Concept
PoC source code: CVE-2026-11792 on GitHub
Standalone ASan PoC
The file poc/poc_006_auditlog_repl.c is a self-contained reproduction of the vulnerable
create_masked_entry_string() function. It simulates the exact buffer allocation behavior
of slapi_entry2str() and triggers the overflow with a 1-byte cleartext password.
Compile and run:
gcc -fsanitize=address -g -o poc_006 poc/poc_006_auditlog_repl.c
./poc_006
Expected result: ASan reports heap-buffer-overflow with WRITE of size 24:
==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x...00cd
WRITE of size 24 at 0x...00cd thread T0
#0 ... in strcpy/memcpy
#1 ... in create_masked_entry_string poc_006_auditlog_repl.c:101
0x...00cd is located 0 bytes after 141-byte region [0x...0040,0x...00cd)
Live server test (audit log corruption)
- Deploy a 389-ds-base supplier-consumer replication topology.
- Enable audit logging on both instances:
dsconf slapd-supplier config replace nsslapd-auditlog-logging-enabled=on dsconf slapd-consumer config replace nsslapd-auditlog-logging-enabled=on - Set cleartext password storage on the supplier:
dsconf slapd-supplier config replace passwordStorageScheme=CLEAR - Add a user with a short password:
ldapadd -x -H ldap://localhost:389 -D "cn=Directory Manager" -w <password> <<EOF dn: uid=overflow006,ou=customers,dc=dapperdan,dc=com objectClass: inetOrgPerson uid: overflow006 cn: Overflow Test sn: Test userPassword: x EOF - Expected result: Both supplier and consumer audit logs show corrupted output:
The 23-byte mask overflows past the 1-byte cleartext value. Neither instance crashes (production binary without ASan absorbs the 22-byte overflow in allocator padding), but heap memory is corrupted.userPassword: ***** ****************
Supporting evidence files
| File | Description |
|---|---|
poc/poc_006_auditlog_repl.c | Full PoC source (197 lines, includes diagnostic output) |
poc/asan-trace-006-local.txt | ASan trace from macOS arm64e |
poc/asan-trace-006-container.txt | ASan trace from Fedora 42 aarch64 |
poc/auditlog-testA-supplier-pbkdf2.log | Live server audit log — PBKDF2 default, no overflow |
poc/auditlog-testB-supplier-clear.log | Live server audit log — CLEAR scheme, overflow on supplier |
poc/auditlog-testB-consumer-clear.log | Live server audit log — CLEAR scheme, overflow on consumer via replication |
Impact
CVSS 3.1: 3.3 (Low) — CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:L
| Component | Value | Justification |
|---|---|---|
| AV (Attack Vector) | Network | Replication is network-based; LDAP ADD is network-accessible |
| AC (Attack Complexity) | High | Requires non-default passwordStorageScheme: CLEAR (explicitly discouraged) or a compromised replication peer, AND audit logging enabled (also non-default). Two non-default prerequisites must coincide. |
| PR (Privileges Required) | High | Admin privileges to configure CLEAR scheme; replication manager credentials for compromised peer scenario |
| UI (User Interaction) | None | No user interaction required once configuration is in place |
| S (Scope) | Unchanged | Impact limited to the ns-slapd process |
| C (Confidentiality) | None | No data disclosed by the overflow itself |
| I (Integrity) | Low | Audit log output is corrupted (mask overwrites adjacent data in the log buffer); heap metadata may be corrupted |
| A (Availability) | Low | Heap corruption may cause crash on subsequent allocations/frees; confirmed abort on ASan builds. Production builds absorbed the overflow in allocator padding during testing, but this is not guaranteed. |
Primary impact: The ns-slapd LDAP server process. The heap corruption occurs in a
transient logging allocation that is freed immediately after use (slapi_ch_free at
auditlog.c:877).
Downstream consumers of 389-ds-base:
| Consumer | Relationship | Impact |
|---|---|---|
| Red Hat IdM / FreeIPA | Uses 389-ds-base as its LDAP backend | If IdM enables audit logging with CLEAR scheme, the IdM LDAP backend process is affected. IdM does not use CLEAR scheme by default. |
| Red Hat Directory Server (RHDS) 12.x | Direct packaging of 389-ds-base | Same impact as upstream. RHDS documentation discourages CLEAR scheme. |
| Dogtag Certificate System | Uses 389-ds-base for its internal LDAP store | Dogtag does not store user passwords in CLEAR scheme. Not affected in practice. |
| SSSD / pam_ldap clients | Connect to 389-ds-base as LDAP clients | Not directly affected — the overflow is in the server process, not clients. If the server crashes due to heap corruption, clients lose connectivity (DoS). |
Replication topology impact: In a multi-supplier topology, if one instance crashes due to heap corruption, replication continues between surviving instances. The crashed instance resumes replication after restart. No data loss expected from the overflow itself.
No evidence of exploitation in the wild. The create_masked_entry_string() function was
introduced in July 2025 (less than 1 year ago). The passwordStorageScheme: CLEAR
configuration is explicitly discouraged in 389-ds-base documentation and disabled by default.
Comparable CVEs:
| CVE | Bug class | CVSS | Notes |
|---|---|---|---|
| CVE-2024-1062 | Heap overflow in log_entry_attr() (same file, different function) | 5.5 (Medium) | Values > 256 chars overflowing a fixed buffer; local attack vector, low complexity. This finding has higher complexity (non-default config) and network vector. |
| CVE-2025-14905 | Heap overflow in schema_attr_enum_callback() | 7.2 (Medium) | Different function in schema.c; RCE potential with lower prerequisites. This finding has lower impact (fixed overflow content, transient buffer). |
| CVE-2017-2591 | OOB heap read in attribute uniqueness plugin | Low | DoS via segfault; different bug class (read vs write). |
Workaround
-
Do not use
passwordStorageScheme: CLEAR. The defaultPBKDF2-SHA512produces password hashes longer than 23 characters, preventing the overflow. This is the primary and most effective workaround. -
If CLEAR scheme is required for testing, disable audit logging during the test window:
dsconf slapd-<instance> config replace nsslapd-auditlog-logging-enabled=off -
Monitor replication agreements for unauthorized peers. A compromised replication partner could send crafted ADD operations with short cleartext passwords that bypass password hashing on the consumer.
-
Do not enable audit logging unless required. Audit logging is non-default. If it is not needed for compliance or operational requirements, leaving it disabled eliminates this attack surface entirely.
Proposed Fix
Replace the unsafe strcpy with a bounded copy that respects the available space in the
buffer:
if (is_password_attribute(line_start)) {
const char *mask = " **********************";
size_t mask_len = strlen(mask);
size_t avail = 0;
/* Calculate available space from colon_pos+1 to end of value */
if (next_line != NULL) {
avail = (size_t)(next_line - (colon_pos + 1));
} else {
avail = strlen(colon_pos + 1);
}
if (mask_len <= avail) {
memcpy(colon_pos + 1, mask, mask_len);
/* NUL-fill remaining space to avoid leaking original value */
memset(colon_pos + 1 + mask_len, ' ', avail - mask_len);
} else {
/* Mask is longer than available space -- truncate mask */
memcpy(colon_pos + 1, mask, avail);
}
}
Alternatively, use a dynamically-growing buffer (like the MODIFY path’s addlenstr())
instead of in-place modification of the exactly-sized slapi_entry2str() buffer. This
approach would also fix the related data truncation bug where the strcpy NUL terminator
truncates subsequent LDIF content for long hashed passwords.
Timeline
| Date | Event |
|---|---|
| 2026-04-14 | Discovered during 389-ds-base security assessment |
| 2026-04-15 | Reported to vendor |
References
- Red Hat CVE page
- NVD
- CVE-2024-1062 (related heap overflow in same file)
- Issue 6884 in upstream 3.2.0 release notes
- Issue 6884 in upstream 2.8.0 release notes
- CWE-122: Heap-based Buffer Overflow
- CVSS 3.1 Calculator
Credits
Discovered by Ian Murphy.