以 root 身份安全地运行程序

作者:Phil Hughes

这篇文章更多的是关于结束一个坏习惯,而不是严肃的编程。你们有多少人经常变成 root 用户来做一些例行任务?我想是有的。更糟糕的是,你们有多少人仅仅因为知道可以做任何想做的事而一直以 root 身份登录?太多了。

成为 root 用户一个非常常见的原因是运行需要 root 权限的 shell 脚本。例如,启动 PPP 通常由一个必须以 root 身份运行的脚本完成。在本文中,我以此示例作为列表 1中所示代码的基础。它没有什么特别之处——它只是一个常见的例子。可以修改同一个程序来运行其他需要 root 权限的脚本,或者执行其他类似 root 的任务。

首先你需要理解的是“执行时设置 UID”这个短语的含义。这个概念是 Unix 中唯一拥有专利的特性。它是“看起来像另一个用户”来执行程序的能力。最常见的例子是运行 passwd 程序来更改密码。如果你查看密码文件的权限,你可能会看到类似这样的信息

-rw-r--r-- 1 root  1260
Nov  3 10:05 /etc/passwd

请注意,只有 root 用户才有权写入该文件。现在看看密码程序的权限

-rwsr-xr-x 1 root 10636 Jun 6 1996
/usr/bin/passwd
请注意,在您期望找到 x 来指示所有者的执行权限的位置,有一个 ss 指示“设置 UID”位已设置。

设置 UID 位意味着当您作为普通用户执行 passwd 程序时,该程序的执行就像您是 root 用户一样。这使您可以更改 /etc/passwd 中的密码条目,但您将无法执行任何其他操作。程序本身 (/usr/bin/passwd) 负责确保您只执行合理的任务;由于您没有程序的写入权限,因此无法更改它。

如果您理解了设置 UID,您现在可以看到它在保证程序安全性方面的重要性。例如,如果您的程序有进入 shell 的方式,它就存在安全漏洞。

当我们谈论安全漏洞时,另一种方法是允许 shell 脚本以设置 UID 的方式运行。 这种能力实际上存在于某些 Unix 系统中,并且会打开巨大的安全漏洞。 理想情况下,您必须能够读取该脚本并信任它。

我编写的用于启动和停止 PPP 的程序位于列表 1 中。它的目的是执行适当的 shell 脚本来启动或停止 PPP,具体取决于是否使用 onoff 参数调用它。

大部分代码在注释中进行了解释,但请允许我进一步解释几个项目。首先,我选择将 PATH 环境变量设置为一组合理的目录。 这样做很重要,以保证无法将未经授权的可执行文件偷偷放入程序中。 其次,我使用 execle 系统调用来执行相应的脚本。 execle 将新环境传递给被调用的程序,因此它继承了我设置的搜索路径,而不是调用用户的路径。

我还指定了要运行的程序的完整路径名(参见 #define 行)——另一个安全考虑。 在设置 PATH 后,它应该是不必要的,但这是一个廉价的安全预防措施。

最后,必须正确安装该程序。构建可执行文件 (make ppp) 后,您应该成为 root 用户,将其移动到适当的目录(例如,/usr/local/bin)并正确设置权限。

如果您希望任何人都能够运行该程序,请确保它由 root 拥有,并将权限设置为 4711。 前导 4 指定设置 UID 位。 如果您有一组特定的人员想要允许运行该程序,请将该程序的组所有者更改为相应的组,并将权限设置为 4710。

就是这样。如果一切顺利,您现在就少了一个以 root 身份登录的理由。

如果您需要一个系统来为普通用户分配各种 root 任务,那么很容易找到解决方案。 查看 sudosuper 程序,它们包含在大多数 Linux 发行版中。

Phil HughesLinux Journal 的出版商。 在过去的生活中,他是一名 Unix 系统程序员。

加载 Disqus 评论