[ Hacker Night School ] :: Exploiting sudo: Altering your PATH

This entry is part 15 of 34 in the series [ Hacker Night School ]

You don’t have to know C extensively to learn hacking, but you do need to know how to figure out how the code works. Consider this piece of C code:

    #include <sys/types.h>
    int main(void)
        setreuid(geteuid(), geteuid());
        system("ls ./user.txt");
        return 0;

See that setreuid function? It sets the real and effective user ID (UID) for the running environment. First, do your G-level research (Google) and look up theĀ setreuid function. In this case we’re setting both real and effective user to root. Of course this code needs to be compiled, in this case into an executable I’ll call listit.

Why do this, and why do it in C? If we want a script or program to run as root, can’t we just set user ID (SUID) on the file, so that a long listing looks like this (note the s in the user permissions):

-r-sr-x---  1 root hackers_group 7252 May 19 18:34 listit

Won’t the compiled executable listit run as root anyway?

Unfortunately (for us), in modern shells, shell scripts can be invoked as root, but shells disallow the commands within the executable from being run as root. This is a compiled binary though, which Linux WILL allow to run with rootly permissions – as long as the user is set to root WITHIN the compiled code.

So what we do here is run the script and see its output, which will just produce the output:


In other words, the system() call in the C code invokes a shell command (that’s what a system call is). It’s not very useful to us, though. Wouldn’t it be handy if we could invoke something like cat when the command ls is run?

You can, because terminal shells allow you (in most cases) to change your environment variables. In this case, we want our PATH to include a directory where we’ve put a link to the cat binary but named it ls:

ln -s /bin/cat /tmp/ls

So far so good. Now we need to change our PATH so that /tmp appears at the beginning of it:

export PATH=/tmp:$PATH
echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin: ....

Now, when we run the binary listit, it will run with the permissions of root, but it will use MY environment, in which /tmp is the first directory searched for a command!

Thus when I run listit, and it calls ls, it will instead run my linked copy of cat in the /tmp directory. Ultimately, if I can find a SUID executable, I may be able to hijack its function by changing my PATH variable and substituting a call to another command.

You’ll find this highly useful in both security auditing and Capture the Flag situations. Have fun!