27

我需要以 root 身份运行 bash 脚本(无密码 sudo 或 su 不可行),并且由于您无法在 Linux 中设置脚本,因此我考虑从可执行文件中调用它并将设置为setuid:

$ cat wrapper.c
int main(void)
{
        system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ sudo chown root wrapper
$ sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$

这有效 - 就像正确运行脚本一样 - 但脚本以执行“./wrapper”的用户身份运行。

为什么?以及如何正确实现这一点?

谢谢!

4

5 回答 5

44

由于suid可执行文件上的位仅更改可执行文件将运行的有效 UID (EUID),而不是getuid()返回的真实 UID (RUID),并且除了对suid解释脚本(任何以“”开头的可执行文件#!)的限制之外,一些 shell就像bash在这种情况下额外的安全措施会将 EUID 设置回 RUID,您需要setuid(0)在执行脚本之前在 C 代码中使用调用。

请参阅、、 和的man页面,setuid了解真实有效的 UID 的确切语义。seteuidgetuidgeteuid

警告)当然,这是一个恰当的点,即suid在许多 Unix 系统、shell 和解释器中对脚本的限制是有原因的,那就是如果脚本在清理其输入和状态方面不是很小心当它被执行时,它们是危险的并且可以被用于安全升级。因此,在执行此操作时要非常小心。尽可能严格地设置对脚本和包装器的访问,只允许您打算执行的这个非常特定的脚本,并在启动脚本之前清除 C 程序中的环境,设置环境变量PATH以准确包含以正确的顺序是必需的,并且没有可写给其他人的目录。

于 2009-02-17T10:19:45.067 回答
7

这里要注意的另一件事是,这里的限制来自 bash 而不是 *nix 系统本身。Bash 实际上对 SUID 脚本进行验证,以仅使用 EUID root 执行它们。如果您使用较旧的贝壳,您通常会得到您想要的开箱即用的东西。例如, sh 不会进行这种验证:

$ cat wrapper.c
int main(void)
{
            system("/bin/sh -c whoami");
}

$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:15 wrapper
$ ./wrapper
root

使用 bash:

$ cat wrapper.c
int main(void)
{
            system("/bin/bash -c whoami");
}

$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:18 wrapper
$ ./wrapper
skinp

尽管如此,汤姆的回答通常是为 SUID 根程序制作包装器的方法

于 2009-02-17T14:18:32.607 回答
3

在脚本中添加 setuid(0) 并编译它。在此之后它应该起作用。

$ cat wrapper.c 
int main(void) 
{ 
        setuid(0);
        system("/bin/bash ./should_run_as_root.sh"); 
} 
$ gcc -o wrapper wrapper.c 
$ sudo chown root wrapper 
$ sudo chmod ug+s wrapper 
$ ll wrapper 
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper 
$ 
于 2010-05-06T08:37:53.090 回答
1

这些示例非常不安全,并且允许具有两种知识的任何人以 setuid 用户身份运行他们想要的任何程序。

除非您首先清理环境,否则永远不要通过 shell,这里显示的大多数示例都容易在运行之前设置 IFS 和 PATH。

于 2012-01-03T11:36:27.503 回答
0

为什么 sudo 不可行?它避免了严重的安全漏洞,例如:

bash-3.2$ cat test
#!/bin/bash
echo ima shell script durp durp
bash-3.2$ chmod +x test
bash-3.2$ ./test
heh heh
bash-3.2$ 

由于环境没有得到适当的消毒,例如在这种情况下:

export echo='() { builtin echo heh heh; }'

sudo 清理了这种情况,也许还有其他边缘情况和陷阱,最好不要写入自定义 suid 包装器。

于 2011-11-03T23:42:44.833 回答