如何在 Linux 上使用 SUID、SGID 和 Sticky Bits

SUID、SGID 和 Sticky Bits 是您可以为 Linux 上的可执行文件和目录设置的强大的特殊权限。我们将分享使用它们的好处和潜在的陷阱。
他们已经在使用
将安全性构建到多用户操作系统中会遇到一些难题。以密码的(看似)基本概念为例。它们都必须存储起来,这样每次有人登录时,系统都可以将他输入的密码与存储的副本进行比较。显然,密码是王国的钥匙,必须妥善保管。
在 Linux 上,存储的密码以两种方式受到保护:它们被加密,并且只有具有 root
权限的人才能访问包含密码的文件。这听起来不错,但它提出了一个难题:如果只有具有 root
权限的人才能访问存储的密码,那么没有该权限的人如何更改他们的密码?
提升你的地位
通常,Linux 命令和程序以与启动程序的人相同的一组权限运行。当 root
运行 passwd
命令更改密码时,它以 root
的权限运行。这意味着 passwd
命令可以自由访问 /etc/shadow
文件中存储的密码。
理想的方案是系统上的任何人都可以启动 passwd
程序,但让 passwd
程序保留 root
的提升权限特权。这将使任何人都能够更改自己的密码。
上面的场景正是设置用户 ID 位 (SUID
) 所做的。它以文件所有者的权限运行程序和命令,而不是启动程序的人的权限。
您正在提升计划的地位
不过,还有另一个难题。必须防止此人干预其他任何人的密码。 Linux 结合了 SUID
方案,允许它使用一组临时借用的权限运行应用程序——但这只是安全故事的一半。
防止某人使用另一个人密码的控制机制包含在 passwd
程序中,而不是操作系统和 SUID 方案。
以提升的权限运行的程序如果不是以“设计安全”的心态创建的,可能会带来安全风险。这意味着安全是您首先要考虑的事情,然后再以此为基础。不要写你的程序,然后再尝试给它一层安全外衣。
开源软件的最大优势是您可以自己查看源代码或参考可信赖的同行评审。在passwd
程序的源代码中,有检查,因此您可以查看运行该程序的人是否是root
。如果某人是 root
(或某人使用 sudo
),则允许不同的功能。
这是检测某人是否是 root
的代码。

以下是考虑到这一点的示例。因为 root
可以更改任何密码,所以该程序不必费心检查它通常执行的检查以查看此人有权更改哪些密码。因此,对于 root
,它会跳过这些检查并退出检查功能。

使用核心 Linux 命令和实用程序,您可以确信它们已经融入了安全性,并且代码已经过多次审查。当然,始终存在未知漏洞利用的威胁。但是,补丁或更新很快就会出现,以应对任何新发现的漏洞。
它是第三方软件——尤其是任何非开源软件——你在使用 SUID
时需要格外小心。我们并不是说不要这样做,但是,如果您这样做,您要确保它不会让您的系统面临风险。您不想提升无法正确自我管理自身和运行它的人的程序的特权。
使用 SUID 的 Linux 命令
以下是一些 Linux 命令,它们使用 SUID 位为普通用户运行时提供提升的权限:
ls -l /bin/su
ls -l /bin/ping
ls -l /bin/mount
ls -l /bin/umount
ls -l /usr/bin/passwd

请注意,文件名以红色突出显示,表示设置了 SUID 位。
文件或目录的权限通常由三组三个字符表示:rwx。这些代表读取、写入和执行。如果字母存在,则该许可已被授予。但是,如果出现连字符 (-
) 而不是字母,则表示未授予该权限。
这些权限分为三组(从左到右):文件所有者权限、文件组成员权限和其他权限。当在文件上设置 SUID
位时,“s”代表所有者的执行权限。
如果 SUID
位设置在不具有可执行功能的文件上,则大写“S”表示此。
我们来看一个例子。普通用户 dave
输入 passwd
命令:
passwd

passwd
命令提示 dave
输入他的新密码。我们可以使用 ps
命令查看正在运行的进程的详细信息。
我们将在不同的终端窗口中使用 ps
和 grep
并查找 passwd
进程。我们还将使用 -e
(每个进程)和 -f
(完整格式)选项以及 ps
。
我们输入以下命令:
ps -e -f | grep passwd

报告了两行,第二行是 grep
进程寻找其中包含字符串“passwd”的命令。不过,这是我们感兴趣的第一行,因为这是启动 passwd
进程 dave
的行。
我们可以看到 passwd
进程的运行方式与 root
启动它时的运行方式相同。
设置 SUID 位
使用 chmod
可以轻松更改 SUID
位。 u+s
符号模式设置SUID
位,u-s
符号模式清除SUID
位。
为了说明 SUID 位的一些概念,我们创建了一个名为 htg
的小程序。它位于 dave
用户的根目录中,并且没有设置 SUID
位。执行时,它会显示真实有效的用户 ID (UID)。
真正的 UID 属于启动程序的人。有效 ID 是程序运行的帐户,就好像它是由其启动的一样。
我们键入以下内容:
ls -lh htg
./htg

当我们运行程序的本地副本时,我们看到真实和有效的 ID 都设置为 dave
。所以,它的行为就像一个正常的程序应该的那样。
我们把它复制到/usr/local/bin
目录下,方便其他人使用。
我们键入以下内容,使用 chmod
设置 SUID
位,然后检查它是否已设置:
sudo cp htg /usr/local/bin
sudo chmod u+s /usr/local/bin/htg
ls -hl /usr/local/bin/htg

因此,程序被复制,SUID 位被设置。我们将再次运行它,但这次我们将运行 /usr/local/bin
文件夹中的副本:
htg

即使 dave
启动了该程序,有效 ID 也设置为 root
用户。因此,如果 mary
启动程序,同样的事情会发生,如下所示:
htg

真实ID是mary
,有效ID是root
。该程序以 root 用户的权限运行。
SGID 位
设置组 ID (SGID
) 位与 SUID
位非常相似。当可执行文件的 SGID
位被设置时,有效组被设置为文件所在的组。该进程以文件组成员的权限运行,而不是启动它的人的权限。
我们调整了 htg
程序,使其也显示有效组。我们将把 htg
程序的组更改为用户 mary
的默认组 mary
。我们还将使用 u-s
和 g+s
符号模式以及 chown
删除 SUID
位并设置SGID
。
为此,我们键入以下内容:
sudo chown root:mary /usr/local/bin/htg
sudo chmod u-s,g+s /usr/local/bin/htg
ls -lh /usr/local/bin/htg

您可以在组权限中看到由“s”表示的 SGID
位。另外,请注意该组设置为 mary
,文件名现在以黄色突出显示。
在我们运行程序之前,让我们确定 dave
和 mary
属于哪个组。我们将使用带有 -G
(组)选项的 id
命令来打印所有组 ID。然后,我们将以 dave
的身份运行 htg
程序。
我们输入以下命令:
id -G dave
id -G mary
htg

mary
的默认组ID是1001,htg
程序的有效组是1001。所以,虽然它是由dave
发起的,它在 mary
组成员的许可下运行。这就像 dave
加入了 mary
组一样。
让我们将 SGID
位应用于目录。首先,我们将创建一个名为“work”的目录,然后将其组更改为“geek”。然后我们将在目录上设置 SGID
位。
当我们使用 ls
检查目录设置时,我们还将使用 -d
(目录)选项,以便我们看到目录的详细信息,而不是目录的内容.
我们输入以下命令:
sudo mkdir work
sudo chown dave:geek work
sudo chmod g+s work
ls -lh -d work

SGID
位和“极客”组已设置。这些将影响在 work
目录中创建的任何项目。
我们键入以下内容进入work
目录,创建一个名为“demo”的目录,并检查其属性:
cd work
mkdir demo
ls -lh -d demo

SGID
位和“geek”组自动应用于“demo”目录。
让我们键入以下内容以使用 touch
命令创建一个文件并检查其属性:
touch useful.sh
ls -lh useful.sh

新文件的组自动设置为“极客”。
粘性位
粘性位的名字来源于它的历史用途。当在可执行文件上设置时,它会向操作系统标记可执行文件的文本部分应该交换保存,以便更快地重用它们。在 Linux 上,sticky 位只影响一个目录——将它设置在一个文件上是没有意义的。
当您在目录上设置粘滞位时,人们只能删除该目录中属于他们的文件。他们无法删除属于其他人的文件,无论对文件设置了哪种文件权限组合。
这允许您创建一个目录,每个人以及他们启动的进程都可以用作共享文件存储。这些文件受到保护,因为再一次,没有人可以删除其他人的文件。
让我们创建一个名为“shared”的目录。我们将使用 o+t
符号模式和 chmod
来设置该目录的粘滞位。然后我们将查看该目录以及 /tmp
和 /var/tmp
目录的权限。
我们输入以下命令:
mkdir shared
sudo chmod o+t shared
ls -lh -d shared
ls -lh -d /tmp
ls -lh -d /var/tmp

如果设置了粘性位,则“其他”文件权限集的可执行位将设置为“t”。文件名也以蓝色突出显示。
/tmp
和 /var/tmp
文件夹是为所有者、组和其他人设置所有文件权限的目录的两个示例(这就是它们被突出显示的原因绿色)。它们用作临时文件的共享位置。
有了这些权限,从理论上讲,任何人都应该能够做任何事情。然而,sticky bit 覆盖了它们,任何人都不能删除不属于他的文件。
提醒事项
以下是我们上面所涵盖内容的快速清单,以供将来参考:
SUID
仅适用于文件。- 您可以将
SGID
应用于目录和文件。 - 您只能将粘滞位应用于目录。
- 如果“
s
”、“g
”或“t
”指示符以大写形式出现,则可执行位(x
) 尚未设置。