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')