setuid(0)和系统失败

时间:2011-06-07 16:47:17

标签: c linux root setuid

我有一个在C中运行的程序。这需要使用system执行“iptables”命令。

我试过

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

setuid和系统不共存。来自系统手册页

  

不要使用程序中的system()   使用set-user-ID或set-group-ID   特权,因为奇怪的价值观   对于一些          环境变量可能用于破坏系统完整性。   使用exec(3)系列函数   代替,          但不是execlp(3)或execvp(3)。事实上,system()不会起作用   适当的程序与   set-user-ID或set-          / bin / sh为bash的系统上的group-ID权限   版本2,因为bash 2下降   启动时的权限。          (Debian使用修改后的bash,当调用时不会这样做   SH)

我怎样才能克服我的问题?

由于

3 个答案:

答案 0 :(得分:4)

system()将与setuid()一起使用,但这就是问题:主要的安全风险。问题是system()使用任何适当的环境启动shell(bash,sh等),当你打算运行“iptables”时,我的PATH可以指向我自己的iptables版本,我很容易说服你以root身份为我而战。您似乎可以通过使用iptables的完整路径来解决这个问题,但是可以使用其他环境变量(例如LD_PRELOAD_PATH)来说服工具加载恶意共享库 - 再次以root身份运行并不是预期的。

对于您需要安全地执行的操作,您必须使用其中一个exec()系列,并且您必须控制其操作环境。还有其他事情要求安全滥用。 http://pubs.opengroup.org/onlinepubs/009695399/functions/environ.html似乎是了解更多内容的好地方。

答案 1 :(得分:2)

为什么需要使用system()man page正在告诉您该做什么:

  

请改用exec(3)系列功能,但不能使用execlp(3)execvp(3)

您可能也会对fork(2)wait(2)系统调用感兴趣。

答案 2 :(得分:2)

这样的事可能会有所帮助。这是未经测试但应该有效。

    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;
    }