我对 setuid 二进制文件有一些疑问。我知道它存在一些危险的程序(如果您允许将此程序与 sudo 一起使用,则有可能退出该程序并获得 root shell),例如 ftp、gdb 或 find。例如,如果我可以使用 root 权限创建 sudo ftp,那么我就可以输入 !/bin/bash 并获得 root shell。
所以我认为如果这个二进制文件有 suid 位,那么它也会遇到同样的问题。所以我在自己的电脑上试了一下,问题就出在这里。我把 suid 放在了 /usr/bin/netkit-ftp 上(/usr/bin/ftp 是指向 /usr/bin/netkit-ftp 的符号链接)。以下是ls -l /usr/bin/netkit-ftp
-rwsr-xr-x 1 root root 96968 déc. 6 2016 /usr/bin/netkit-ftp
然后我尝试使用 ftp 并输入 !whoami。结果不是 root(这是我当前的用户名)。
我不明白为什么?如果二进制文件 /usr/bin/netkit-ftp 有 suid 位,它应该以 root 权限执行,不是吗?(那么为什么我的 whoami 没有返回 root 权限?)
谨致:)
答案1
每个进程至少有两个 UID 集(通常为三个或更多)。其中一个是“真实”UID,它决定了哪个用户拥有进程。另一个是“有效”UID,它决定了权限该进程具有。您可以在 Linux 中查找描述凭证(7)。
当“setuid”程序启动时,只有它的“有效”UID 会改变,因此它拥有新的权限,但仍然知道WHO启动它。(这就是 sudo 知道你是谁的方式,即使它是 setuid。)
例子:
$ sudo cp /bin/id /bin/test-id
$ sudo chmod u+s,g+s /bin/test-id
$ ls -la /bin/test-id
-rwsr-sr-x 1 root root 42K Jan 4 11:59 /bin/test-id*
$ /bin/test-id
uid=1000(grawity) gid=1000(grawity) euid=0(root) egid=0(root) groups=1000(grawity),3(sys),4(adm),10(wheel),100(users)
此类新启动的程序将已具有 root 权限。例如,如果您将 setuid 位赋予cat
或less
,则任何用户都将能够读取仅限 root 的文件。
程序可以从两个方向改变此状态:它们可以将两个 UID 都更改为 EUID(完全“成为 root”),或者他们可以将两者都更改为真实 UID(放弃特权并返回到“普通”用户)。我认为须藤执行前者,但您也会经常看到许多程序执行后者。
请注意狂欢shell 也做后者:如果你尝试将 setuid 位赋予/bin/bash
,它将在启动时放弃其 setuid 权限,除非它是使用-p
(--privileged) 选项启动的。您可以在 bash 的标志.c和外壳程序。
这很重要,因为当你!
使用FTP,提供的命令不会直接执行;它实际上是通过 shell 运行的,适用于 shell 的内容也适用于 !-命令。也就是说,什进程由FTP实际上会按照您期望的那样继承 setuid 状态(euid=0),但会在运行提供的命令之前放弃它。
(这意味着输入!/bin/bash
实际上运行了*两个* shell 进程:第一个进程具有正确的 euid 但在启动第二个进程之前放弃了权限。)
你可以通过以下方式测试(并绕过)FTP使用其他东西作为初始 shell:
$ ls -l /bin/id /bin/test-ftp
-rwxr-xr-x 1 root root 42K Aug 19 12:54 /bin/id*
-rwsr-sr-x 1 root root 137K Jan 4 12:08 /bin/test-ftp*
$ SHELL=/bin/id /bin/test-ftp
ftp> !
uid=1000(grawity) gid=1000(grawity) euid=0(root) egid=0(root) groups=0(root),3(sys),4(adm),10(wheel),100(users)
ftp>
(注意:并非所有程序都会查看 $SHELL;有些程序总是使用 /bin/sh,或者根本不使用 shell。)