Hacking Tricks SUID

Some Hacking Tricks on SUID programs.

A SUID program is a program that will always run as its owner's privilege.

A normal program is the same privilege with its runner, while a SUID program always run as its owner.

A SUID program is -rwsr-xr-x . The forth privilege bit is s.

chmod 4755 file

The above command can turn on the Set-UID bit.

Every Unix program is running in a specific environment, which consists of a table of environment variables.

In C, a program can use getenv() to get the values of environment variables.

In C, system(const char * cmd) function will first invoke the /bin/sh program, and then let the shell execute cmd

Hacking Tricks

Some important environment variables that can be used in penetration testing.

PATH

A hacker can execute following commands to set the current dir as the first item in PATH.

PATH=".:$PATH";
export PATH

IFS

IFS determines the characters which would be interpreted as white space.

IFS="/ \t\n";
export IFS

The above commands would let the '/' as space, which means any program attempt to use an absolute PATH will be translate into spaces.

system("/bin/mail root") —> bin mail root

thus, the hacker can run his own program called bin

However, this bug has been fixed: the invoked new shell process will not inherbit IFS variable.

LD_LIBRARY_PATH

In Linux, most program requires dynamic link libraries at run time.

Dynamic linker/loader: ld.so/ld-linux.so.

ldd /bin/ls

That will list all shared libraries that ls needed.

LD_LIBRARY_PATH contains a set of directories that ld.so will look for runtime libraries.

setenv LD_LIBRARY_PATH .:$LD_LIBRARY_PATH 

Countermeasure

Never use C-shell for SUID scripts

For example, change-pass is a script like this:

#!/bin/csh -b
set user=$1
passwd $user

This script is useful for root user to help changing other users' password.

But for the reason that csh scripts are vulnerable to manipulating environment variables.

The hacker can run follow instructions:

 env TERM='cp /bin/sh /tmp/sh;chown root /tmp/sh; chmod 4755/tmp/sh'
 change-pass

Use Full PATH

Now,we change the script to this one:

#!/bin/ksh
user=$1
passwd $user

This is also vulnerable, because the program uses relative path names

The hacker can run following instructions to run his own program:

export PATH='/tmp'
echo "cp /bin/sh /tmp/sh;chown root /tmp/sh;chmod 4755/tmp/sh" >/tmp/passwd"
./change-pass

Then the script runs /tmp/passwd instead of /usr/bin/passwd

Use bash other than zsh

Take following command for example

cp $(which bash) /tmp && cp $(which zsh) /tmp && cd tmp
chmod u+s /tmp/bash /tmp/zsh

Firstly, run these commands as root

We can see that both bash and zsh 's Set-Uid bit is set.

$ ls -l bash zsh
-rwsr-xr-x 1 root root 1168776 Jan  5 13:28 bash
-rwsr-xr-x 1 root root  861720 Jan  5 13:28 zsh

Switch to a normal user and simply run the binary.

Bash is running as the normal user while Zsh is running as root.

In order to avoid such situation, sometimes developer use setuid for operations that need higher privilege.

Setuid before open it

In C programming language, there is a api named setuid that can change the program's privilege.

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>

int main(){

    int fd;
    fd = open("/tmp/root_file",O_RDWR|O_APPEND);
    sleep(1);
    setuid(getuid());
    pid_t pid ;

    if( ( pid = fork() ) < 0 )
        perror("fork error");
    else if( pid == 0 ){
        // child process
        write( fd , "Hello World!" , 13 );
    }

    int status=waitpid(pid,0,0);
    close(fd);

    return 0;
}

Compile the program and create the root_file that can only modified by root.

$ touch /tmp/root_file
$ gcc test.c -o test
$ chmod u+s test

After that, run test as a normal user

The message has been written into the root_file!

The reason is that the above code called setuid(getuid()) after open('/tmp/root_file')