简体   繁体   中英

setuid(0) and system fails

I have a program running in C. This needs to execute an "iptables" command using system.

I tried

setuid(0); 
system("iptables .... ");

setuid and system do not coexist. from the system man page

Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set- group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)

how can I overcome my problem?

Thanks

system() will work in conjunction with setuid() but that's the problem: major security risk. The problem is system() starts a shell (bash, sh, etc.) using whatever environment is in place, and when you intend for it to run "iptables", my PATH could point to my own version of iptables which I could easily convince you to run for me, as root. You can seem to solve that by using a full path to iptables, but other environment variables (LD_PRELOAD_PATH, for example) can be used to convince tools to load rogue shared libraries -- again, running things as root which were not intended.

For what you need to do, securely, you must use one of the exec() family, and you must take control over its operating environment. Anything else is asking for security abuse. http://pubs.opengroup.org/onlinepubs/009695399/functions/environ.html appears to be a good place to learn more.

Why do you need to use system() ? The man page is telling you exactly what to do:

Use the exec(3) family of functions instead, but not execlp(3) or execvp(3) .

You will probably be interested in the fork(2) and wait(2) system calls as well.

Something like this might help. It's untested but should work.

    char * const argv[] = {"/sbin/iptables", "-L", NULL};

    pid = fork();
    switch (pid) {
            case -1:
                    /* handle error */
            case 0:
                    execv("/sbin/iptables", argv);
                    /* handle error if you get here */
            break;
            default:
                    waitpid(pid, &status, 0);
                    /* check waitpid return code */
            break;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM