Linux privilege escalation using Wildcard Injection


Wildcards are symbols which represent other characters. You can use them with any command such as the cat or rm commands to list or remove files matching a given criteria. There are others, but the one that is important to us right now is the * character, which matches any number of characters.

For example:

  • cat * displays the contents of all files in the current directory
  • rm * removes all files in the current directory

How it works under the hood is that the * character gets expanded to all the matching files. If we have the files a, b and c in our current directory, and we run rm *, then the outcome will be rm a b c.

The problem

As we know, we can pass flags to programs on the command line to indicate how it should run. For example if we use rm -rf instead of just rm then it will recursively and forcefully delete files without further prompting.

Now what would happen if we ran rm * and had a file in the current directory with name -rf? Shell expansion of the * would cause the command to become rm -rf a b c and -rf will be interpreted as a command argument.

This is bad news when a privileged user or script uses wildcards in a command which has potentially dangerous flags, in particular, ones related to external command execution. In these cases we can likely use it to escalate privileges.

Dangerous programs: chown and chmod

Both chown and chmod can be exploited in the same way, so I will only explain chown.

Chown is a program which allows you to change the owner of a specified file. The following example changes the owner of some-file.txt to be some-user:

chown some-user some-file.txt

Chown has a --reference=some-reference-file flag, which specifies that the owner of the file should be the same as the owner of the reference file. An example should help:

chown some-user some-file.txt --reference=some-reference-file

Let’s say the owner of some-reference-file is another-user. In that case, the owner of some-file.txt will be another-user instead of some-user.

Exploitation

Let’s say we have a vulnerable program called vulnerable.sh which contains the following:

cd some-directory
chown root *

In that case, let’s create a file which is owned by us:

cd some-directory 
touch reference

Then we create a file which will inject the flag:

touch -- --reference=reference

If you create a symlink to /etc/passwd in the same directory, then the owner of /etc/passwd will also be you, which will allow you to gain a root shell. For more detailed information about escalating privileges using /etc/passwd, refer to this article.

Dangerous program: tar

Tar is a program which allows you to collect files into an archive.

In tar, there are “checkpoint” flags, which allow you to execute actions after a specified number of files have been archived. Since we can inject those flags with wildcard injection, we can use checkpoints to execute commands of our choosing. If tar is run as the root user, the commands will also be run as the root user.

Given this vulnerability, an easy way to gain root privileges is by making ourselves a sudoer. A sudoer is an user who can assume root privileges. These users are specified in the /etc/sudoers file. By just appending one extra line to that file, we can make ourselves a sudoer as well.

Exploitation

Let’s say we have a vulnerable program and cron is being used to run it periodically. The program contains the following:

cd important-directory
tar cf /var/backups/backup.tar *

The steps to follow for root access are:

1) Inject a flag which specifies our checkpoint

First we will specify that after one file has been archived, there is a checkpoint. We will later give an action to that checkpoint, but for now we will simply tell tar that it exists.

Let’s create the file which will inject the flag:

cd important-directory
touch -- --checkpoint=1

2) Write a malicious shell script

The shell script will append code to /etc/sudoers that will make you a sudoer.

The line you need to add to/etc/sudoers is my-user ALL=(root) NOPASSWD: ALL.

Let’s create the shell script:

echo 'echo "my-user ALL=(root) NOPASSWD: ALL" >> /etc/sudoers' > demo.sh

The shell script should be in the same directory as the wildcard.

Note that we will have to change my-user to be the actual user we want to make a sudoer.

3) Inject a flag which specifies the checkpoint action

We will now specify that, when tar hits the checkpoint we specified at step #1, it should run the shell script we created at step #2:

touch -- "--checkpoint-action=exec=sh demo.sh"

4) Gain root

Wait until cron has executed the script and gain root privileges by typing:

sudo su

Dangerous program: rsync

Rsync is a “fast, versatile, remote (and local) file-copying tool”, that is very common on Unix systems.

Some interesting flags to use with rsync are:

 -e, --rsh=COMMAND           specify the remote shell to use
     --rsync-path=PROGRAM    specify the rsync to run on remote machine

We can use the -e flag to run any shell script we want. Let’s create a shell script which will add us to the sudoers file:

echo 'echo "my-user ALL=(root) NOPASSWD: ALL" >> /etc/sudoers' > shell.sh

Now let’s inject the flag which will run our shell script:

touch -- "-e sh shell.sh"

Mitigation

Although wildcard injection can be extremely dangerous, it is also pretty easy to avoid. Adding the full path of the directory in front of the wildcard is enough to stop the attack.

This is exploitable:

some_command *

But this isn’t:

some_command /path/to/some/folder/*

Conclusion

Using wildcards seems completely safe at first glance, but in reality, we must take great care not to expose ourselves to wildcard injection.

Heino Sass Hallik