0

我正在尝试创建一个可以以用户身份运行的关机命令,即 ic,一个不以 root 身份运行的烧瓶网页。听起来很简单,只需shutdown在 SETUID 脚本中输入一个命令即可。因为 SETUID 不适用于 shell 脚本,所以我从 C 程序创建了一个可执行文件。

问题是这在目标机器上不起作用,一个 Raspberry Pi Zero W。我在我的 Ubuntu 20.4 电脑上测试了相同的东西,它运行完美。所以该方法本身似乎是正确的,但存在树莓派问题。

Pi 运行这个操作系统:

cat /etc/issue
-->
Raspbian GNU/Linux 10 \n \l

这是 usershutdown.c :

#include <stdio.h>
#include <stdlib.h>

int main(){
   system("/sbin/poweroff");
}

这些是可执行文件的权限:

-rwsr-xr-x 1 root   root   7988 Dec 20 23:59 usershutdown

我在 /etc/fstab 中检查了根磁盘的挂载选项,并在其中添加,suid并重新启动:

PARTUUID=738a4d67-02  /               ext4    defaults,noatime,suid  0       1

这些是按预期调用 exec 时 Pi 上的错误消息:

$ ./usershutdown 
Failed to set wall message, ignoring: Interactive authentication required.
Failed to power off system via logind: Interactive authentication required.
Failed to open initctl fifo: Permission denied
Failed to talk to init daemon.
$

这就是在 Pi 上起作用的方法,当以 root/sudo 调用 exec 时,与它的 ssh 连接将关闭,并且设备会在没有错误的情况下关闭:

$ sudo ./usershutdown 
$ Connection to picamhq closed by remote host.
Connection to picamhq closed.
$ 

我该如何解决?

4

1 回答 1

1

system()通过 shell 运行程序,从安全角度来看,从任何 setuid 程序运行 shell 都是极其危险的;用户可以通过多种方式劫持它来做其他事情(IFS例如,查找滥用的方式)。为了缓解这种情况,常用的 shell 将尝试注意它们何时在 setuid 下运行(通过注意真实和有效的 uid 不同)并删除特权。

因此,一个更安全的选择是改为运行poweroffvia execle。(execl也可以,但是通过您无法控制的环境变量是有风险的,因此最好让您的程序设置一个已知安全的环境。)

您仍然有一个问题,即任何人都可以运行您的 setuid 程序,因此服务器上的任何非特权本地用户都可以将其关闭。您需要确保它只能由运行您的应用程序的用户执行。由于文件的所有者必须是rootsetuid 才能工作,这将需要与组进行一些杂耍。

你可以避免所有这些麻烦和风险,而是sudo使用. 这将:poweroffNOPASSWD/etc/sudoers

  • 仅将其限制为所需的用户

  • 清洁环境

  • 避免您必须维护额外的 setuid 程序所固有的风险(例如,未来的 libc 错误,或者您想添加功能等)

有关更多信息,请参阅https://unix.stackexchange.com/questions/18830/how-to-run-a-specific-program-as-root-without-a-password-prompt

于 2020-12-21T18:55:45.303 回答