[17124] in Kerberos-V5-bugs
=?UTF-8?B?W2tyYmRldi5taXQuZWR1ICM5MjMyXSBVc2UtYWZ0ZXItZnJlZSBpbiBsaWJr?=
daemon@ATHENA.MIT.EDU (vidal segura via RT)
Mon Aug 31 16:59:43 2026
From: "vidal segura via RT" <rt-comment@krbdev.mit.edu>
In-Reply-To: <CALtf=54oLkU2N802QkTHDSoz3by_y+MeUh43UKm1YDyxtj4hvA@mail.gmail.com>
Message-ID: <rt-4.4.3-2-2590515-1788209977-1467.9232-4-0@mit.edu>
To: "AdminCc of krbdev.mit.edu Ticket #9232":;
Date: Mon, 31 Aug 2026 16:59:37 -0400
MIME-Version: 1.0
Reply-To: rt-comment@krbdev.mit.edu
Content-Type: text/plain; charset="utf-8"
Errors-To: krb5-bugs-bounces@mit.edu
Content-Transfer-Encoding: 8bit
Mon Aug 31 16:59:37 2026: Request 9232 was acted upon.
Transaction: Ticket created by vidalseguragarcia@gmail.com
Queue: krb5
Subject: Use-after-free in libkdb_ldap (tl_data2berval / free_berdata) — reachable via kadmin, present in master
Owner: Nobody
Requestors: vidalseguragarcia@gmail.com
Status: new
Ticket <URL: https://krbdev.mit.edu/rt/Ticket/Display.html?id=9232 >
Hi krb5 security team,
I'd like to report a use‑after‑free in the LDAP KDB backend, reachable by
an authenticated kadmin client under memory‑pressure conditions. The defect
is present in the current master branch (verified 2026‑08‑31) and appears
latent since at least krb5‑1.16. It was flagged by the Clang Static
Analyzer (scan-build) as one of nine warnings on
plugins/kdb/ldap/libkdb_ldap; the other eight are lower‑severity
reliability issues I'll file separately as a public bug once you've looked
at this one.
Summary. tl_data2berval()
(src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c, ~629–646 in master)
allocates two objects sequentially; when the second malloc fails it frees
the first (free(*out)) but returns without setting *out = NULL. The caller
krb5_ldap_put_principal() breaks the fill loop, leaving ber_tl_data[j]
dangling, then calls free_berdata(ber_tl_data) unconditionally (~line
1386). free_berdata() (459–471) iterates and does array[j]->bv_val (read of
freed memory) then free(array[j]) (double‑free).
Code path (master).
// krb5_ldap_put_principal, ~1364
for (j = 0, ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) {
if (/* skip conditions */) continue;
if ((st = tl_data2berval(ptr, &ber_tl_data[j])) != 0)
break; // ber_tl_data[j] left dangling
j++;
}
if (st == 0) { ber_tl_data[count] = NULL; st =
krb5_add_ber_mem_ldap_mod(...); }
free_berdata(ber_tl_data); // unconditional -> dereferences
dangling slot
// tl_data2berval, ~631
(*out)->bv_val = (char *) malloc((*out)->bv_len);
if ((*out)->bv_val == NULL) {
free(*out); // frees *out but does not NULL it
return ENOMEM;
}
// free_berdata, ~464
for (i = 0; array[i] != NULL; i++) {
if (array[i]->bv_val != NULL) // UAF read of freed struct
free(array[i]->bv_val);
free(array[i]); // double-free of same address
}
Reproduction. Build krb5 with clang and run scan-build on
plugins/kdb/ldap/libkdb_ldap; it reports a Memory error / Use‑after‑free
anchored in ldap_principal2.c free_berdata, entered from
krb5_ldap_put_principal (201‑step trace). git log --all -S 'tl_data2berval'
-S 'free_berdata' shows no fixing commit.
Trigger conditions. An authenticated kadmin client submitting a
modify‑principal operation carrying tl_data extras, where the second malloc
in tl_data2berval (of tl_data_length + 2 bytes) fails while the first (16
bytes) succeeds.
Impact and reachability. The practical impact is a denial of service (crash
on the UAF read / double‑free). A UAF read and double‑free are present as
primitives, but I have not assessed exploitability and, given the
precondition, would not expect reliable exploitation — I mention them only
for completeness. Candidly on reachability: on Linux with default
overcommit malloc rarely returns NULL, so this is not hit in ordinary
operation; it becomes reachable with overcommit disabled, a per‑process
address‑space rlimit, 32‑bit exhaustion, or a tl_data extra large enough to
force the allocation to fail. I'd classify it as a real but
low‑to‑moderate‑severity hardening issue and leave the severity to your
judgement.
Suggested patch (fixes the primitive, so any caller benefits):
if ((*out)->bv_val == NULL) {
free (*out);
+ *out = NULL;
return ENOMEM;
}
I found this while auditing libkdb_ldap with scan-build as part of an
academic report. Happy to provide the full plist trace or the eight
lower‑severity findings. Please treat this as coordinated disclosure — I
won't publish until you've had a chance to release a fix or ask me to.
Regards,
Vidal Segura García
_______________________________________________
krb5-bugs mailing list
krb5-bugs@mit.edu
https://mailman.mit.edu/mailman/listinfo/krb5-bugs