Search code examples
securityubuntuubuntu-12.04privileges

Does system() syscall drop privileges?


I am doing some experiments about Linux permissions, using Ubuntu 12.04 (64bit).

I created the following program.

#include<stdio.h>
#include <unistd.h>    
main(){   
    printf("euid=%4d uid=%4d egid=%4d gid=%4d\n", geteuid(), getuid(),getegid(),getgid());
    system("id");
}

and I set its executable as a setuid/setgid file:

-rws--s--x 1 root  root   8638 Apr 28 02:00 pt*

When it is run from an unprivileged user, I get as output:

euid=   0 uid=1001 egid=   0 gid=1001
uid=1001(test1) gid=1001(test1) euid=0(root) egid=0(root) groups=0(root),1001(test1)

I would expect that after the use of the system() syscall root privileges would have been dropped (and this is the reason why shellcodes usually use execv() instead of system() ), but this is not the case.

Can you explain me why?

Thank you.


Solution

  • system() does not drop (or add, or change) any privileges. It is not documented to do so, and there shouldn't be anything about its implementation or usage that suggests that it does. I'm not sure why you assumed that it would.

    I assume that "shellcodes" (malicious exploit code) prefer execv() for the following two reasons:

    • system()'s function is to fork a new process, spawn a shell with a given command line, and wait for it to finish. shellcodes don't need to fork a process and wait for it, and they don't need to introduce an extra shell for parsing a command line.
    • execv(2) is a system call whereas system(3) is a library function. Code introduced from the outside would need to correctly guess the address at which the implementation of a library function lives in order to call it. But to call a system call they just need the syscall number and to invoke the right magic (platform-specific) machine instructions to trap to the kernel.