我正在尝试编写一个程序,该程序将在不提示输入密码或确认的情况下快速关闭笔记本电脑。笔记本电脑运行的是 Linux,特别是 Manjaro。
为此,我正在尝试制作一个使用固定参数执行的setuid
可执行文件(并且还生成一个 shell)。我在这里只是为了保持程序简短,从安全的角度来看这是一个糟糕的主意。downnow
shutdown
system
// downnow.c
#include <stdlib.h>
int main() {
system("shutdown --no-wall --halt now");
return 0;
}
然后我编译downnow
,把它移到/bin
,改变它的所有者并给它 setuid 和 setgid 权限:
$ sudo chown root /bin/downnow
$ sudo chgrp root /bin/downnow
$ sudo chmod u+s /bin/downnow
$ sudo chmod g+s /bin/downnow
但是,当我尝试以downnow
非特权用户身份执行时,它无法与 systemd 通信。
$ downnow
Failed to halt system via logind: Interactive authentication required.
Failed to talk to init daemon.
ch{own,grp,mod}
我在ing之前和之后收到相同的消息。
stat
/bin/downnow
在和上报告相同的权限/usr/bin/sudo
。
$ stat /bin/downnow
File: /bin/downnow
Size: XXXX Blocks: XX IO Block: XXXX regular file
Device: XXXXX/XXXXX Inode: XXXXXX Links: 1
Access: (6755/-rwsr-sr-x) Uid: ( 0/ root) Gid: ( 0/ root)
$ stat /usr/bin/sudo
File: /usr/bin/sudo
Size: XXXXXX Blocks: XXX IO Block: XXXX regular file
Device: XXXXX/XXXXX Inode: XXXXXXX Links: 1
Access: (4755/-rwsr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
为什么在完美运行downnow
时可能无法提升其特权?sudo
设置权限位仅允许您的应用程序使用该
setuid
调用,并且它本身不会更改您的权限。为此,您需要将 uid 设置为setuid(uid_t uid)
. 有关详细信息,请参见手册页:https ://linux.die.net/man/2/setuid您可以使用
geteuid()
获取当前有效的uid(即具有setuid 权限的文件的所有者)。参见手册页:https ://linux.die.net/man/2/geteuid例子:
可能是因为没有
setuid(2)
来电。这是这样一个电话的前后对比:此外,您的包装器也不是很安全;希望它不会逃到多用户系统。避免不必要的 shell 调用可能会更安全(除非你喜欢 shellshock 类型的漏洞或重复环境变量的奇怪处理,比如说
bash
......),而是使用exec(3)
调用来直接替换你的进程shutdown
:之后几次意外关机...