我需要以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
$
Run Code Online (Sandbox Code Playgroud)
这有效 - 就像正确运行脚本一样 - 但脚本以执行"./wrapper"的用户身份运行.
为什么?以及如何正确实现这一点?
谢谢!
Tom*_*erg 42
由于suid上可执行位仅改变有效的UID(EUID)的可执行文件会运行,而不是真正的UID(RUID),它getuid()返回,并且除了在限制suid解释脚本(任何可执行年初" #!"),有些炮弹像bash作为一个额外的安全措施将设置EUID回RUID在这种情况下,你需要使用呼叫setuid(0)执行脚本之前的C代码.
查看man该页面setuid,seteuid,getuid,和geteuid学习真实有效的UID的精确语义.
(警告)当然,这是一个适当的提点,关于限制suid在许多Unix系统,炮弹和翻译剧本,是有原因的,这是如果脚本不是很小心消毒它的输入和状态在执行环境时,它们是危险的,可以被利用来进行安全升级.这样做时要非常小心.尽可能严格地设置对脚本和包装器的访问权限,只允许执行这个非常具体的脚本,并在启动脚本之前清除C程序中的环境,设置环境变量,例如PATH准确包含什么是必须按正确的顺序,没有可写给他人的目录.
这里要注意的另一件事是这里的限制来自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
Run Code Online (Sandbox Code Playgroud)
用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
Run Code Online (Sandbox Code Playgroud)
尽管如此,汤姆的答案通常是为SUID根程序制作包装器的方法