system() vs execve()

Jake picture Jake · Dec 12, 2014 · Viewed 17.6k times · Source

Both system() and execve() can be used to execute another command inside a program. Why in set-UID programs, system() is dangerous, while execve() is safe ?

Answer

cuonglm picture cuonglm · Dec 12, 2014

system will call the shell (sh) to execute the command sent as an argument. The problem with system because the shell behavior depends on the user who run the command. A small example:

Creating a file test.c:

#include <stdio.h>

int main(void) {
    if (system ("ls") != 0)
        printf("Error!");
    return 0;
}

Then:

$ gcc test.c -o test

$ sudo chown root:root test

$ sudo chmod +s test

$ ls -l test
-rwsr-sr-x 1 root root 6900 Dec 12 17:53 test

Creating a script called ls in your current directory:

$ cat > ls
#!/bin/sh

/bin/sh

$ chmod +x ls

Now:

$ PATH=. ./test
# /usr/bin/id
uid=1000(cuonglm) gid=1000(cuonglm) euid=0(root) egid=0(root) groups=0(root),
24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),105(scanner),
110(bluetooth),111(netdev),999(docker),1000(cuonglm)
# /usr/bin/whoami
root

Oops, you got a shell with root privileges.

execve does not call a shell. It executes the program that passed to it as first argument. The program must be a binary executable or a script start with shebang line.