arrow-left arrow-right brightness-2 chevron-left chevron-right circle-half-full dots-horizontal facebook-box facebook loader magnify menu-down rss-box star twitter-box twitter white-balance-sunny window-close
Linux Privilege Escalation - SUID/SGID Executables
3 min read

Linux Privilege Escalation - SUID/SGID Executables

Linux Privilege Escalation - SUID/SGID Executables

SUID is a special file permission for executable files which enables other users to run the file with effective permissions of the file owner. Instead of the normal x which represents execute permissions, you will see an s (to indicate SUID) special permission for the user.

SGID is a special file permission that also applies to executable files and enables other users to inherit the effective GID of file group owner. Likewise, rather than the usual x which represents execute permissions, you will see an s (to indicate SGID) special permission for group user.

If the file is owned by root, it gets executed with root privileges, and we may be able to use it to escalate privileges.

List of all SUID and SGID Executables

Known Exploits

SUID/SGID files can have vulnerabilities that can be exploited to gain root shell. Some exploits can be found using Searchsploit, Google, and GitHub, in the same way with Kernels and Services.

Note that one of the SUID in the list is /usr/sbin/exim-4.84-3. Exim is one of the popular mail transfer agents that is known for having many security vulnerabilities.

A local privilege escalation exploit matching this version of exim can be found in searchsploit.

Copy the exploit script, transfer it to the target machine and run the exploit.


Shared Object Injection

Once a program is executed, it will seek to load the necessary shared objects. We can use a program called strace to track the shared objects that being called. If a shared object were not found, we can hijack it and write a malicious script to spawn a root shell when it is loaded.

One of the SUID in the list is /usr/local/bin/suid-so and is vulnerable to shared object injection.

Run the strace and you'll notice the last shared object that is not found and located at /home/user which is the folder we can write to.

Next step is to create a .config directory and create a libcacl.c file with the following script:

#include <stdio.h>
#include <stdlib.h>

static void inject() __attribute__((constructor));

void inject() {
        setuid(0);
        system("/bin/bash -p");
}

Then compile it and the output should be the same file name (shared object) that is being called by the SUID.

Execute the executable file /usr/local/bin/suid-so and you should get the root shell!


PATH Environment Variable

The PATH environment variable contains a list of directories where the shell should try to find programs. If a program tries to execute another program, but only specifies the program name, rather than its full (absolute) path, the shell will search the PATH directories until it is found.

For this demonstration, we will be using the /usr/local/bin/suid-env. Running it seems to be trying to start the apache2 webserver.

Next step is to check if a program tries to execute another program. For this, we can use several tools such as string, strace and ltrace.

The strings command returns service apache2 start which shows that the service executable is being called to start the apache2 web server, however the full path of the executable (/usr/sbin/service) is not being used.

We can exploit it by creating a script with the following content:

int main() {
        setuid(0);
        system("/bin/bash -p");
}

Then compiling it to create a service executable file.

Finally, prepend the directory where the new service executable is located to the PATH variable and execute the SUID file to spawn a root shell.