Download PDF version of this article PDF

网络取证

良好的侦查工作意味着在攻击前、攻击中和攻击后都要保持关注。
本·劳里,A. L. DIGITAL

字典对“取证”的定义是“在刑事或民事法庭上使用科学和技术来调查和确定事实。” 然而,我更感兴趣的是计算机世界中常见的用法:使用计算机遭受攻击后留下的证据来确定攻击是如何实施的以及攻击者做了什么。

取证的标准方法是查看攻击发生后可以检索到什么,但这有很多不足之处。第一个也是最明显的问题是,成功的攻击者通常会竭尽全力确保掩盖他们的踪迹。第二个问题是,不成功的攻击通常会被忽视,即使被注意到,也很少有信息可以帮助诊断。

成功攻击后的混淆处理

一旦攻击成功,攻击者通常可以完全访问被攻击的系统。狡猾的黑客随后可以通过修改日志、删除核心转储等方式来删除攻击证据。实际上,许多攻击都会安装新的软件并修改系统,以便使用诸如ps之类的标准实用程序无法看到新的软件。一旦发生这种情况,就很难清理系统,更不用说确定发生了什么。

不成功的攻击

失败的攻击远多于成功的攻击。尽管多年来一直发出警告,但最流行的攻击形式仍然是缓冲区溢出。在这种攻击中,通常情况下,一些代码被放置在堆栈上,并且函数调用的返回地址被破坏,以导致植入的代码被调用。从攻击者的角度来看,困难在于代码最终所在的精确地址在很大程度上取决于目标系统的确切构建版本(例如,操作系统、编译器版本、使用的确切编译标志、目标代码版本、构建时使用的选项、链接的库)。因此,攻击者通常必须尝试许多略有不同的攻击版本,直到一个版本起作用。我个人熟悉的一个例子是 Slapper 蠕虫,因为我发现了并修复了它在 OpenSSL 中利用的漏洞。1 该代码包含一个非常长的表,其中一部分在图 1 中提供。

此表用于确定攻击要使用的地址,但可以看出,即使蠕虫确定了平台和 Apache 版本(情况可能并非总是如此),有时仍然需要尝试多个地址。如果它使用了错误的地址,那么通常的结果是目标发生段错误(Segmentation Fault),而不是屈服于攻击。

在过去的好日子里,这会导致核心转储,这可能是一个有用的诊断工具(尽管请记住,由于堆栈已损坏,即使是核心转储的用处也可能有限)。不幸的是,由于核心转储可能包含密码、私钥等,出于安全考虑,大多数系统默认情况下不会从可能成为目标的软件(例如,sendmail、Apache、IMAP 服务器)生成核心转储。当然,这通常是可以修复的,但您必须记住在*被攻击之前*这样做。

即使有了核心转储,确定攻击是如何工作的也可能很困难,因为直接证据已经消失了,而且许多成功的攻击会破坏重要的数据结构,例如堆栈或堆。此外,一个不幸的趋势是,许多广泛使用的软件包为了提高性能而禁用了堆栈帧,这使得核心转储非常难以解释。例如,在 GCC(GNU 编译器套件)中,这是 -fomit-frame-pointer 标志。如果省略了帧指针,调试器将无法显示堆栈回溯。

尽管存在这些问题,但确保服务运行以便可以生成核心转储,并且编译它们以使核心转储有用,当然是值得的:总的来说,启用调试信息并且不禁用堆栈帧是最佳方法。

攻击类型

毫不奇怪,人们的注意力集中在使用互联网作为传输媒介的攻击上——但还有另一类攻击也引起了一些人的关注:本地攻击。即使与基于互联网的攻击相关,这些攻击也值得讨论。广义上讲,基于互联网的攻击可以分为两种类型:协议攻击和恶意软件。当然,这些问题在所有网络中都很常见;互联网并没有什么特别之处,除了它的普遍性。

协议攻击

协议攻击依赖于协议或协议实现中的缺陷,以导致实现该协议的软件中出现不良行为。最著名的协议攻击类型是广为讨论的缓冲区溢出,但还有许多其他类型:不太为人所知的例子是版本降级和相关的降低安全性的攻击,或者依赖于意外输入以导致不正确行为的攻击(例如,在路径中使用“..”来访问已发布树之外的目录,或 SQL 注入以导致服务器执行任意 SQL)。

其他攻击,例如跨站脚本攻击或 cookie 劫持,可以说严格来说不是协议攻击,但我将它们归为此类,原因有二

1. 它们完全基于程序的 I/O。

2. 它们不使用可执行代码作为其主要的利用手段——“主要”是因为缓冲区溢出通常确实携带可执行代码作为其有效载荷,而恶意软件首先使用本地可执行代码来获得控制权。

恶意软件

恶意软件是一个术语,用于描述最终依赖于执行才能执行其“邪恶”(暂且用这个词)任务的各种软件。它涵盖病毒、木马和蠕虫,尽管这些之间的界限开始变得模糊。一般来说,这些攻击依赖于用户错误或无知才能执行,一个众所周知的最近的例子是 MyDoom 病毒,它导致收件人相信他们正在重新发送一封第一次无法送达的电子邮件,从而诱使他们双击附件,然后附件就会做坏事。

事后取证

通常,新的攻击(无论是恶意软件还是协议攻击)都是在攻击成功后才被发现的,因为受害机器的行为发生了改变。例如,在与剑桥大学计算机实验室的 Richard Clayton 合作撰写的一篇文章中,我们正在研究通过(除其他外)分析大型互联网服务提供商的邮件日志来使用受感染的机器发送垃圾邮件。有趣的是,Clayton 的软件旨在发现发送垃圾邮件的机器,它迅速发现了 MyDoom 的传播,因为它彻底改变了受感染机器的电子邮件习惯。更常见的情况是,机器的所有者开始注意到可疑的症状:CPU 始终处于 100% 使用率,互联网访问突然变慢,某些程序似乎无法“完全正常”工作,等等。多年前,当我从事排版工作时,就发生过这样的例子。Ventura Publisher 是 80 年代非常流行的排版程序,突然在一台机器上停止工作。几天后,另一台也停止了。我被叫去调查。我发现后来被命名为 Bethlehem 的病毒感染了这些机器——但它有一个 bug。当它感染 .EXE 文件时,它检查自身是否存在失败,因此它不断地重新感染它们,直到它们太大而无法装入内存。

一旦注意到这种改变的行为,接下来的任务就是弄清楚哪里出了问题。通常这是一个混乱的事情,涉及到翻阅日志、检查旧电子邮件、检查磁盘上是否有意外的可执行文件等等。复杂的恶意软件甚至会掩盖其自身的踪迹并修改系统二进制文件以隐藏其持续的活动(这就是“rootkit”所做的),从而导致很难追踪它。实际上,标准的建议是将机器下线,卸下其磁盘并在另一台机器中以只读方式挂载它,并运行各种狡猾的诊断程序以尝试对恶意软件进行逆向工程(例如,使用 Dan Farmer 和 Wietse Venema 创建的 The Coroner’s Toolkit)。2

当然,世界上大多数人几乎不需要担心这一点——世界上大多数人既不是早期的受害者,也不是必须弄清楚哪里出了问题以及如何修复它的人。世界上大多数人可以非常高兴地坐在一旁,等待别人来担心它,弄清楚发生了什么,并告诉他们;然后他们可以开始担心他们将如何防御这个问题,或者开始抱怨 XYZ 的安全性有多么无效。

我最感兴趣的是那些必须诊断问题的人,以及他们如何才能让自己的生活更轻松。

事前取证

对此,最轻松和简单的答案通常是日志记录。而且,在大多数情况下,大多数软件如果配置正确,都会产生大量的日志。但是,正如我的朋友和有时的合作者 Tina Bird 多年来一直指出的那样,这些日志对于检测和诊断通常都几乎毫无用处。为什么?因为,为了诊断软件中的逻辑错误和其他错误,它们通常被设计为由程序员手动读取,或者至少由熟悉代码的人员结合对程序的输入和输出的相当牢固的知识来读取。它们并非旨在帮助应对恶意攻击,也并非旨在进行自动分析。前者的缺点是显而易见的——但后者的缺点可能不太明显:攻击的特征之一是它们并非总是在发生后很快就被检测到;事实上,有些攻击永远不会被检测到。这可能是因为机器在任何人注意到之前就停止使用了(这可能是几年的时间——用于发送垃圾邮件的机器的行为清楚地表明,受感染的机器已准备好在一个池中,未被检测到,等待被使用!),或者,也许更有趣的是,因为攻击失败了,所以没有什么明显的迹象可以注意到。

如何改进这种情况?有趣的是,程序*内部*正在发生的详细日志(这通常是我们在日志中获得的)可能用处不大;一般来说,成功的攻击不会沿着我们在代码内部期望的路径进行,因此日志记录往往要么不发生,要么难以与原因联系起来。更有用的是确切地知道输入和输出是什么,因为这样我们就可以在闲暇时重复攻击,使用调试器、代码检测或其他任何东西来诊断攻击的载体。

但是,记录一切难道不是一个问题吗?

是的,确实如此。所涉及的量通常是巨大的,并且最有可能在攻击最容易发生的地方达到最大。这里没有灵丹妙药,但有一些策略可以帮助缓解这个问题。

例如,我最近为 Apache 编写了一个名为 mod_log_forensic 的取证日志记录模块。它记录两次:一次在请求开始时,一次在请求结束时。由于对 Apache 的大多数攻击都失败了(如前所述),如果我们仅保留与失败的攻击相关的日志,则该模块 99% 的实用性将得到保留。我们如何发现这些攻击?这很容易:它们是在请求开始时记录,但没有在结尾记录的那些(因为服务器在中间死了)。为了减少繁忙站点的日志大小,我考虑过使用外部程序过滤日志,将预请求组件保留一段时间,并且仅当相应的后请求条目未到达时才记录到磁盘。通过使程序意识到服务器的死亡并在这种情况下进行记录,可以使此方法更加复杂,但是这种方法让我担心——取证日志记录应该是轻量级和健壮的,以免它本身成为攻击的目标。

尽管这里存在一定的风险因素,但第一次或在短时间内成功的攻击可能会杀死日志减少过滤器,并导致日志根本无法写入磁盘;或者感兴趣的攻击可能针对 CGI(通用网关接口),因此不会导致服务器本身死亡。在某些环境中,特别是当使用率非常高且没有外部 CGI 时,这种方法是有意义的。请记住,诸如 mod_perl 或 mod_php 之类的进程内 CGI 仍会显示在日志中。

Mod_log_forensic 还与另一个流行的模块 mod_unique_id 交互。如果正在使用此模块,则 mod_log_forensic 将使用其 ID 而不是自己的 ID;因此,取证日志可以与访问日志以及 CGI 生成的日志绑定在一起。Mod_unique_id 还处理日志池(其中一组机器都共享一个公共日志),而 mod_log_forensic 本身不这样做(存在 ID 冲突的风险)。

Mod_log_forensic *不*记录来自服务器的任何输出,因为(至少在理论上)输出应该是确定性的,或者如果不是,则是不相关的。当然,其他应用程序可能对输入和输出有不同的要求。

最近添加到 Apache 的还有取证模块 mod_log_backtrace 和 mod_whatkilledme。这些模块仅在出现严重错误时才记录日志,这意味着它们的量要小得多,但再次增加了感兴趣的事件将不会被记录的风险。Mod_log_backtrace 也存在一个主要的缺点,即它告诉你你死时在哪里,但没有告诉你是什么杀死了你。Mod_whatkilledme 可能会告诉你,但前提是杀死你的东西没有破坏它(这在 mod_log_forensic 中不会发生,因为它在任何事情发生之前而不是之后记录日志)。

可以用来减少量的另一种策略是仅记录输入的一个子集。实际上,mod_log_forensic 就是这样做的——它不记录通过 HTTP POST 请求发送到 CGI(或模块)的数据。这样做有两个原因,主要原因是务实的:POST 请求往往很大。第二个原因是 Apache 没有一种机制允许任意模块访问 POST 数据,因此这种日志记录必须由处理请求的模块来完成(如果是 mod_cgi,则可以将其配置为记录请求数据)。

最后,要记录什么、如何减少量以及这样做所带来的风险在很大程度上取决于应用程序。但好消息是,这通常在很大程度上取决于应用程序作者的控制,如果他们决定这样做,而不是靠运气而不是判断力收集的偶然信息的随机组合。

确保日志有用

一个经常被忽略直到为时已晚的细节是,您必须小心取证日志,以确保它们可以用于准确地重建攻击。例如,令人惊讶的是,直到最近,Apache 都没有阻止精心构造的请求在访问日志中造成虚假条目。

同样重要的是,日志可以自动分析。当需要查看几十 GB 的日志时,您最不想做的事情就是单独阅读它们。

幸运的是,这两个细节都很容易处理,并且冒着班门弄斧的风险,我将概述一般策略。

布局

布局应该易于被诸如 grep、sed、awk 和 perl 之类的工具解析。这通常意味着它应该

1. 完全由可读的 ASCII 组成。

2. 具有明确的标记。

3. 以行为单位。

4. 不要有过长的行(尽管我宁愿使用自定义版本的 grep,也不愿通过人为地缩短行来降低日志质量)。

由于在几乎所有情况下,正在记录的内容都受攻击者的控制,因此您不应依赖于遵循任何协议规则来强制执行这些约束。这意味着您应该对非 ASCII 字符使用转义(在大多数情况下,也包括控制字符,以避免旨在利用用于显示日志的终端程序的攻击——是的,这些攻击已经在野外出现过)。为了具有明确的标记,您需要选择一个字段分隔符,该分隔符在字段中出现时也会被转义,并且如果字段是命名的而不是位置的,那么理想情况下,请为这些字段使用第二个分隔符。

为了便于说明,以下是我为 mod_log_forensic 所做的工作。首先,我没有记录原始输入,而是记录初始解析后的 HTTP 请求,因此它已被分解为单个标头和请求行本身。这是一个经过计算的风险——缺点是在日志发生之前解析代码中的错误会被利用,但优点是日志本身更容易解析。碰巧的是,这种方法对服务器结构的干扰远小于记录原始输入(实际上,它根本没有干扰;mod_log_forensic 是一个标准模块)。字段由竖线 (hex 7c) 分隔,字段组件由冒号 (hex 3a) 分隔。对于预处理日志,第一个字段是 +,后跟唯一 ID;第二个字段是请求;其余字段是标头,格式为 <标头名称>:<标头内容>。条目以换行符 (hex 0a) 结尾。所有低于 hex 20 和高于 hex 7e 的字符都经过 URL 转义(即,被 %xx 替换,其中“xx”是十六进制值),冒号、竖线和百分号也是如此。在后处理条目的情况下,整行是一个 —,后跟唯一 ID。

保护日志

正如我之前所说,成功的攻击者通常会竭尽全力删除泄露其活动的日志。实际上,有许多广泛可用的工具可以在攻击后掩盖踪迹。那么,如何确保日志在被攻击后不会丢失呢?最明显的策略是记录到不同的机器,但这可能很昂贵 *并且* 会引入另一个漏洞,至少是对日志记录拒绝服务攻击而言。

一个不太明显的策略是将日志写入一次写入介质;然而,值得记住的是,并非所有一次写入介质都是 *真正* 的一次写入——例如,WORM(一次写入,多次读取)磁盘在写入后可以被擦除。在更可能的情况下,即在不同的机器上记录日志,要使用的明显机制是 syslog 的现有功能,即向另一台机器发送消息。因为您很可能想要进行复杂的过滤(例如 mod_log_forensic 建议的过滤)——这实际上应该在日志记录机器上而不是生成日志的机器上运行,以保护过滤器免受攻击者的攻击——您应该考虑将 syslog-ng3 作为日志记录平台。这很容易允许插入外部过滤器。有关一般日志记录策略的有用资源可以在日志分析网站 4 上找到。

为不可避免的事情做好计划

从并非旨在用于该目的的分布式信息中拼凑出系统发生的情况是一个令人沮丧且不令人满意的过程。最好为不可避免的攻击做好计划,并确保安全地收集必要的信息,并且即使攻击成功,这些信息仍然可用——如果您正在编写代码,请确保首先提供必要的信息!

参考文献

1. 有关 Slapper 故事的更多信息,请参阅我的咆哮:安全:我为什么要烦恼?O’Reilly Network;http://www.oreillynet.com/pub/wlg/2004。

2. The Coroner’s Toolkit;请参阅:http://www.porcupine.org/forensics/tct.html。

3. Scheidler, B. syslog-ng。http://www.balabit.com/products/syslog_ng/。

4. Bird, T. 和 Ranum, M. Loganalysis.org,http://www.loganalysis.org/。

 

本·劳里是 A. L. Digital 的技术总监,也是 Apache-SSL Web 服务器的作者。他是 Apache 软件基金会的创始董事和安全主管。他还是 OpenSSL 项目(世界上使用最广泛的密码库)和许多其他互联网项目的核心成员。他的主要兴趣是安全、密码学、隐私、公民自由和啤酒。

© 2004 1542-7730/04/0600 $5.00

acmqueue

最初发表于 Queue 第 2 卷,第 4 期——
数字图书馆 中评论这篇文章





更多相关文章

保罗·维克西 - 要么静态,要么回家
计算机和网络安全中当前和历史上的大多数问题都归结为一个简单的观察结果:让其他人控制我们的设备对我们不利。在另一个时候,我将解释我所说的“其他人”和“不利”是什么意思。就本文而言,我将完全专注于我所说的控制是什么意思。我们失去对设备控制的一种方式是来自外部的分布式拒绝服务 (DDoS) 攻击,这些攻击用不需要的流量填充网络,从而没有空间容纳真实的(“需要的”)流量。其他形式的 DDoS 类似:例如,低轨道离子炮 (LOIC) 的攻击可能不会完全填满网络,但它可以使 Web 服务器忙于响应无用的攻击请求,以至于服务器无法响应任何有用的客户请求。


阿克塞尔·阿恩巴克、哈迪·阿斯加里、米歇尔·范·伊顿、尼科·范·艾克 - HTTPS 市场的安全崩溃
HTTPS(超文本传输协议安全)已发展成为安全 Web 浏览的事实标准。通过基于证书的身份验证协议,Web 服务和互联网用户首先使用 TLS/SSL 证书相互验证(“握手”),对 Web 通信进行端到端加密,并在浏览器中显示挂锁以指示通信是安全的。近年来,HTTPS 已成为保护在线社交、政治和经济活动的重要技术。


莎伦·戈德堡 - 为什么保护互联网路由需要这么长时间?
BGP(边界网关协议)是将互联网粘合在一起的粘合剂,它使不同组织运营的大型网络之间能够进行数据通信。BGP 通过为组织之间的流量设置路由来使互联网通信全球化——例如,从波士顿大学的网络,通过更大的 ISP(互联网服务提供商),如 Level3、巴基斯坦电信和中国电信,然后到住宅网络,如 Comcast 或企业网络,如美国银行。


本·劳里 - 证书透明度
2011 年 8 月 28 日,一个为 google.com 错误颁发的通配符 HTTPS 证书被用于对伊朗的多个用户进行中间人攻击。该证书由一家名为 DigiNotar 的荷兰 CA(证书颁发机构)颁发,DigiNotar 是 VASCO Data Security International 的子公司。后来的分析表明,DigiNotar 早在一个多月前(至少从 7 月 19 日起)就意识到了其系统中的漏洞。它还表明,至少已颁发了 531 个欺诈性证书。由于 DigiNotar 没有所有错误颁发的证书的记录,因此最终计数可能永远无法得知。





© 保留所有权利。

© . All rights reserved.