从 setuid root C 程序调用脚本 - 脚本不以 root 身份运行

发布于 2024-07-14 11:46:16 字数 468 浏览 4 评论 0原文

我需要以 root 身份运行 bash 脚本(无密码 sudo 或 su 不可行),并且由于您无法在 Linux 中设置脚本的 uid,所以我考虑从可执行文件中调用它并设置 it 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”的用户身份运行。

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

谢谢!

I need to run a bash script as root (passwordless sudo or su not viable) and since you cannot setuid a script in Linux, I thought about calling it from an executable and making it 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
$

This works - as in runs the script correctly - but the script runs as the user who executes "./wrapper".

Why? And how to correctly implement this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

掐死时间 2024-07-21 11:46:16

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

请参阅 setuidseteuidgetuidgeteuidman 页来了解了解真实有效的 UID 的确切语义。

警告)当然,这是一个适当的观点,需要指出的是,许多 Unix 系统、shell 和解释器中对 suid 脚本的限制是有原因的,那就是如果脚本在执行时没有非常小心地清理其输入和环境状态,那么它们是危险的,并且可以被利用来进行安全升级。 因此,执行此操作时要非常小心。 尽可能严格地设置对脚本和包装器的访问权限,仅允许执行您打算执行的非常具体的脚本,并在启动脚本之前清除 C 程序中的环境,设置环境变量,例如 PATH< /code> 以正确的顺序准确包含必需的内容,并且没有其他目录可写的目录。

Since the suid bit on executables only changes the effective UID (EUID) the executable will run as, and not the real UID (RUID) which getuid() returns, and in addition to the restriction on suid interpreted scripts (any executable beginning with "#!"), some shells like bash as an extra safety measure will set the EUID back to the RUID in this case, you will need to use the call setuid(0) in the C code before executing the script.

See the man pages of the setuid, seteuid, getuid, and geteuid to learn the exact semantics of the real and effective UIDs.

(WARNING) Of course, this is an appropriate point to mention that the restriction on suid scripts in many Unix systems, shells and interpreters, are there for a reason, which is that if the script is not very careful about sanitizing its input and the state of environment when it is executed, they are dangerous and can be exploited for security escalation. So be very careful when doing this. Set the access to your script and wrapper as strict as you can, only allow this very specific script which you intend to be executed, and clear the environment within your C program before starting the script, setting environment variables such as PATH to contain exactly what is necessary in the right order and no directories that are writable to others.

一个人的夜不怕黑 2024-07-21 11:46:16

这里要注意的另一件事是,这里的限制来自 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

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

Another thing to note here is that the limitation here is from bash and not the *nix system itself. Bash actually make verifications on SUID scripts to only execute them with EUID root. If you take older shells, you will often get what you wanted out of the box. For example, sh doesn't make this kind of verifications:

$ 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

With 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

Still, Tom's answer is generally the way to go for making a wrapper for SUID root programs

若能看破又如何 2024-07-21 11:46:16

在脚本中添加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 
$ 

Add the setuid(0) in the script and complie it. It shoudl work after this.

$ 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 
$ 
千紇 2024-07-21 11:46:16

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

除非先清理环境,否则切勿通过 shell,此处显示的大多数示例都容易受到在运行之前设置 IFS 和 PATH 的影响。

The examples are horribly insecure and allows anyone with two bits of knowledge to run any program they want as the setuid user.

Never go through a shell unless you sanitize the environment first, most of the examples shown here are vulnerable to having IFS and PATH set before running it.

故事还在继续 2024-07-21 11:46:16

为什么 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 包装器。

Why is sudo not viable? It avoids raging security holes such as:

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$ 

Due to the environment not being properly sanitized, for example in this case:

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

sudo sanitizes this case, and perhaps other edge cases and gotchas that would be well not to write into a custom suid wrapper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文