使用 CVS 验证文件系统完整性
即使是最尽职尽责的偏执企鹅也需要时不时地度假,所以本月我们请到了一位客座专栏作家 Mick Bauer。
作者:Michael Rash
捕捉基于主机的入侵最有效的方法是通过检测文件系统中的更改。为此,Tripwire 是最知名的软件,它可以自动化验证机器上文件系统完整性的过程,并在检测到任何未经授权的更改时提醒管理员。Tripwire 可以检测到的更改类型包括文件权限和类型、inode 编号、链接计数、uid 和 gid、大小、访问时间戳、修改时间戳、inode 更改时间戳以及单向哈希签名(由十种不同的签名函数中的任何一种生成,包括 md5 和 Snefru)。在本文中,我们将探讨使用并发版本系统 (CVS) 以及一些 Perl 粘合代码,以类似于 Tripwire 的方式作为文件系统完整性检查器。虽然 Tripwire 是最知名的文件系统完整性检查器,但应该注意的是,Tripwire 最近成为一种专有产品,有许多免费和/或开源的替代品,例如 AIDE 和 FCheck(请参阅“资源”)。
在系统上部署 Tripwire 的基本过程可以概括为以下步骤:1) 安装操作系统,并立即从控制台运行 Tripwire,然后再将机器暴露于任何类型的网络连接;2) 将生成的文件系统信息 Tripwire 数据库存储在与系统分离的只读介质上;以及 3) 定期针对原始数据库运行 Tripwire,以便在当前文件系统信息和原始数据库之间进行比较,从而查找任何异常。
CVS 是一种主要由软件开发人员使用的工具,用于帮助组织一组源代码并为其提供版本结构。其最有用的功能之一是能够跟踪一段时间内一段源代码(或普通文本)中的所有更改,从代码最初检入 CVS 存储库时开始。当开发人员希望进行更改时,代码将从存储库中检出,进行修改,并将结果代码提交回存储库。CVS 会自动递增版本号并跟踪更改。在修改已提交到存储库后,可以使用 cvs diff 命令查看新版本相对于前一个版本(或任何其他版本)的更改之处。
现在我们已经基本了解了用于管理系统 Tripwire 的步骤,我们将展示如何以大致相同的方式利用 CVS,但有一个重要的增强功能:纯文本配置文件的差异跟踪。如果您的某台机器被破解,并且将用户添加到 /etc/passwd 文件中,Tripwire 可以报告任何数量的文件属性已更改的事实,例如 mtime 或单向哈希签名,但它无法告诉您具体添加了哪个用户。
入侵检测普遍存在的一个重要问题是,生成的误报数量往往非常高,并且基于主机的入侵检测系统 (HBIDS) 也不能幸免于这种现象。根据所涉及的系统数量,以及由此产生的复杂性,可能会频繁生成误报,以至于 HBIDS 生成的数据对于管理员来说可能变得难以承受。因此,在将用户添加到 /etc/passwd 文件的示例中,如果 HBIDS 可以准确报告添加了哪个用户,这将有助于确定添加是合法系统管理操作的一部分还是其他情况。这可以节省数小时的时间,因为一旦确定系统已被入侵,保证系统恢复到正常状态的唯一方法是从头开始重新安装整个操作系统。
为了与 Tripwire 将初始文件系统快照存储在与受监控系统分离的介质上的方法保持一致,我们需要一种从远程系统收集数据并将其存档在本地 CVS 存储库中的方法。为了实现这一点,我们在我们的网络中设置了一个专用的 CVS“收集器箱”。所有文件系统监控功能都将由来自该机器的单个用户执行。监控功能包括收集原始数据、将数据与 CVS 存储库同步以及在发现未经授权的更改时发送警报。我们将利用 ssh 协议作为网络通信工具,从远程机器收集数据。为了使事情更容易,我们将我们的 HBIDS 用户的 RSA 密钥放入每个目标系统上的 root 的 authorized_keys 文件中。这允许 HBIDS 用户在任何目标系统上以 root 身份执行命令,而无需通过 ssh 提供密码。现在我们对收集器箱的架构有了大致了解,我们可以开始收集数据了。
我们需要从远程系统收集两类数据:ASCII 配置文件和命令输出。收集命令输出通常比收集文件更广泛,因为我们可能不想完全复制所有远程文件系统。生成重要监控输出的命令包括 md5sum(生成文件的 md5 签名)和 find / -type f -perm +6000(查找所有权限中设置了 uid 和 gid 位的 文件)。在列表 1 和 2 中,我们演示了 Perl 代码,该代码从远程系统收集数据并监控此数据随时间的变化。
在列表 1 中,我们有一段 Perl 代码,它使用 Net::SSH::Perl 模块从地址为 192.168.10.5 的主机收集三组数据,一些重要系统二进制文件的 md5 哈希签名,一些操作系统配置文件的 tar 存档以及所有权限位中设置了 uid 和/或 gid 权限位的文件列表。第 7 行和第 8 行定义了目标机器的 IP 地址以及 collector.pl 将登录的远程用户。回想一下,我们在远程机器上预共享了本地用户的密钥,因此我们无需提供密码即可登录。第 10-13 行定义了一个小型系统二进制文件样本列表,将为其计算 md5 哈希签名,类似地,第 15-18 行定义了一个将从远程系统本地存档的文件列表。第 20-24 行构建了一个小型哈希,将本地文件名链接到将在远程系统上执行的命令,并且每个命令的输出都将本地存储在此文件中。第 27-33 行包含收集代码的核心,并为 %Cmds 哈希中的每个命令调用 run_command() 子例程(第 36-49 行)。run_command() 的每次执行都将创建一个新的 Net::SSH::Perl 对象,该对象将用于打开到远程主机的 ssh 会话,登录并执行传递给子例程的命令。
在列表 2 中,我们演示了一段 Perl 代码,如果 collector.pl 收集的任何文件发生更改,它负责生成电子邮件警报。这首先通过从 CVS 存储库中检出当前的 192.168.10.5 模块(第 12 行)来完成,执行 collector.pl(第 14 行)以在本地目录结构中安装远程命令输出和文件的新副本,然后将每个(可能已修改的)文件提交回存储库(第 20 行)。通过检查每个文件的 cvs commit 命令的返回值(第 20 行),我们可以确定文件是否已更改,因为 cvs 会自动递增文件的版本号并跟踪 确切 的更改内容。如果在特定文件中检测到更改,cvschecker.pl 会计算先前的版本号(第 27-36 行),执行 cvs diff 命令以针对先前的修订版本获取更改(第 39-40 行),并将更改的内容通过电子邮件发送(第 47-48 行)到第 7 行中定义的电子邮件地址。
现在让我们通过几个入侵示例将 collector.pl 和 cvschecker.pl 脚本投入使用。假设目标系统是一台 Red Hat 6.2 机器;HIBDS 数据是在建立任何外部网络连接之前从此机器收集的,并且目标的 IP 地址为 192.168.10.5。
假设机器 192.168.10.5 被破解,并以 root 身份执行以下命令
# cp /bin/sh /dev/... && chmod 4755 /dev/...
这将把 /bin/sh shell 复制到 /dev/ 目录作为文件“...”,并将设置 uid 位。由于该文件由 root 拥有,并且我们使其可由系统上的任何用户执行,因此攻击者只需要知道路径 /dev/... 即可作为 root 执行任何命令。显然,我们想知道 192.168.10.5 系统上是否发生了类似的事情。现在,在收集器箱上,我们执行 cvschecker.pl,并且向 root@localhost 发送以下电子邮件,其中清楚地显示 /dev/... 是一个新的 suid 文件
From: hbids@localhost Subject: Changed file on 192.168.10.5: suidfiles To: root@localhost Date: Sat, 10 Nov 2001 17:35:13 -0500 (EST) Index: /home/mbr/192.168.10.5/suidfiles ======================================================= RCS file: /usr/local/hbids_cvs/192.168.10.5/suidfiles,v retrieving revision 1.3 retrieving revision 1.4 diff -r1.3 -r1.4 4a5 > -rwsr-xr-x 1 root root 512668 Nov 10 18:40 /dev/...
现在假设攻击者能够以 root 身份执行以下两个命令
# echo "eviluser:x:0:0::/:/bin/bash" >> /etc/passwd # echo "eviluser::11636:0:99999:7:::" >> /etc/shadow
请注意,/etc/passwd 条目中 eviluser 的 uid 和 gid 设置为 0 和 0,并且 /etc/shadow 条目中没有加密的密码字符串。因此,系统上的任何用户只需键入 su - eviluser 即可成为 root,而无需提供密码。与之前的示例一样,在运行 cvschecker.pl 后,我们在 root 的邮箱中收到以下电子邮件
From: hbids@localhost Subject: Changed file on 192.168.10.5: /etc/passwd Delivered-To: root@localhost Date: Sat, 10 Nov 2001 17:43:17 -0500 (EST) Index: /home/mbr/192.168.10.5/etc/passwd ======================================================= RCS file: /usr/local/hbids_cvs/192.168.10.5/etc/passwd,v retrieving revision 1.2 retrieving revision 1.3 diff -r1.2 -r1.3 26a27 > eviluser:x:0:0::/:/bin/bash和
From: hbids@localhost Subject: Changed file on 192.168.10.5: /etc/shadow Delivered-To: root@localhost Date: Sat, 10 Nov 2001 17:43:18 -0500 (EST) Index: /home/mbr/192.168.10.5/etc/shadow ======================================================= RCS file: /usr/local/hbids_cvs/192.168.10.5/etc/shadow,v retrieving revision 1.2 retrieving revision 1.3 diff -r1.2 -r1.3 26a27 > eviluser::11636:0:99999:7:::
查找文件系统中的更改可能是检测入侵者的有效方法。在本文中,我们演示了一些简单的 Perl 代码,这些代码将 CVS 变成了一个自制的、基于主机的入侵检测系统。在我目前的工作单位,位于马里兰州安纳波利斯的 USinternetworking, Inc.,一家大型 ASP,我们使用类似的(尽管已大大扩展)自定义系统 USiOasis 来帮助验证我们网络基础设施中数百台机器的文件系统完整性。这些机器加载了各种操作系统,包括 Linux、HPUX、Solaris 和 Windows,并运行许多不同类型的服务器应用程序。该系统包括 MySQL 数据库后端、一个相当大的 CVS 存储库和一个主要用 Perl 编写的自定义 Web/CGI 前端。利用 CVS 存储库执行差异跟踪还带来了重要的额外好处:一个用 Python 编写的优秀可视化工具,名为 ViewCVS。将操作系统和应用程序配置文件存储在 CVS 中也有助于检测入侵之外的几个领域,例如排除网络和应用程序级中断、灾难恢复以及随时间跟踪系统配置。
