我需要以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"的用户身份运行.
为什么?以及如何正确实现这一点?
谢谢!
由于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
用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根程序制作包装器的方法