19.1 代码审查方法

代码审查的方法很多,这些方法有助于提高在有限的时间内发现安全漏洞的效率。此外,还可以将代码审查与其他测试方法结合起来,充分利用每种方法的优势。

19.1.1 “黑盒”测试与“白盒”测试

前面各章描述的攻击方法常被称为黑盒(black-box)测试方法,因为它主要从外部攻击应用程序,并监控其输入与输出,而之前并不了解它的内部工作机制。相反,白盒(white-box)方法需要分析应用程序的内部运作,查阅所有设计文档、源代码与其他资料。

“白盒”代码审查可非常高效地发现应用程序中存在的漏洞。在审查源代码的过程中,我们常 常可以迅速确定仅使用“黑盒”技巧很难或需要很长时间才能发现的漏洞。例如,通过阅读代码可迅速确定一个可访问任何用户账户的后门密码,但使用密码猜测攻击几乎不可能发现这个密码。

然而,代码审查并不能完全替代“黑盒”测试。当然,从某种程度上讲,应用程序中的全部漏洞都“存在于源代码中”;因此,理论上,通过代码审查可以确定所有这些漏洞。但是,使用“黑盒”方法可以更迅速、高效地发现许多漏洞。举例来说,使用第14章描述的自动化模糊测试技巧,每分钟可以向一个应用程序发送数百个测试字符串,它们将迅速分散到所有相关代码路径中,并立即返回响应。另外,通过向每个字段发送常见漏洞的触发器,常常可以在几分钟内确定大量通过代码审查需要数天才能发现的漏洞。而且,许多企业级应用程序的结构极其复杂,对用户提交的输入进行多层处理。同时,应用程序在每一个层面实施不同的控制与检查,一段源代码中的明显漏洞可能会被其他地方的代码完全消除。

大多数情况下,“黑盒”与“白盒”技巧可以相互补充,彼此强化。通常,通过代码审查初步查明一个漏洞后,再在一个正在运行的应用程序中对其进行测试,是确定该漏洞是否真实存在的最简单、最有效的方法。相反,在一个正在运行的应用程序中确定某种反常行为后,审查相关源代码往往是确定其根本原因的最佳途径。因此,如有可能,应适当结合使用“黑盒”与“白盒”的技巧,并根据实时测试过程中应用程序的反常行为、源代码的大小与复杂程度,调整在每种技巧上投入的时间与精力。

19.1.2 代码审查方法

任何功能比较强大的应用程序都可能包含成千上万行源代码,许多情况下审查代码时间有限,可能仅有几天时间。因此,有效代码审查的一个关键目标是,在有限的时间与精力条件下,确定尽可能多的安全漏洞。为了实现这个目标,我们有必要采用一种结构化的方法,使用各种技巧确保迅速确定源代码中存在的“明显漏洞”,为探查更微妙、更难发现的漏洞争取更多时间。

根据我们的经验,当审查Web应用程序源代码时,使用三重查找方法可迅速高效地确定其中存在的漏洞。这种方法由以下3个步骤组成。

(1)从进入点开始追踪用户向应用程序提交的数据,审查负责处理这些数据的代码。

(2)在代码中搜索表示存在常见漏洞的签名,并审查这些签名,确定某个漏洞是否确实存在。

(3)对内在危险的代码进行逐行审查,理解应用程序的逻辑,并确定其中存在的所有问题。需要进行仔细审查的功能组件包括:应用程序中的关键安全机制(验证、会话管理、访问控制与任何应用程序范围内的输入确认)、外部组件接口,以及任何使用本地代码(通常为C/C++)的情况。

首先分析各种常见的Web应用程序漏洞在源代码中的各种表现形式,以及当进行代码审查时如何以最简单的方式确定这些表现形式。这将有助于在代码中搜索漏洞签名[第(2)步]和仔细审查危险的代码[第(3)步]。

然后依次分析一些最流行的Web开发语言,确定应用程序如何获得用户提交的数据(通过请求参数、cookie等)、它如何与用户进行会话交互、每种语言中存在潜在危险的API以及每种语言的配置与环境对应用程序安全的影响。这将有助于我们从进入点开始追踪用户向应用程序提交的数据[第(1)步],并为其他步骤提供每种语言的参考。最后介绍一些进行代码审查的有用工具。

img001  注解  当进行代码审查时,应该始终记住,应用程序可能扩展了类库与接口,对标准API调用执行了包装器,并对安全性至关重要的任务(如保存关于每个会话的信息)采用了定制机制。在进行仔细的代码审查之前,必须了解这些定制的范围,并相应调整审查方法。