Paranoid Penguin - Linux 文件系统安全,第一部分
在《Linux Journal》的“Paranoid Penguin”专栏辉煌的四年中,我倾向于撰写以工具为中心的文章。我描述了如何保护 Sendmail 的安全,如何使用 Stunnel 为事物添加 SSL 加密,以及如何配置和运行任意数量的其他强大的安全软件工具。
然而,在接下来的几篇文章中,我将探讨 Linux 安全最基本和最重要的方面之一;文件系统权限,但它却经常被忽视。如果明智地使用它们,用户和入侵者将更难滥用他们的系统权限。但是,如果您粗心大意地设置它们,小的漏洞可能会导致重大的系统安全问题。
这些文章对于想知道所有drwxr-xr-x文件列表中乱码是什么意思的 Linux 新手尤其有用。但是,即使您是中级用户——也许是那种还不了解 setuid 和 setgid 的精确含义的用户——这些文章,尤其是第二部分,也可能对您有所帮助。
您是否知道在 UNIX 和类 UNIX 系统中,基本上一切都由文件表示?文档、图片甚至可执行程序都容易概念化为硬盘上的文件。虽然我们将目录视为文件的容器,但目录实际上是一个文件,其中包含您猜对了,其他文件的列表。
同样,连接到您系统的 CD-ROM 驱动器看起来很实在,但对于您的 Linux 内核来说,它也是一个文件——特殊设备文件 /dev/cdrom。为了从中发送数据或将其写入 CD-ROM 驱动器,内核实际上是从这个特殊文件读取和写入。实际上,在大多数系统上,/dev/cdrom 是指向 /dev/hdb 或其他一些特殊文件的符号链接。您知道吗,符号链接反过来只不过是一个包含另一个文件位置的文件。
其他特殊文件,例如命名管道,充当输入/输出 (I/O) 管道,允许一个进程或程序将数据传递给另一个进程或程序。
我在这里的重点不是描述 Linux 或 UNIX 中存在的每种文件类型。而是为了说明几乎所有东西都是用文件表示的。一旦您理解了这一点,就更容易理解为什么文件系统安全如此重要以及它是如何工作的。
命令和帮助手册页
在本文中,我侧重于文件系统概念,而不是实际命令的精确语法和用法。但是,如果您是初学者,您可能想知道如何完全执行命令以及在哪里可以找到语法/用法帮助。
首先,在我所有的示例和示例场景中,我都在终端窗口中工作。 Microsoft Windows 用户可以将终端视为类似 DOS 提示符或命令窗口。终端窗口提供了与 Linux 交互的最直接方式,即让您手动输入所有命令,而不是通过鼠标单击触发它们。
要从 GNOME 启动您自己的 shell 会话,请单击主菜单按钮并选择系统工具→终端。在 KDE 中,终端命令称为 konsole,它在任务栏上有自己的图标,一个计算机屏幕前的贝壳。或者,您可以启动“运行程序”对话框并键入konsole在提示符下。
为了快速获得几乎任何 Linux 命令的帮助,您可以在终端/shell 会话中键入该命令,后跟 --help 选项。例如,如果我不记得 ls 命令(列出文件和目录)的所有命令行选项,我输入命令ls --help.
--help 选项速度很快,但并非适用于所有命令。即使它确实有效,其输出也可能非常简洁。获取命令帮助的最佳方法是使用 man 命令。帮助手册页提供了关于如何使用大多数 Linux 命令的完整说明,并且几乎存在于所有类 UNIX 系统上。例如,要查看 ls 命令的帮助手册页,请键入命令man ls。在帮助手册页列表中,按空格键向前翻一页,按 B 键向后翻一页,然后键入/somestring以在帮助手册页中搜索 somestring。
但是,如果您不知道您需要的命令的名称怎么办?这就是 apropos 的用途。例如,键入apropos list以查看各种列出事物的命令,然后调出其中任何看起来是您需要的命令的帮助手册页。
实际上,Linux 系统上有两件事不是用文件表示的,即用户帐户和组帐户,我们简称它们为用户和组。各种文件包含有关系统用户和组的信息,但这些文件实际上都不能代表它们。用户帐户表示能够使用文件的人或事物。也就是说,人和系统进程都可以使用用户帐户。例如,名为 webmaster 的用户帐户通常代表维护网站的人。但是标准的 Linux 用户帐户 lp 由行式打印机守护进程 (lpd) 使用;lpd 程序以用户 lp 的身份运行。稍后我将解释程序以一个用户与另一个用户的身份运行意味着什么。
组帐户只是用户帐户的列表。每个用户帐户都定义了主要组成员身份,但实际上可以属于所需的任意数量的组。例如,用户 maestro 的主要组成员身份可能是 conductors,也可能属于 pianists。
用户的 主组 成员身份在用户帐户在 /etc/password 中的条目中指定。您可以通过编辑 /etc/group 并将用户名添加到用户应属于的每个组的条目的末尾来将该用户添加到其他组。或者,您可以使用 usermod 命令;有关更多信息,请参阅 usermod(8) 帮助手册页。
列表 1 显示了 maestro 在文件 /etc/password 中的条目,列表 2 显示了相应 /etc/group 文件的一部分。
列表 1. 用户 maestro 的 /etc/password 条目
maestro:x:200:100:Maestro Edward Hizzersands:/home/maestro:/bin/bash
列表 2. 两个 /etc/group 条目
conductors:x:100: pianists:x:102:maestro,volodyia
在列表 1 中,我们看到第一个字段包含用户帐户的名称 maestro。第二个字段 (x) 是 maestro 密码的占位符,实际上密码存储在 /etc/shadow 中。第三个字段显示 maestro 的数字用户 ID 或 uid;在本例中为 200。第四个字段显示 maestro 的主要组成员身份的数字组 ID 或 gid——在本例中为 100。其余字段指定注释、maestro 的主目录和 maestro 的默认登录 shell。
在列表 2 中,来自 /etc/group,每行仅包含组名、组密码(通常未使用——x 是占位符)、数字组 ID (gid) 和以逗号分隔的在组中具有辅助成员身份的用户列表。因此,我们看到组 conductors 的 gid 为 100,这与在列表 1 中指定为 maestro 的主要组的 gid 相对应。我们还看到组 pianists 包括用户 maestro,以及另一个名为 volodyia 的用户,作为辅助成员。
修改 /etc/password 和 /etc/group 以创建、修改和删除用户帐户的最简单方法是分别使用命令 useradd、usermod 和 userdel。我宁愿在这里专注于概念而不是命令语法,因此,我只想说这三个命令都可以用于设置和修改组成员身份,并且所有这三个命令都在各自的帮助手册页中有详细的文档记录。要查看快速用法摘要,您还可以键入命令后跟 --help,例如,useradd --help.
每个文件都有两个所有者,一个用户和一个组,每个所有者都有自己的一组权限,这些权限指定用户或组可以对文件执行的操作——读取、写入和执行它。第三组权限与其他人(不拥有该文件或不属于拥有该文件的组的用户帐户)可以对文件执行的操作有关。列表 3 显示了文件 /home/maestro/baton_dealers.txt 的长文件列表。
列表 3:显示权限的文件列表
-rw-rw-r-- 1 maestro conductors 35414 Mar 25 01:38 baton_dealers.txt
权限按用户权限、组权限和其他权限的顺序列出。对于列表 3 中显示的文件,其用户所有者 (maestro) 可以读取和写入文件 (rw-);其组所有者 (conductors) 也可以读取和写入文件 (rw-),但其他用户只能读取文件。但是,权限有点复杂。在特定文件的权限方面,归类为“其他”的用户可以删除他们对其具有写入权限的目录中的任何文件。换句话说,对文件具有只读权限的用户无法编辑该文件,但如果他们对该文件的目录具有写入权限,则可以删除该文件。
除了读取和写入之外,还有第三种权限:执行,当设置时用 x 表示。如果 maestro 编写了一个名为 punish_bassoonists.sh 的 shell 脚本,并且如果他将其权限设置为 -rwxrw-r--,那么他可以通过在命令行输入脚本的名称来执行该脚本。但是,如果他忘记设置执行权限,即使他拥有该脚本,他也无法运行该脚本。
权限和 root 用户
实际上,文件权限根本不适用于 root 用户;root 用户可以随时随地对任何文件执行任何操作。这就是为什么除非绝对必要,否则永远不要以 root 用户身份登录或使用 su 命令成为 root 用户如此重要的原因。当您是 root 用户时,文件权限无法保护您免受自身错误的影响。
这并不是说当您是 root 用户时,所有程序都完全无视文件权限。例如,如果 root 用户尝试使用 vim 编辑器更改只读文件,则 root 用户必须使用 :w! 命令(强制写入)。在这种情况下,普通的 ZZ 或 :w 命令会返回错误。但是,许多其他命令没有这种健全性检查功能。
权限通常使用 chmod 命令设置,chmod 是 change mode(更改模式)的缩写。继续我们的示例,假设 maestro 对允许 conductors 组的其他成员读取他的 baton dealers 列表三思而后行。他可以使用列表 4 中显示的命令删除组读取/写入权限。
列表 4. 使用 chmod 更改文件权限
bash-$ ls -l baton_dealers.txt -rw-rw-r-- 1 maestro conductors 35414 Mar 25 01:38 baton_dealers.txt bash-$ chmod go-rw baton_dealers.txt bash-$ ls -l baton_dealers.txt -rw------- 1 maestro conductors 35414 Mar 25 01:38 baton_dealers.txt
在列表 4 的示例 chmod 命令中(chmod go-rw), go告诉 chmod 更改组权限和其他权限;-rw表示删除这两类权限(组和其他)的读取和写入权限。因此,chmod 命令有三个部分:权限类别,u、g 和 o 或 a 的某种组合(表示全部);运算符,- 表示删除,+ 表示添加;以及要添加或删除的权限列表,通常为 r、w 或 x。
我们现在知道如何更改常规文件的基本权限,但是目录呢?目录权限的工作方式与常规文件的权限略有不同。读取和写入是相似的;对于目录,这些权限分别转换为列出目录的内容和在目录中创建或删除文件。
但是,执行权限在目录上有点不太直观。在这里,执行权限转换为使用目录中的任何内容或将工作目录更改为此目录。也就是说,如果用户或组对给定目录具有执行权限,则用户或组可以列出该目录的内容,读取该目录的文件(假设这些文件的权限本身包含此权限),并使用命令 cd 将工作目录更改为该目录。如果用户或组对给定目录没有执行权限,则用户或组无法列出或读取其中的任何内容,无论设置在其中的事物的权限如何。如果您缺少对目录的执行权限但确实具有读取权限,并且您尝试使用 ls 列出其内容,您会收到一条错误消息,但实际上该消息会列出目录的内容。但是,如果您对目录既没有读取权限也没有执行权限,则此方法不起作用。
假设我们的示例系统有一个名为 biff 的用户,他属于组 drummers。还假设他的主目录包含一个名为 extreme_casseroles 的目录,他希望与他的打击乐手同伴共享。列表 5 显示了 biff 可能如何设置该目录的权限。
列表 5. 组可读目录
bash-$ chmod g+rx extreme_casseroles bash-$ ls -l extreme_casseroles drwxr-x--- 8 biff drummers 288 Mar 25 01:38 extreme_casseroles
根据列表 5,只有 biff 有权在 extreme_casseroles 中创建、更改或删除文件。组 drummers 的其他成员可以列出其内容并 cd 到其中。但是,系统上的其他所有人都被阻止列出、读取、cd 或对该目录执行任何其他操作。
Mick Bauer,CISSP,《Linux Journal》的安全编辑,也是明尼苏达州明尼阿波利斯市的 IS 安全顾问。他是 Building Secure Servers With Linux(O'Reilly & Associates,2002 年)的作者。