2

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

我试过

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

setuid 和 system 不能共存。从系统手册页

不要在具有 set-user-ID 或 set-group-ID 权限的程序中使用 system(),因为某些环境变量的奇怪值可能会被用来破坏系统完整性。请改用 exec(3) 系列函数,但不要使用 execlp(3) 或 execvp(3)。事实上,system() 在 /bin/sh 是 bash 版本 2 的系统上无法从具有 set-user-ID 或 set-group-ID 特权的程序正常工作,因为 bash 2 在启动时会放弃特权。(Debian 使用修改后的 bash,它在作为 sh 调用时不会这样做。)

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

谢谢

4

3 回答 3

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似乎是了解更多信息的好地方。

于 2011-06-07T16:56:40.103 回答
2

为什么需要使用system()手册页确切地告诉您该怎么做:

请改用exec(3)函数族,但不要使用execlp(3)or execvp(3)

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

于 2011-06-07T16:49:41.377 回答
1

这样的事情可能会有所帮助。它未经测试,但应该可以工作。

    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;
    }
于 2011-06-07T17:05:10.203 回答