Bugtraq mailing list archives

`sniffit -L mail' vulnerabilities


From: maxx () VIA ECP FR (Michel Kaempf)
Date: Thu, 25 May 2000 15:54:05 +0200


-------[ `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


<HR NOSHADE>
<UL>
<LI>text/x-csrc attachment: 5niffi7.c
</UL>


Current thread: