60
Fortify Source Code Analysis 入门 版本 5.1 2007 12

Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

  • Upload
    others

  • View
    21

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

Fortify Source Code Analysis 入门

版本 5.12007 年 12 月

Page 2: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

版权所有 © 2003-2007 Fortify Software, Inc.RB_RB_3 12, 2008 11:21 上午保留所有权利。美国印刷。 Fortify Software, Inc.2215 Bridgepointe PkwySuite 400San Mateo, CA 94404 Fortify Software, Inc.(以下简称 "Fortify")和他的授权者保留对此文档(以下简称“文档”)的一切所有权。本文档的使用需遵守相关的版权法。 Fortify 保留在不预先通知的情况下随时修改本文档的权利。 本文档在没有任何承诺的情况下按“此版本”提供。对于本文档中发现的任何错误所引起的特殊的、巧合的或间接的损害,包括对其业务、利益、使用或数据等以及其他的任何方面造成的任何损失和意外中断,Fortify均不对此承担责任。Fortify 保留有在不预先通知的情况下对本文档中所介绍的 终产品的任何功能或组件进行修改和删除的权利。 Fortify 是 Fortify Software, Inc. 的注册商标。本文档中的品牌和产品名称是其各自所有者的商标。

Fortify Source Code Analysis 入门

Page 3: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

目录

前言 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1第 1 章: 概述 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

分析过程概述 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

练习概述 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3第 2 章: Java 代码的分析练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5练习 1:查看一个已完成的审计. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5练习 2:人工审计源代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12练习 3:运行 Fortify Source Code Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14练习 4:理解未处理的分析结果. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14练习 5:分析一个完整的应用程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18练习 6:使用 Audit Workbench 调整结果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19练习 7:审计某个问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23练习 8:执行一次完整的审计 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25练习 9:编写自定义规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

答案 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33第 3 章: C 和 C++ 代码的分析练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

练习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35练习 1:查看一个已完成的审计. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35练习 2:人工审计源代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43练习 3:运行 Fortify Source Code Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44练习 4:理解未处理的分析结果. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44练习 5:分析一个完整的应用程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47练习 6:使用 Audit Workbench 调整结果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48练习 7:审计某个问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52练习 8:执行一次完整的审计 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

答案 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Fortify Source Code Analysis 入门 iii

Page 4: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

iv Fortify Source Code Analysis 入门

Page 5: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

前言本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

任务的相关教程。

如果您对本指南的任何内容存有疑问或建议,请与 Fortify Software 联系:

技术支持

650.358.5679

[email protected]

企业总部

2215 Bridgepointe Pkwy

Suite 400

San Mateo, CA 94404

650.358.5600

[email protected]

网站

http://www.fortify.com

Fortify Source Code Analysis 入门 1

Page 6: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

2 Fortify Source Code Analysis 入门

Page 7: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

第 1 章:概述静态分析能非常有效地辨识安全相关的编码错误。本文档中的教程章节提供了使用静态分析所需的

实际经验,用来发现漏洞和增强安全性。这些章节还提供了一系列 source code analysis 练习。

分析过程概述 静态分析的典型流程可以分成几个步骤,从源代码的自动分析开始,直到生成一份关于安全结果的

完整报告。 后,审计员使用这些经过检查、区分过优先级的问题创建报告,指出在审计过程中发

现的问题。

这个流程的第一步,通常称之为分析,是使用一种静态分析工具来分析项目的源代码。为了让这一

步骤取得成功,必须保证代码完整并且可以进行编译。

一旦工具找到了一组问题,审计员必须检查这些问题,从中找出确实会引发安全风险的问题,并按

照它们在代码中出现的上下文环境以及可能造成的后果或漏洞利用,定义其严重级别。这个步骤被

称之为审计,它实际上是人通过检查工具发现的问题,发现真正问题的过程。

后,审计员使用这些经过检查、区分过优先级的问题创建报告,指出在审计过程中发现的问题。

概括说,这个流程看上去如下图所示:

图 1:分析过程

练习概述每个教程章节提供了一系列用来引导您如何执行这种安全检查的练习,您将使用 Fortify Source Code Analyzer (Fortify SCA) 执行静态分析并通过 Audit Workbench 检查工具发现的问题。这些练习

要按顺序进行。在许多情况下,在练习 N 中得到的知识是完成练习 N+1 的必要条件。

注意:这里假设您已经按照 《Fortify Source Code Analysis 安装指南》中所述的步骤,安装了 Fortify SCA 和 Audit Workbench。

下表介绍了每章中的练习。

Fortify Source Code Analysis 入门 3

Page 8: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

表 1: 练习

练习 描述

练习 1:检查一个完整的审计 使用 Audit Workbench 检查一个完整的审计。完成练习后,

您将创建好一个分析结果文件。

练习 2:人工审计源代码 考虑不使用工具来检查代码的问题。如果过去您只是从理论上考虑过这个问题,那么现在当您面对代码的时候,您会发现理论与实际大不相同。

练习 3:运行 Fortify Source Code Analyzer

使用 Fortify SCA 分析一个 Java 类或 C 源文件。

练习 4:理解未处理的分析 理解 Fortify SCA 所生成的命令行输出。

练习 5:分析一个完整的应用程序 对一个完整的应用程序运行 Fortify SCA。

练习 6:使用 Audit Workbench 调整结果

快速过滤掉您不想审计的问题。

练习 7:审计某个问题 使用 Audit Workbench 来审计用 Fortify SCA 找到的第一个

问题。

练习 8:执行一次完整的审计 完成一个小型 Web 应用程序的审计。

练习 9:编写自定义规则(仅包含“分析 Java 的练习”)

自定义 Fortify SCA,检查您指定的属性。

4 Fortify Source Code Analysis 入门

Page 9: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

第 2 章:Java 代码的分析练习本章介绍了如何扫描 Java 源代码,其中包括以下主题:

• 练习

• 答案

每个练习均采取循序渐进的分步讲解。其中一些练习,在讲解的 后部分有一个名为深入讨论的部

分,这部分内容会对练习内容做更深层次的探讨,以便用户理解练习所涉及的相关主题。

您可以通过以下路径找到练习答案以及各种更深入的问题:

<install_directory>/Tutorial/Java/answers

练习本部分为练习内容。因为每个练习都建立在前一个练习的基础之上,所以您应按顺序进行。

练习 1:查看一个已完成的审计

在这个练习中,您可以使用 Audit Workbench 来查看对 WebGoat 3.7 版的已完成审计。WebGoat 是一个开放源代码的 Java Web 应用程序,由 Open Web Application Security Project (OWASP) 编写

和维护,用来介绍各种各样的软件安全问题1。

注意:练习 6 和 7 会重新回到 Audit Workbench,对其进行更加详尽的介绍。

1. 启动 Audit Workbench。

在 Windows 中:打开“开始”菜单,导航至开始 - 程序 - Fortify Software - Fortify SCA 5.0 - Audit Workbench。

在其他平台上:在终端或命令提示界面中,运行 auditworkbench。

在闪现屏幕中会显示 Audit Workbench,然后会显示启动页。

2. 加载审计。

选择 Open Project (打开项目)。

选择以下文件并单击 Open (打开):

<install_directory>/Tutorial/Java/audits/webgoat/webgoat.fpr

注意:在 Linux、Unix 平台上和自定义安装的 Windows 中,会显示“Project Source Path(项

目的源路径)”对话。单击 Yes (是)并选择以下的 WebGoat 源目录:

<install_directory>/Tutorial/Java/source/webgoat

3. 查看 Project Summary (项目汇总)面板中显示的信息。 Project Summary (项目汇总)提供

已加载的分析结果的总体概述,如已分析的项目的大小。

1. http://www.owasp.org/software/webgoat.html

Fortify Source Code Analysis 入门 5

Page 10: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 2:项目汇总

4. 使用 Issues (问题)面板查看问题是如何分组和定义优先级的。

图 3:问题面板

Hot (严重)文件夹包含了优先级 高的问题,接下来是 Warning (警告), 后是 Info (信

息),它包含了优先级 低的问题。 All(全部)文件夹包含了所有 Hot(严重)、Warning(警

告)和 Info (信息)问题。您也可以按不同的标准对每个列表中的问题进行分组。在这个练习

中根据 Category (类别)进行分组。

5. 单击 Hot (严重)、 Warning (警告)和 Info (信息)可查看是如何对问题进行分组的。

6. 单击 Hot (严重),然后在导航树中展开 SQL Injection 类别来查看单个问题。

6 Fortify Source Code Analysis 入门

Page 11: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 4:展开 SQL Injection 类别

文件名左边的图标表示审计员对每个暴露的问题进行风险评估,评估的结果从安全到可利用。在这个项目中,审计员将所有 SQL injection 问题都归为可利用一类。在本练习的稍后部分,您

会发现有种类繁多的状态图标,可以用来表示问题审计的不同级别。以下列表列举了各个图标与其所选择的审计状态之间的对应关系。请注意,正如 《Audit Workbench 用户指南》中所介

绍的,审计状态标签是可以自定义的。

图 5:审计状态图标

7. 展开 Cross-Site Scripting 类别,然后选择 AbstractLesson.java:837 中报告的问题。

Fortify Source Code Analysis 入门 7

Page 12: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 6:展开 Cross-Site Scripting 类别

请注意,在 AbstractLesson.java:837 条目下有两个问题。 Audit Workbench 将共享同一

个终点(称为 sink)但是不同起点 (称为 source)的问题分在一组。由于在同一指令中结束的

问题通常代表了某个漏洞的多个实例,因此这种分组形式有助于同类问题的审计。在这个例子中, Cross-Site Scripting 问题发生在 AbstractLesson.java 的第 837 行,但是起源于不同

源的两条路径都出现在 ParameterParser.java 中:一条在第 540 行,另一条在 557 行。

8. 查看某个问题摘要。在 Issues (问题)面板中找到并选中以下 SQL injection 问题:

BlindSqlInjection.java:76

考虑与这个问题相关联的源代码,并注意存在漏洞的函数是对 executeQuery() 的调用。

图 7:源代码视图

在“Issue Auditing (问题审计)”面板的 Summary (总结)选项卡中,仔细阅读审计员对该

问题的注释,并注意审计员针对这一问题所选择的分析选项。还要注意 Category (类别)字段

表明这一问题所代表的漏洞类别,同时包括的内容还有该漏洞所属的漏洞系列以及发现这个漏洞的分析器的详细信息。

8 Fortify Source Code Analysis 入门

Page 13: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 8:总结选项卡

选择 Details (详细信息)选项卡来读取有关此类漏洞的更多信息。

图 9:详细信息选项卡

Fortify Source Code Analysis 入门 9

Page 14: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

9. 查看 Analysis Trace (分析跟踪)面板。

单击 Analysis Trace (分析跟踪)面板中的具体条目,查看 Fortify SCA 是如何在整个程序中跟

踪恶意数据的。当选中数据流问题时, Analysis Trace (分析跟踪)面板上所显示的一连串条目

就会提供数据流跟踪信息。跟踪从分析器 先开始追踪数据的那一点开始 (如一个用户输入源),然后在整个程序中一直跟踪该数据,直到找到数据不安全使用的那一点为止。

图 10:分析跟踪面板

10. 生成审计报告。

a. 在“Tools (工具)”菜单中选择 Generate Report (生成报告)。生成的审计报告总结了

审计过程中所发现的问题,并提供了一个良好的机制,和其他人共享您的审计结果。

b. 从 Report (报告)下拉菜单中选择 Fortify Security Report (Fortify 安全报告)。

10 Fortify Source Code Analysis 入门

Page 15: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 11: 生成报告面板

c. 单击 Save Report (保存报告)可生成报告。

屏幕中将显示 Save Report (保存报告)对话框。

d. 单击 Browse (浏览)。

e. 为报告选择所需的输出文件夹,并单击 Save (保存)。

f. 从 “Format (格式)”下拉菜单中选择 PDF Report (PDF 报告)。

g. 在 Save Report (保存报告)对话框中单击 Save (保存)可生成报告。

h. 使用 Acrobat Reader 打开报告。报告包含了所分析项目的相关信息,所报告问题的类型和

数量以及对经审计的每个问题的总结。

深入讨论

探讨其他问题。查看其他类别中的问题,并阅读审计员对这些问题的相关注释。有关每一类问题的

更多一般信息,请参见 “Issue Auditing (问题审计)”面板中的 Details (详细信息)选项卡。

Fortify Source Code Analysis 入门 11

Page 16: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 2:人工审计源代码

理解静态分析工具为什么重要的一个 好的办法是不借助任何分析工具来检查一组代码。这个练习

演示了在不使用任何支持工具的情况下,对一个小型 Web 应用程序进行基本安全审计所涉及到的

步骤。

任何形式的代码检查都需要耐心,仔细查看细节,还需要具有对那些会造成风险的问题类型的丰富知

识。安全审计也是这样,但审计员需要考虑的不是“什么东西可能会出错?”,而是 “什么东西在

攻击者的影响下会出错?”审计员的职责就是将无穷大的搜索范围缩小,找出应用程序中 危险的问

题和 容易受到攻击的漏洞。经验是无价的,而经验来自于实践。

应用程序的根目录是:

<install_directory>/Tutorial/Java/source/webapp/

1. 回答下列问题:

a. 应用程序有多大?

b. 包含了哪些技术?

c. 应用程序的基本设计是怎样的?

d. 谁是可能的攻击者?

e. 攻击者想要达到什么目的?

f. 开发人员如何保护应用程序?

g. 应用程序的什么地方会引起攻击者的注意?

h. 攻击者会使用什么类型的技术来破坏应用程序?

i. 成功的攻击会对公司造成什么样的风险?

2. 检查以下路径中的文件:

<install_directory>/Tutorial/Java/source/webapp/src/java/com/simpleco/CountServlet.java

12 Fortify Source Code Analysis 入门

Page 17: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

3. 回答下列问题:

a. 代码在何时执行以及如何执行?

b. 攻击者可以控制什么?

c. 程序开发者是否假设过攻击者可能会违反程序规则?

d. 这个 servlet 的漏洞是什么?

4. 结束审计。

以与 CountServlet.java 类似的方式检查每个应用程序文件。考虑各模块之间的相互作用,

找出容易受到攻击的地方。

5. 查看第 33 页中的 “答案”,寻找在上面文章中提到的相关问题的答案。

现在,您已经检查了一个现有的审计,且执行了一个 19 行代码的手动审计。您能想象手动审计一个

包含 100,000 行代码的项目所需要的资源吗?有些应用程序甚至具有数百万行的代码。大规模的人

工代码检查需要非常庞大的资源,而且审计员理解代码不同领域中复杂的相互作用的能力是相当有

限的。在现实中,对企业系统的人工代码检查要求非常小心地进行选择和检查应用程序的少部分。

虽然人工审计能够有效地查找到漏洞,但是却没有办法涉及到那些未经检查的代码部分。

接下来的练习介绍了分析和审计源代码以便查找出安全漏洞的工具,并通过具体示例演示了如何有

效利用这些工具来审计企业系统规模的代码的主体部分。

Fortify Source Code Analysis 入门 13

Page 18: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 3:运行 Fortify Source Code Analyzer本练习介绍了 Fortify SCA。请您检查已经正确安装该工具,并用它来分析一个小程序。接下来的练

习将会帮助您理解工具所产生的输出,并且向您展示通过不同方式来分析一个真实的项目。

1. 分析单个源代码文件。

切换到以下目录:

<install_directory>/Tutorial/Java/source/userserv

输入以下命令:

sourceanalyzer UserServ.java

2. 与预期结果相比较。

您将会从屏幕终端上看到类似于下面的输出信息:

[# : high : Password Management : Hardcoded Password : semantic ]

UserServ.java(16) : DriverManager.getConnection()

[#: low : J2EE Bad Practices : getConnection : semantic ] UserServ.java(16) : DriverManager.getConnection()

[# : high : SQL Injection : dataflow ]

UserServ.java(25) : ->Statement.executeUpdate(0)UserServ.java(19) : <=> (this.query)UserServ.java(22) : <- ServletRequest.getParameter(return)

[# : medium : Unreleased Resource : Database : controlflow ]

UserServ.java(16) : start -> connection : conn = getConnection(...)UserServ.java(16) : connection -> connection : conn refers to a database connectionUserServ.java(26) : connection -> connection : conn no longer refers to a database connectionUserServ.java(34) : Branch taken: (stmt != null)UserServ.java(35) : java.sql.SQLException thrownUserServ.java(44) : connection -> connection : conn no longer refers to a database connectionUserServ.java(44) : connection -> end_of_scope : conn end scope : Database resource leaked

[# : medium : System Information Leak : Missing Catch Block : structural ]

UserServ.java(10)FunctionCall [UserServ.java(17)]

[# : high : Race Condition : Singleton Member Field : structural ]

UserServ.java(19)Field: UserServ.query [UserServ.java(8)]

注意:为了保持可读性, 32 位十六进制的实例识别符已经用哈希标记 (#) 代替了。

把您分析的输出结果与上述做比较。练习 4 将会详细描述列出的每个问题。

练习 4:理解未处理的分析结果

本练习将会引导您浏览一下在练习 3 中使用 Fortify SCA 分析小程序产生的结果。请您检查 Fortify SCA 中各种不同分析器所发现的问题,并比较 Fortify SCA 生成的各种不同输出格式。

1. 请考虑 UserServ.java 的内容:

14 Fortify Source Code Analysis 入门

Page 19: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 12:UserServ.java 的代码

Fortify Source Code Analysis 入门 15

Page 20: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

2. 检查语义问题。

下图突出显示了在练习 3 中的 UserServ.java 中检测出来的 password management 问题的

各个要素。

图 13:语义问题

唯一识别符:开头的十六进制数(在此文本中以哈希标记 (#) 代替)是一个全局性唯一识别符,

也称为实例识别符。这些识别符以分析器找到问题的路径、漏洞类型以及其他一些不受细小的代码变动影响的因素为基础而计算得出。例如,唯一识别符不依赖于代码行数。除了唯一性,实例识别符还提供了其他十分有价值的功能,它们可以标识出在多次分析中或不同代码版本之间的相同问题,因此可以被用来追踪审计过的问题。

严重性:因为这个问题可以使得任何具有访问源代码或者字节码权限的人都可以操作数据库,所以 Fortify SCA 把它的严重级别设为 high。

漏洞类别/漏洞子类别:Password Management 类中的问题都与潜在地不安全使用密码和其他证

书有关。在这个例子中,问题归为 Hardcoded Password 子类别,是由于这里用来连接数据库的

密码直接出现在了源代码中。

分析器:问题由 semantic 分析器报告。 semantic 分析器以与编译器十分相似的方式、以它定义

的语义分析规则来检查代码。有关分析器的更多信息,请查看 《Fortify Source Code Analyzer 用户指南》。

文件名/行号:虽然密码本身出现在 UserServ.java 文件的第 18 行,但问题被报告在第 16 行,因为使用密码的函数在此被调用。

易受攻击的方法:hardcoded password 被传递给了 DriverManager 类中的 getConnection() 方法。

3. 检查数据流问题。

使用下列图示来理解 SQL injection 问题。

16 Fortify Source Code Analysis 入门

Page 21: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 14:数据流问题

请注意这里有许多字段和上面的语义问题相同。这些字段的含意在数据流问题 (和在下面要讨论的其他类型的问题)中是相同的。在这里,您将更加关注那些没有在语义问题中出现的字段。数据流问题比语义问题更复杂,因为它们牵涉到源代码中的多个地方。这是一个 SQL injection 问题,它发生在攻击者控制的数据被用来构造 SQL 查询时。数据流分析器将会跟踪那些潜在的

恶意输入数据,从数据被输入到程序中一直到它被用来作为攻击的一部分。

Sink:sink 的文件名、行号以及方法名指出了攻击者控制的查询在何处传递到数据库。紧随在

行号之后而在类名和方法名之前的右箭头 (->) 指出了被感染的数据流入了 Statement.executeUpdate()。方法名后括号内的数字是这个方法的参数编号。数字 0 表示攻击者可以控制 executeUpdate() 的第一个参数(SQL 查询字符串)。

Pass-Through:pass through 的文件名、行号以及变量名指出了将受感染的数据传递给 sink 的变量。双向箭头 (<=>) 指出了受感染的数据流入、并且流出该方法的变量 this.query。

Source:source 的文件名、行号以及方法名指出了攻击者控制的数据第一次进入程序的位置。紧

随在行号之后而在类名和方法名之前的左箭头 (<-) 指出 ServletRequest.getParameter() 引入了被感染的数据。方法名后括号中的单词 return 表示是该方法的返回值持有被感染的数据。

4. 检查控制流问题。

使用下列图示来理解 unreleased resource 问题。

图 15:控制流问题

控制流问题看上去类似于数据流问题,因为它们通常包含多个结点,不同点在于这些结点所代表的操作步骤是不安全的。 Control flow 漏洞被表述为一系列状态的转换。

Fortify Source Code Analysis 入门 17

Page 22: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

开始状态/结束状态:第一个状态转换项显示了从 start 状态到 connection 状态的转换发生

在第 16 行。第二个状态转换项显示了从 connection 状态到 end_of_scope 状态的转换发生

在第 44 行。

转换表达式:转换表达式紧跟在 start 和 end 状态名称之后。它给出了触发转换的代码构成。

从 start 到 connection 的转换由调用 getConnection() 引起。从 connection 到 end_of_scope 的转换由变量 conn 到达其域的终止处引起。

控制流分析器在代码中找到了一个路径,该路径因为没有调用 conn.close() 而导致数据库连

接泄漏。虽然 conn.close() 在第 37 行进行了调用,但是由于第 35 行调用 stmt.close() 有可能会抛出异常,所以该方法并不能保证对 conn.close() 的调用总会执行。

5. 检查第二种结构问题。

考虑以下 member field race condition 问题。

图 16:结构问题

虽然结构问题可能只是报告了一行源代码,但是有时候它们会包含一些与程序结构相关的上下文,以便精确地指出错误。在这个问题中,分析器考虑了成员变量在一个继承于 HttpServlet 的类中进行声明的情况。

6. 生成 Fortify Project Results (FPR) 文件

Fortify SCA 不但能够生成可以直接被审计员阅读的输出,也能够生成一个 FPR 文件,此文件可

以用 Audit Workbench 或者其他工具进行查看。

再次运行 Fortify SCA,但是这一次生成 FPR 输出。使用 -f 选项将输出发送给 FPR 文件,如下

所示:

sourceanalyzer -f results.fpr UserServ.java

深入讨论

重写 UserServ.java 以解决您检查出的安全问题。再次运行 Fortify SCA 来验证您的工作。

练习 5:分析一个完整的应用程序

本练习演示了如何使用 Fortify SCA 来分析一个完整的应用程序。 简单的 Java 应用程序分析方法

就是将 Fortify SCA 指向包含应用程序的源文件的根目录。1 通过在命令行上提供此信息, Fortify SCA 将会在指定目录下自动识别所有已知类型的源文件,包括 Java 源文件, Java Server Pages (JSP) 文件, PL/SQL 和 TSQL 文件, Java properties 文件,以及 XML 配置文件。一个类似于类路

径的参数可以使 Fortify SCA 使用任何您指定的 jar 文件,来解析定义在源代码中的标识名称。

1. 运行 Fortify SCA。

切换到以下目录:

<install_directory>/Tutorial/Java/source/webgoat

输入以下命令,这可能需要几分钟来完成执行:

sourceanalyzer -classpath "WEB-INF/lib/*.jar" -f webgoat.fpr .

1.如果您使用 Ant 来编译应用程序,您还可以将 Fortify SCA 集成到 Ant build 脚本中。有关与 Ant 集成的信息,

请参见《Fortify Source Code Analyzer 用户指南》。

18 Fortify Source Code Analysis 入门

Page 23: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

注意:命令以一个 "." (点)结束,来表示当前目录。

向 Fortify SCA 指定的命令行参数:

类路径: Fortify SCA 会将参数 -classpath "WEB-INF/lib/*.jar" 解释为:当解析源代码

中的标识和导入指令时,需要考虑目录 WEB-INF/lib 下的所有 jar 文件。与 Java 编译器一

样,您也可以指定一系列 jar 文件,每个文件之间用分号 (Windows)或冒号 (其他平台)隔

开。 后,您也可以通过使用与 Ant build system 相同的方式,让 Fortify SCA 向下递归寻找所

有子目录。参数 -classpath "WEB-INF/lib/**/*.jar" 让 Fortify SCA 包含在 WEB-INF/lib 目录中及其子目录中的所有 jar 文件。

输出文件:参数 "-f webgoat.fpr" 让 Fortify SCA 将结果输出到文件 webgoat.fpr 中。

因为文件名以 .fpr 扩展名结尾, Fortify SCA 会自动以 FPR 格式写入其输出。

源文件:参数 "." (点)让 Fortify SCA 在当前目录及其子目录下查找源文件。您可以使用与类

路径相同的通配符语法,来限制 Fortify SCA 去寻找某组特定目录或特定文件。

练习 6:使用 Audit Workbench 调整结果

本练习描述了如何使用 Audit Workbench 来调整由 Fortify SCA 生成的分析结果。这样调整的目的是

要限制检查的问题,以更适合应用程序和审计员的检查方式。一般而言,一个专业的代码审计员和

一个有安全意识的软件开发者不会检查同一组结果。调整过程使不同的审计员可以根据各自的需要

来配置 Fortify SCA。

1. 启动 Audit Workbench。

在 Windows 中:在开始菜单中,导航至开始 - 所有程序 - Fortify Software - Fortify SCA 5.0 - Audit Workbench。

在其他平台上:在终端或命令提示界面中,运行 auditworkbench。

在闪现屏幕中会显示 Audit Workbench,然后会显示启动页。

2. 新建一个审计项目。

选择 Open Project (打开项目),然后选择您在练习 5 中创建的 FPR 文件,然后单击 Open(打开)。

<install_directory>/Tutorial/Java/source/webgoat/webgoat.fpr

请注意,在 Hot(严重)文件夹中有 75 个问题,Warning(警告)文件夹中有 134 个问题,在 Info (信息)文件夹中有 256 个问题,而在 All (全部)文件夹中有 465 个问题。

3. 使用 Audit Guide (审计指南)向导来过滤与质量相关的问题。

a. 选择 Tools (工具)菜单中的 Audit Guide (审计指南),或单击 Audit Guide (审计指

南)按钮。

系统会显示 “Audit Guide (审计指南)”设置面板。

Fortify Source Code Analysis 入门 19

Page 24: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 17:审计指南设置面板

b. 单击 Advanced Mode (高级模式)。

系统会显示“Advanced Audit Guid (高级审计指南)”面板。

c. 选中 J2EE Bad Practices 对应的复选框,然后单击 OK (确定)。

20 Fortify Source Code Analysis 入门

Page 25: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 18:高级审计指南面板

d. 请注意,现在 “Warning (警告)”文件夹中有 115 个问题,在 Info (信息)文件夹中有 242 个问题,而在 All (全部)文件夹中有 432 个问题。

e. 选择 Options (选项) - Show Hidden Items (显示隐藏的项目),以查看哪些结果已在

“Issues (问题)”面板中隐藏。

f. 选择 Warning (警告)选项卡。

“Hidden (19) (隐藏 (19))”会显示在文件夹的标题栏中。

g. 选择 Info (信息)选项卡。

“Hidden (14) (隐藏 (14))”会显示在文件夹的标题栏中。

Fortify Source Code Analysis 入门 21

Page 26: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 19:隐藏的问题

4. 应用另一组过滤器。

从 Filter Set (过滤器组)下拉菜单中选择 Medium (中)。

图 20:过滤器组

注意,已有不少问题被删除。过滤器组可使得结果看上去像是只用一部分规则分析出来的一样,这样可以让您在寻找所有可能的问题和寻找那些 严重、级别 高的问题之间找到平衡。

22 Fortify Source Code Analysis 入门

Page 27: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

深入讨论

选择 Audit Guide (审计指南)并尝试提供的各个选项。查看每个设置隐藏了哪些问题(如果有)。

如果您将继续下一个练习,请不要关闭 Audit Workbench。

练习 7:审计某个问题

您应该已经完成了练习 6,并且在 Audit Workbench 中打开了 WebGoat 的分析结果。

本练习是上次练习的继续,它将解释审计一个问题的步骤,强调 Audit Workbench 中对完成一次审

计不可或缺的各种功能。您需要确切地理解 Fortify SCA 报告的内容,以及包含问题的代码的行为。

与人工审计一样,使用静态分析工具的审计员需要提出合适的问题,以充分利用各种可能的结果。

1. 收集在 “Issues (问题)”面板中报告的关于各种问题的高级信息。

三个严重级别选项卡, Hot (严重)、 Warning (警告)和 Info (信息),显示在每个严重级

别上检测到的问题的数量。单击其中一个严重级别选项卡,可在 Issues (问题)树中显示属于

此严重级别的问题。

Issues (问题)树中项目的分组方式是由 Group by (分组方式)下拉菜单中所选的选项控制

的。项目可以按以下方式进行分组:Category (类别)(默认分组方式)、 File name (文件

名)、 Analyzer (分析器)、 New Issue (新问题) , Source、 Sink、 Package (包)、 Taint flag(感染标识)、Analysis(分析)、OWASP Top Ten 2004、OWASP Top Ten 2007、Fortify Priority Order (Fortify 优先级顺序)或 Category Analyzer (类别分析器),或者以没有任何分

组的平面结构直接显示。从 Group by (分组方式)下拉菜单中选择 Source,注意大多数问题

发生在从 ServletRequest.getParameterValues() 返回的用户输入,就象在简单的 Web 应用程序中预期的那样。

“Issues (问题)”面板底部的文本字段是用来在 Issues (问题)导航树中显示的问题中搜索,

仅留下和搜索相匹配的问题。搜索可以在 any field (任何字段)(默认情况)下执行,或者使

用高级查询语句。有关 Audit Workbench 支持的查询语言的更多信息,请参见《Audit Workbench 用户指南》。由于 WebGoat 是为了演示各种不同种类的安全漏洞,因此它有许多以

其包含的漏洞命名的 Java 文件。在搜索字段中输入查询字符串 'SqlInjection',然后按 Enter 键。基于我们对 WebGoat 设计意图的理解,这些文件似乎是寻找 SQL Injection 漏洞的源头。

单击搜索字段旁的 X,再次显示所有问题,并选择 Group by (分组方式)菜单下的 Category(类别)返回到默认视图。

当展开一个类别时, Issues (问题)树会列出属于该类别的每个问题,并显示出现该问题的源文

件和行号。单击 Hot (严重)列表,再单击以在 Issues (问题)树中展开 SQL Injection 类别。

选择在 BlindSqlInjection.java 中第 76 行出现的 SQL injection 问题。请注意 Analysis Trace (分析跟踪)面板和 “Issue Auditing (问题审计)”面板的 Summary (总结)选项卡

是如何显示有关所选问题的信息。同时,请注意 BlindSqlInjection.java 将在“Source Code Viewer (源代码查看器)”中打开。简单定位一个问题中的各种结点和快速检查相关源代

码的能力,使得理解一个问题比起人工检查整篇代码要简单得多。

右键单击选中的问题。注意,在此菜单中,您可以废除问题,根据该问题生成一个过滤器,找出是哪个过滤器导致了该问题显示于列表中,或自动生成一个错误报告。一旦您完成了该问题的审计,请判断它是否属于 Hot (严重)列表。如果该问题确实是出现在编码环境中的 SQL Injection 漏洞,则它应该仍然留在 Hot (严重)列表中。

2. 使用 Analysis Trace (分析跟踪)面板检查从 source 到 sink 的路径。

Analysis Trace (分析跟踪)面板中的每个结点对应所选问题中的一步。对于数据流问题,每个

结点对应于被跟踪的数据从 source 到 sink 过程中的一次函数调用、分配或返回语句。虽然一些

分析跟踪看起来很像堆栈跟踪,但应避免以堆栈的方式来看待它们。而应将它们当作沿时间线的一系列事件。时间从 Analysis Trace (分析跟踪)面板的顶部开始,一直往后到 后一个结

点,即出现问题的地方。当选中一个新问题时,“Source Code Viewer (源代码查看器)”面板

中将默认显示Analysis Trace (分析跟踪)中的 后一个结点。

Fortify Source Code Analysis 入门 23

Page 28: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

选择 Analysis Trace (分析跟踪)中的第一个结点,该结点与数据流的 source 相对应。相对应

的源代码会显示在“Source Code Viewer (源代码查看器)”面板中。在这个例子中, source 是对 HttpServletRequest.getParameterValues() 的调用,返回一组与指定名称相匹配

的请求参数。

选择在 source (第一个结点)和 sink ( 后一个结点)之间的每个结点。请注意,当数据流分

析器通过一些表达式跟踪被感染的值时,这些表达式均没有执行任何验证,或减轻 SQL injection 攻击的危险。下列图标出现在数据流路径中,表示每个结点上的表达式的类型:

表 2: 图标图示

图标 描述

数据被分配到一个字段或变量

信息读取自代码之外的数据源(如 HTML 表格和 URL)

数据被分配到一个全局字段或变量

已执行比较

函数调用收到被感染的数据

函数调用返回被感染的数据

Pass-through,被感染的数据在函数调用中从一个参数传递到另一个参数

为某个内存位置创建一个别名

从一个变量读取数据

从一个全局变量读取数据

从一个函数返回被感染的数据

创建一个指针

取消一个指针

变量范围终止

执行跳跃

在代码执行中引入分支

代码执行中未引入分支

常规

24 Fortify Source Code Analysis 入门

Page 29: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

1. 检查总结信息并对问题进行注释。

“Issues Auditing (问题审计)”面板的 Summary (总结)和 Details (详细信息)选项卡既提

供了有关在 Issues (问题)面板中选中的问题的附加信息,同时允许用户对该问题添加注释。在

面板右边的粗体文本提供了问题的类别,该类别跟在括号之中,根据漏洞所属类型进行划分,并提供了检测出该问题的具体分析器。在该信息之下,有对该漏洞的简单描述, More Information(更多信息)链接可打开 Details (详细信息)选项卡,“Recommendation (建议)”链接可打

开“Recommendation (建议)”选项卡。

选择 Details (详细信息)选项卡,获取有关该问题的详细描述,包括带有示例的问题的解释。

选择 Recommendations (建议)选项卡,获取有关如何解决问题的建议,在审计类似问题上

的有用提示,以及作为深入了解该主题的参考。当您完成对 SQL injection 漏洞的阅读后,请再

次选择 Summary (总结)选项卡继续。

在底部的 Comment (注释)字段中,填写问题的简要描述以及您为什么认为它容易受到攻击。

完成对该问题的注释后,请按 Enter 键。该注释会被贴上时间戳,且被添加至注释列表中。注

释应包括您在问题审计期间所得到的信息,如引发问题的数据类型(ServletRequest.getParameterValues() 中的用户输入),执行验证时该怎么办

(无),和问题在上下文中出现的重要意义 (如果这个代码出现在生产环境中会很严重)。此外,当检查问题或该问题生成的报告时,还要考虑 Details (详细信息)选项卡中的部分相关描

述。在这个例子中, 好包括来自 Recommendations (建议)区域中的谈论参数查询的正确使

用的建议。

在 Summary (总结)选项卡的左边有一个下拉菜单和两个按钮。下拉菜单用来记录审计的结

果。从 “Analysis (分析)”菜单中选择 Exploitable (可利用),表明该问题是可以被攻击者

利用的。

如果在审计问题后,您判断它实际上是安全的,您可以通过单击 Suppress (废除)按钮来废

除该问题。然而,如果问题需要由开发者来解决,您可以单击 File Bug (报告错误)按钮来自

动生成一个需要进行配置的错误报告。

2. 保存您的工作。

在 “File (文件)”菜单中选择 Save Project (保存项目),将项目保存为 webgoat.fpr。Audit Workbench 项目文件存储 初的问题信息和您在审计中所做的更改。

3. 保持 Audit Workbench 运行以继续下一个练习。

练习 8:执行一次完整的审计

您应该已经完成了练习 7,并且在 Audit Workbench 中打开了 WebGoat 的分析结果。

在过去的练习中,您已经检查了一个已完成的审计,执行了对应用程序的分析,并从分析结果中审

计了一个问题。现在,可以执行您自己的安全审计了。本练习通过介绍软件安全专家在执行安全审

计时采用的一些步骤,让您练习使用 Fortify SCA 和 Audit Workbench,而这些分析技能通常需要一

个源代码审计员学习几年才能掌握。

1. 审计 SQL Injection 问题。

SQL injection 是 Java 应用程序中经常发生的 严重漏洞之一。审计数据流问题时,如 SQL injection,您需要回答两个重要的问题:(1) 输入源允许攻击者包括危险字符或内容吗?

(2) source 和 sink 之间是否有校验逻辑用来排除输入中的危险内容?

选择在 BlindSqlInjection.java 中第 76 行报告的 SQL injection。注意, sink 为对 Statement.executeQuery() 的调用,其中第一个参数 (SQL 命令字符串)被感染。注意

数据流的路径,您可以看到 source 为对 HttpServletRequest.getParameterValues() 的调用,而且数据在它连接到数据流路径中倒数第二个结点的查询字符串之前通过几个中间函数进行传递。

Fortify Source Code Analysis 入门 25

Page 30: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

单击数据流路径中的第一个结点,突出显示 ParameterParser.java 中的 getParameterValues() 源函数。单击数据流路径中的每一个结点,跟踪被感染的值,看它

被分配到数组值,从一个函数返回到另一个 getRawParameter(),并 终分配到 accountNumber。由于 accountNumber 直接来自于 HTTP 请求,而且不用任何验证可以直

接连接到 SQL 查询字符串,因此代码很容易受到 SQL injection 的攻击。这就是静态分析能力的

体现。而人工去发现并跟踪这些路径是相当困难的。

在 Summary (总结)面板的文本框中写上注释,表明您检查数据流路径的结果。在 Analysis(分析)下拉菜单中选择 Exploitable (可利用),表明问题是可以远程利用的。为了判断问题

的影响,您首先需要理解应用程序发生在哪里。由于 WebGoat 是一个在生产环境中永不被部署

的简单应用程序,因此它里面的任何漏洞造成的影响都是相当低的。然而,如果相同的漏洞出现在某个在线金融应用程序的 authentication 逻辑中,它的影响会是 High。

检查 SQL Injection 类别中余下的问题。

2. 审计 Cross-Site Scripting 问题。

选择在 BasicAuthentication.java 第 103 行报告的 Cross-Site Scripting 问题。注意,

sink 是对 Apache Element Construction Set (ECS) 库中的动态 HTML 生成函数的调用,其中第

三个参数被感染。(ECS 是一个用来自动生成标记语言的包,诸如 HTML 和 XML)。注意数据

流的路径,类似于您审计 SQL injection 问题时看到的一样,您可以看到 source 是对 getParameterValues() 的调用,只不过数据在到达 sink 之前通过几个不同的中间函数进行

传递。

本数据流路径的大部分看起来非常类似于您已审计过的 SQL injection 问题的路径,只不过本问

题的数据流路径还包括对函数 clean() 的调用。展开与 clean() 相对应的数据流路径中的结

点,调查函数执行的是什么逻辑。您将发现 clean() 会对照适当的白名单比较每一个非字母数

字字符。该验证的一个问题就是,当内容包括在白名单允许的依靠分号 (;) 的 JavaScript 块中

时,可能会加载部分 cross-site scripting 攻击。更重要的是,逐个的字符验证没有考虑到可能被

用来掩饰恶意输入的特殊编码。如果攻击者用意想不到的编码提交输入,受害者的浏览器会解析该编码,同时注入恶意内容。

例如,如果攻击者以 UTF-7 格式提交了一个请求,被黑名单阻止的特殊字符 '<' (因为它可以用

来加载 cross-site scripting 攻击)会显示为 '+ADw-',从而不会被过滤掉。如果一个页面上的输出

没有明确指出编码格式,则一些浏览器会努力去智能地辨认基于内容(在这个情况下为 UTF-7)的编码,从而使攻击获得成功。验证逻辑应该做更多限制,但是一般来说,这样比不存在或用于应用程序中其他地方的基于黑名单的编码形式好得多。记下您的结果并继续。

用相同的方法检查余下的 Cross-Site Scripting 问题。注意,少数情况下输入会通过 clean(),但在大多数情况下,未经验证的 HTTP 请求参数是直接包含在传回给用户的内容中。您能够推

论出该应用程序很容易受到 cross-site scripting 攻击。

3. 检查 HTTP Response Splitting 问题。

选择发生在 WebSession.java 中第 290 行的 HTTP response splitting 问题。注意,sink 是对 HttpServletResponse.addCookie(), 的调用,它在 HTTP 响应中添加了一个 cookie 头文

件。查看短数据流路径,您可以看到 source 是从 HttpServletRequest.getCookies() 中读取的一个 cookie。显然,在 source 和 sink 之间没有进行验证,这意味着如果一个攻击者能将 CRLF 字符包含在 HTTP 请求中,那么应用程序会将这些字符包含在传回给用户的响应中。记录

下您的发现并阅读 Details (详细信息)选项卡,以便学习有关 HTTP response splitting 的攻击

的更多内容。

4. 检查 Password Management:Hardcoded Password 问题。

选择发生在 DatabaseUtilities.java 中第 59 行的 hardcoded password 问题。注意,虽然

部分连接字符串可动态联接,但当密码等信息直接进行硬编码到字符串中时,所得到的值只包括了数据库的名称。虽然该问题不会被直接利用,但任何人只要获得源代码,就会获得该密码,并且如果密码在应用程序部署后被损坏,将很难更改密码。检查余下的 hardcoded password 问题

并记录下您的发现。

26 Fortify Source Code Analysis 入门

Page 31: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

5. 检查 Race Condition:Singleton Member Field 问题。

选择发生在 HammerHead.java 中第 86 行的 race condition 问题。滚动至源文件的顶部,并注

意被赋值的变量是类 HammerHead 的成员变量。因为该类实现了 doPost() 和 doGet() 方法,您可以假定它继承了 HttpServlet;但要验证该假定,请检查类声明。您可以看到它确实

继承了 HttpServlet,这使它成为一个单独的对象,并且确定了对其成员变量的任何赋值都容

易发生 race condition,因为同一对象被用于处理多个请求。请注意,这是一个不容易通过跟踪

发现的错误,因为当应用程序投入实际使用后,只有在用量很大的情况下,才会出现该问题。

选择发生在 LessonSource.java 中第 53 行的 race condition 问题。注意,这是您刚才检查

过的 HammerHead 的子类。再一次为类的成员变量赋值,该类继承了 HammerHead,因而也继

承了 HttpServlet。对于这个问题,您可以使用与 HammerHead.java 中成员字段 race condition 问题相同的注释。

6. 检查在 Warning (警告)和 Info (信息)中余下的问题。

既然您正在审计问题并试着找出真正的漏洞,那么请继续从 Warning (警告)和 Info (信息)

中审计余下的问题。如果您碰到一个使您感到很困扰的问题,请打开您在第一次练习中检查的已完成的审计,并将您的结果和在那里标记的地方相比较。

7. 保存您的更改并关闭该项目,但保留 Audit Workbench 继续运行。下一个练习将从本次练习停

止的位置继续。

深入讨论

为了更好地理解您在审计中发现的问题,请研究 ECS 库,并研究它的典型使用方式。注意,我们并

没有采取任何措施来避免 cross-site scripting 漏洞。

练习 9:编写自定义规则

现在,您应该已完成了练习 8 并在 Audit Workbench 中打开了经过完整审计的 WebGoat 的分析结果。

Fortify SCA 使用的所有分析器都是由规则驱动的,因此可以对它们进行扩展和自定义,以便对程序

的特定安全属性进行检查。自定义的规则也用来标识库入口点 (即攻击者可能会控制的调用)和验

证函数,验证函数用来确保用户输入不包含恶意数据。本练习对通过自定义规则来对 Fortify SCA 进行扩展的一些方法进行了探索。

Fortify SCA 的规则是用 XML 语言编写的。编写新规则的 好方法是为每个分析器和规则类型都单独

创建一个模板规则,然后复制这个模板规则,在您要写某条特定的规则时修改一些必要的字段即可。

这个方法减少了在规则中出现格式错误或逻辑错误的可能性,并且简化了编写规则的过程。本练习

所包含的每一步的模板和完整规则文件可以在以下目录中找到:

<install_directory>/Tutorial/Java/answers/exercise9

1. 创建一个规则包。

打开 Audit Workbench。

单击 New Rulepack (新建规则包)链接。

屏幕中将显示 Create Rulepack (创建规则包)对话框。

浏览至以下目录,输入文件名 rules,然后单击 Save (保存):

<install_directory>/Tutorial/Java/source/webgoat

“Table (表)”视图中会显示 Custom Rules Editor (自定义规则编辑器)。单击 XML View(XML 视图)选项卡。

屏幕上会显示以下 XML 代码。

注意:RulePackID 号可能会有所不同,因为它是动态生成的。

Fortify Source Code Analysis 入门 27

Page 32: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

<?xml version="1.0" encoding="UTF-8"?>

<RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="RulePack">

<RulePackID>70857D60-F044-4A97-B694-D2BB99305E76</RulePackID><SKU>SKU-rules.xml</SKU><Name><![CDATA[rules.xml]]></Name><Version>1.0</Version><Description><![CDATA[Description for rules.xml]]></Description><Rules version="3.4">

<RuleDefinitions> </RuleDefinitions>

</Rules>

</RulePack>

这个空规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step1.xml

当自定义规则的类型和要使用的分析器一致时,有效的规则包定义的 <RuleDefinitions> 元素可以包含任意数量的规则。以下步骤中的每一步都给出了使用 Fortify SCA 中的某个分析器,

可以识别出程序源代码属性或构造的简单文字描述。在每个规则所解决的问题的描述后,提供了规则的 小 XML 实现。可选规则元素,例如描述,不包括在其中。

2. 创建并测试一个 semantic (语义)规则。

假设 WebGoat 用户名允许包含 HTML 元字符,这就意味着在任何动态 HTML 内容中使

用它们前,都应该先对其进行验证。为了证实您对用户名被误用的怀疑,在规则包的 <RuleDefinitions> 元素中包含以下标准的语义规则。此规则无条件地标记对 session.WebSession.getUserName() 函数的所有调用。

将光标置于 RuleDefinitions 区域中,并按Control -Space 键,以显示规则选项下拉菜单,

然后选择 <SemanticRule>。

系统会显示语义规则模板和一个动态生成的规则 ID。

使用 Control-Space 键自动结束功能,按如下方式进行修改:

<SemanticRule formatVersion="3.4" language="java"><RuleID>A090AAC1-9CA8-4F40-994D-8C30FC6D4671</RuleID><VulnCategory>Dangerous Input Source</VulnCategory><DefaultSeverity>4.0</DefaultSeverity><Type>default</Type><Description/><FunctionIdentifier>

<NamespaceName><Value>session</Value>

</NamespaceName><ClassName>

<Value>WebSession</Value></ClassName><FunctionName>

<Value>getUserName</Value></FunctionName><ApplyTo overrides="true" extends="true" implements="true"/>

</FunctionIdentifier>

</SemanticRule>

28 Fortify Source Code Analysis 入门

Page 33: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

包含此规则的规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step2.xml

规则定义的核心是称为函数识别符的元素,它可以用来控制触发规则的函数。一个标准的函数识别符由命名空间(或包)、类和函数构成。每个组成部分既可以用实际的字符串(使用 <Value> 标签)表示,也可以用正则表达式(使用 <Pattern> 标签)表示。override、extend 和 implement 属性用来控制:规则是否应该与重写指定函数的指定类的子类中的函数相匹配,或

者与指定函数名匹配但未在父类中定义的函数,或者是与所实现接口的指定函数相匹配。

保存您对 rules.xml 所做的更改,然后切换到以下目录:

<install_directory>/Tutorial/Java/source/webgoat

输入以下命令:

sourceanalyzer -cp "WEB-INF/lib/*.jar" -f webgoat_custom.fpr -rules rules.xml .

返回到 Audit Workbench 并选择 File (文件) - Open Audit Window (打开审计窗口)。

系统会显示 Audit Workbench 登录页面。

单击 Open Project (打开项目)

找到 webgoat_custom.fpr 并单击 Open (打开)。

确认对 session.WebSession.getUserName() 的所有调用,现在都标记在 Dangerous Input Source 类别之下。

关闭该项目。

3. 引入错误和丢失结果。

编写规则是一个棘手的过程,因为很容易产生错误并且有时很难发现。为了更好地理解潜在的错误,请返回到 “Custom Rule Editor (自定义规则编写器)”,并从之前的规则中修改函数识

别符,错误地将函数指定为 getUserNames(),而不是 getUserName(),如以下规则所示。

<SemanticRule formatVersion="3.4" language="java">

<RuleID>A090AAC1-9CA8-4F40-994D-8C30FC6D4671</RuleID><VulnCategory>Dangerous Input Source</VulnCategory><DefaultSeverity>4.0</DefaultSeverity><Type>default</Type><Description/><FunctionIdentifier>

<NamespaceName><Value>session</Value>

</NamespaceName><ClassName>

<Value>WebSession</Value></ClassName><FunctionName>

<Value>getUserNames</Value></FunctionName><ApplyTo overrides="true" extends="true" implements="true"/>

</FunctionIdentifier>

</SemanticRule>

反映这个变化的规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step3.xml

输入以下命令:

sourceanalyzer -cp "WEB-INF/lib/*.jar" -f webgoat_custom.fpr -rules rules.xml .

Fortify Source Code Analysis 入门 29

Page 34: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

返回到 Audit Workbench 审计窗口。

单击 webgoat_custom.fpr。

确认您新建的 Dangerous Input Source 问题不再出现在输出中,因为函数识别符与预期函数不

匹配。

4. 使用正则表达式使规则更灵活。

函数识别符中的错误是导致规则不能如期执行的主要原因之一。一种简单地减少错误指定函数识别符的方法是,使用正则表达式使它与一个范围更广的、满足某种命名约定的函数名称相匹配。

修改在上一步中不能正确匹配任何函数的规则,使用正则表达式以便可以匹配任何以字符串 getUser 开头的函数,规则如下。

<SemanticRule formatVersion="3.4" language="java">

<RuleID>A090AAC1-9CA8-4F40-994D-8C30FC6D4671</RuleID><VulnCategory>Dangerous Input Source</VulnCategory><DefaultSeverity>4.0</DefaultSeverity><Type>default</Type><Description/> <FunctionIdentifier>

<NamespaceName><Value>session</Value>

</NamespaceName><ClassName>

<Value>WebSession</Value></ClassName><FunctionName>

<Pattern>getUser.*</Pattern></FunctionName><ApplyTo overrides="true" extends="true"/>

</FunctionIdentifier>

</SemanticRule>

反映这个变化的规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step4.xml

输入以下命令:

sourceanalyzer -cp "WEB-INF/lib/*.jar" -f webgoat_custom.fpr -rules rules.xml .

返回到 Audit Workbench 审计窗口。

单击 webgoat_custom.fpr。

确认会再次检测到 Dangerous Input Source。

5. 创建并测试数据流 source 和 sink 规则。

检查标记在 BasicAuthentication.java 第 173 行中的 Dangerous Input Source 问题。

ECS 函数 ElementContainer.addElement() 可以通过多种方式使用,但在这个例子中,

它会收集随后将被送回给用户 Web 浏览器的内容,使得 WebSession.getUserName() 的使

用容易受到 cross-site scripting 的攻击。要将此标记为一个 Cross-Site Scripting 问题,您可以

编写两条自定义规则:WebSession.getUserName() 的数据流 source 及 ElementContainer.addElement() 的数据流 sink。为了鉴别此漏洞和其他一些新的漏洞,

请在您的规则包中包含如下数据流规则。这些规则将 WebSession.getUserName() 当作用

户输入的 source,而将 ElementContainer.addElement() 当作 cross-site scripting sink。

<DataflowSourceRule formatVersion="3.4" language="java">

<RuleID>CC8A592E-277F-4D25-93AC-7F1EF0994CF6</RuleID>

30 Fortify Source Code Analysis 入门

Page 35: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

<TaintFlags>+XSS,+HTTPRS,+WEB</TaintFlags><FunctionIdentifier>

<NamespaceName><Value>session</Value>

</NamespaceName><ClassName>

<Value>WebSession</Value></ClassName><FunctionName>

<Value>getUserName</Value></FunctionName><ApplyTo overrides="true" extends="true" implements="true"/>

</FunctionIdentifier><OutArguments>return</OutArguments>

</DataflowSourceRule>

<DataflowSinkRule formatVersion="3.4" language="java">

<RuleID>D99929A9-37C5-4FED-81CA-B6522AE8B763</RuleID><VulnCategory>Cross-Site Scripting (custom)</VulnCategory><DefaultSeverity>4.0</DefaultSeverity><Description/><Sink><InArguments>0</InArguments><Conditional>

<TaintFlagSet taintFlag="XSS"/> </Conditional>

</Sink><FunctionIdentifier>

<NamespaceName><Value>org.apache.ecs</Value>

</NamespaceName><ClassName>

<Value>ElementContainer</Value></ClassName><FunctionName>

<Value>addElement</Value></FunctionName><ApplyTo overrides="true" extends="true" implements="true"/>

</FunctionIdentifier>

</DataflowSinkRule>

包含这些规则的规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step5.xml

关闭该审计项目。

输入以下命令:

sourceanalyzer -cp "WEB-INF/lib/*.jar" -f webgoat_custom.fpr -rules rules.xml .

返回到 Audit Workbench 审计窗口。

单击 webgoat_custom.fpr。

确认 Cross-Site Scripting (自定义)类别中报告的问题出现在 BasicAuthentication.java 中第 173 行。

Fortify Source Code Analysis 入门 31

Page 36: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

注意,另一个问题会被报告在 Cross-Site Scripting (自定义)类别中,但是其输入源于一个 HTTP 请求参数,而不是 WebSession.getUserName()。报告出这个问题,是因为安全编码

规则包会认为所有 HTTP 请求参数均被 HTML 元字符感染。自定义规则为空时不起作用。通常

情况下,在安全编码规则包中增加少量自定义规则,可使问题的检测变得更广泛或更准确。

6. 创建并测试数据流净化规则。

到现在为止,您已经编写了自定义规则,去识别那些没有被安全编码规则包检测到的新问题。自定义规则也可用来排除由 Fortify SCA 不理解的程序逻辑所引起的错误判断。

检查报告在 WeakAuthenticationCookie.java:363 中发生的 Cross-Site Scripting 问题。

注意,作为 source 的 ParameterParser.java:651 的数据流路径表明,被感染的变量在到

达 sink 之前会先通过 checkParams() 函数。

单击分析树中的结点。

在编辑器中选择 checkParams()。

右键单击并选择 opendeclaration。

如果 HTTP 请求参数提交的用户名是 webgoat 或 aspect,那么函数将会返回此用户名。如果它

还有另一个值,那么函数将报告错误并返回空值。由于有了这个逻辑,checkParams() 的返回

值的安全得到了保证,因为它只能是由应用程序控制的三个值中的一个。这种类型的函数接受被感染的输入,然后返回一个安全值,因此被称为净化函数。

为了给 checkParams() 的净化行为制作模型并且排除错误判断,请在您的规则包里包含以下

数据流净化规则。

<DataflowCleanseRule formatVersion="3.4" language="java">

<RuleID>E79458AA-6428-4126-91B4-696FF370E1DB</RuleID><FunctionIdentifier>

<NamespaceName><Value>lessons</Value>

</NamespaceName><ClassName>

<Value>WeakAuthenticationCookie</Value></ClassName><FunctionName>

<Value>checkParams</Value></FunctionName><ApplyTo overrides="true" extends="true" implements="true"/>

</FunctionIdentifier><OutArguments>return</OutArguments>

</DataflowCleanseRule>

包含此规则的规则包也可以在以下文件中找到:

<install_directory>/Tutorial/Java/answers/exercise9/step6.xml

输入以下命令:

sourceanalyzer -cp "WEB-INF/lib/*.jar" -f webgoat_custom.fpr -rules rules.xml .

返回到 Audit Workbench 审计窗口。

单击 webgoat_custom.fpr。

确认通过 checkParams() 的错误数据流不再报告 WeakAuthenticationCookie.java 中第 363 行有 Cross-Site Scripting 问题。余下的数据流路径是有效的,因为在包含至动态 HTML 内容之前,在用户名上将不会执行合适的验证。

32 Fortify Source Code Analysis 入门

Page 37: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

答案本节包含了对在练习 2 (人工审计源代码)中列出的问题的答案。为了方便,我们再次列出了这些

问题。

1. 从提问开始。

应用程序有多大?

该应用程序有 3 个 Java 文件,2 个 JSP 文件,1 个 SQL 包,4 个配置文件以及 1 个 jar 文件。

只计算 Java 和 SQL 的话,总共有大概 100 行代码。因此这是一个非常小的 J2EE 应用程序。

包含了哪些技术?

Java、 JSP、 Struts、 servlets、 EJB、 PL/SQL 及 SQL。

应用程序的基本设计是怎样的?

JSP 与 servlet 和 Struts action 交互数据。Struts action 使用 EJB,而 EJB 使用关系数据库作为

持久化存储器。

谁是可能的攻击者?

基于 Web 的应用程序一般都会放在 Internet 上,所以任何人都有可能攻击它。您可能需要考虑

那些对于恶意行为、恶作剧或者专业的犯罪感兴趣的攻击者。攻击者也可能是一个内部人士,他将比一个外来者拥有更多权限,也对系统更加了解。

攻击者想要达到什么目的?

关系数据库中的内容对于攻击者来说是一个明显的目标。攻击者可能想要窃取数据库中的内容,修改他人的数据,或者干脆停止对其他用户的服务。您还需要考虑能确保攻击者无法接管应用程序服务器,无法修改应用程序对于其他用户的行为,并且无法使用应用程序执行不同的攻击,如 cross-site scripting 或 phishing。

开发人员如何保护应用程序?

从安全的角度来看,使用 Java 和 J2EE 相对于使用 C/C++ 来说是一个很大的进步。它同时也比 PHP 要更加安全。开发者看起来打算使用 Struts 来进行验证。

应用程序的什么地方会引起攻击者的注意?

有可能受到的攻击大概是恶意的 HTTP 请求。

攻击者会使用什么类型的技术来破坏应用程序?

攻击者可能会尝试提交一个包含元字符的请求,旨在破坏数据库或其他外部系统。

成功的攻击会对公司造成什么样的风险?

如果应用程序的漏洞使攻击者可以获得敏感的客户信息,那么该公司可能会受到罚款或其他正式制裁。更加重要的是,如果该公司的客户发现应用程序被攻击者利用,他们会对公司的安全失去信心。这会导致收入减少,并可能会使吸引新客户变得更加困难。

2. 考虑以下 servlet 实现:

Tutorial/java/webapp/webapp/src/java/com/simpleco/CountServlet.java

回答下列问题:

代码在何时执行以及如何执行?

这个 servlet 实现了 doGet() 方法,因此可以推测攻击者将可能向其提交 HTTP GET 请求。

攻击者可以控制什么?

攻击者可以完全控制 HTTP 请求。他们可能会通过浏览器来发送请求,但也可能使用他们自身

的软件来发送恶意请求。

程序开发者是否假设过攻击者可能会违反程序规则?

基于变量的命名,开发者原本期望变量 "count" 是一个数字,但是并没有采取任何措施以防止其

转化为任何文本形式。

这个 servlet 的漏洞是什么?

Fortify Source Code Analysis 入门 33

Page 38: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

攻击者可以利用该 servlet 发起 cross-site scripting 攻击。通过把包含了一些 HTML 或者 JavaScript 的内容作为参数 "count" 的值发送给 servlet,攻击者可以把任意恶意内容反映在网站

上。这可以让攻击者窃取受害者的 cookies,或者诱惑受害者去下载那些看上去来自合法站点的

东西。

3. 结束审计。

以与 CountServlet.java 相同的方式来检查每个应用程序文件。考虑不同模块之间发生的交

互,找出其他可能容易受到攻击的地方。通过使用 Struts action TestAction,攻击者可以在数

据库中执行任何 SQL 查询。来自 TestActionForm 的参数传递给了数据库 LoginFn 函数,

在那里构建一个动态 SQL 查询。通过传递一个嵌入了 SQL 查询的字符串,攻击者实质上可以从

数据库读取任何信息。

应用程序还包含了其他一些不是很严重的错误,但也值得引起注意。首先,应用程序配置文件 web.xml 没有为重要的错误代码(如 500)定义自定义错误页面,并且没有通过实现 java.lang.Throwable 的错误页面来捕捉未处理的异常。同时,应用程序还有 poor error handling 的问题,例如在 TestAction.java 第 20 行出现的 empty catch block。

34 Fortify Source Code Analysis 入门

Page 39: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

第 3 章:C 和 C++ 代码的分析练习本章包含以下主题:

• 练习

• 答案

每个练习都包含了详细的步骤说明。其中一些练习,在说明的 后一步有一个叫做深入讨论的部分,

包含了更深层次的概念,帮助理解这些练习所覆盖的主题。

这些练习的答案和更深的问题在下面的路径中:

<install_directory>/Tutorial/c/answers

注意:其中一些练习假设您的计算机上有 gcc 编译器和 bash shell 可用。虽然 Fortify SCA 能够配合

其他编译器使用,如 Microsoft cl (这个编译器是 Microsoft Visual Studio 的一部分),但是本章中所

使用的一些示例开源程序是与 gcc 与 bash 配合使用的。

如果您希望在 Microsoft Windows 下使用 gcc 和 bash, 简单的方法之一是安装 Cygwin (http://www.cygwin.com),一个可以任意使用的众多 Gnu 工具的 Windows 端口。不要忘记在 Cygwin 的安装过程中选择 gcc 作为安装的一部分。

练习本部分为练习内容。因为每个练习都建立在前一个练习的基础之上,所以您应按顺序进行。

练习 1:查看一个已完成的审计

在这个练习中,你将使用 Audit Workbench 来检查一个小型 SMTP 守护程序 qwik-smtpd version 0.3 的完整审计。

注意:练习 6 和 7 会重新回到 Audit Workbench,对其进行更加详尽的介绍。

1. 启动 Audit Workbench。

在 Windows 中:在开始菜单中,导航至开始 - 所有程序 - Fortify Software - Fortify SCA 5.0 - Audit Workbench。

对于其他操作系统:在终端或命令提示界面中,运行 auditworkbench。

系统会显示 Audit Workbench 开始画面,然后会显示启动页。

2. 加载审计。

选择 Open Project (打开项目)。

选择以下文件并单击 Open (打开):

<install_directory>/Tutorial/c/audits/qwik-smtpd/qwik-smtpd.fpr

注意:在某些安装中,将显示 “Project Source Path (项目的源路径)”

对话框。单击 Yes (是)并选择以下源目录:

<Install_directory>/Tutorial/c/source/qwik-smtpd

3. 阅读 Project Summary (项目汇总)。

Fortify Source Code Analysis 入门 35

Page 40: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 21:项目汇总

查看 Project Summary (项目汇总)面板中显示的信息。请注意 Project Summary (项目汇总)

提供已加载的分析结果的总体概述,如已分析的项目的大小。

4. 使用 Issues (问题)面板。

图 22:问题面板

在 Issues (问题)面板中,您将看到问题的文件夹。 Hot (严重)文件夹包含了优先级 高的问

题,接下来是 Warning(警告), 后是 Info(信息),它包含了优先级 低的问题。All(全部)

文件夹包含了所有问题。

5. 转到 Issues (问题)导航面板并分别单击Hot (严重)、 Warning (警告)和Info (信息),

看问题是如何按照优先级分组的。

6. 单击 Hot (严重),然后展开导航树中的 Format String 类来查看单个问题。

36 Fortify Source Code Analysis 入门

Page 41: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 23:显示单个问题的问题导航面板

文件名左边的图标表示审计员对每个问题暴露的风险的评估,范围从安全到可利用。在这个项目中,审计员将所有 Format String 问题都归类为可利用。但是在本练习的稍后部分,您会发现

有种类繁多的状态图标,可以用来表示问题审计时的不同级别。下图显示了每个图标和它所表示的审计状态的对应关系。请注意,正如 《Audit Workbench 用户指南》中所介绍的,审计状

态标签是可以自定义的。

图 24:审计状态图标

7. 展开在 qwik-smtpd.c 的第 434 行中报告的项目。请注意在顶级条目下,实际上有三个问题。

Audit Workbench 将共享同一个终点(称为 sink)但是不同起点 (称为 source)的问题分在一

组。由于在同一指令中结束的问题通常代表了某个漏洞的多个实例,因此这种分组形式有助于同类问题的审计。在这个例子中,这个接收 format string 参数的函数出现在 qwik-smtpd 的第 434 行,但是却有三种路径起源于三种完全不同的输入源。在这个例子中,输入源也在 qwik-smtpd.c 中。它们分别在第 182、 506 和 584 行。

Fortify Source Code Analysis 入门 37

Page 42: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 25:显示 Sink 和 Source 的导航面板

8. 查看某个问题摘要。

在 Issues (问题)面板中找到并选中以下 format string 问题:

from getline(0) - qwik-smtpd.c:182

考虑与这个问题相关联的源代码,并注意存在漏洞的函数是对 fprintf() 的调用。

图 26:源代码视图

在Issue Auditing (问题审计)的 Summary (总结)选项卡中,仔细阅读审计员对该问题的注

释,并注意审计员针对这一问题所选择的分析选项。同时也应注意 Category (类别)字段表示

的是,这个问题代表的是什么类别的漏洞,这个漏洞属于哪一大类,和发现这个漏洞的分析器的详细信息,而“Abstract (摘要)”字段给出了关于这个漏洞类别的粗略解释。

38 Fortify Source Code Analysis 入门

Page 43: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 27:总结面板

选择 Details (详细信息)选项卡来读取有关此类漏洞的更多信息。

Fortify Source Code Analysis 入门 39

Page 44: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 28: 详细信息面板

9. 查看 Analysis Trace (分析跟踪)。

单击 Analysis Trace (分析跟踪)面板中的具体条目,查看 Fortify SCA 是如何在整个程序中跟

踪恶意数据的。当选中数据流问题时, Analysis Trace (分析跟踪)面板上所显示的一连串条目

就会提供数据流跟踪信息。跟踪从分析器 先开始追踪数据的那一点开始 (如一个用户输入源),然后在整个程序中一直跟踪该数据,直到找到数据不安全使用的那一点为止。

40 Fortify Source Code Analysis 入门

Page 45: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 29: 分析跟踪面板

10. 生成审计报告。

a. 在 Tools (工具) 菜单中选择 Generate Report (生成报告)。生成的审计报告总结了审

计过程中所发现的问题,并提供了一个良好的机制,和其他人共享您的审计结果。

b. 在 Report (报告) 的下拉菜单中选择 Fortify Security Report (Fortify 安全性报告)。

Fortify Source Code Analysis 入门 41

Page 46: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 30:生成报告

c. 在报告对话框中单击 Save Report (保存报告) 来生成报告。

d. 单击 Browse (浏览)。

e. 从 Format (格式) 下拉菜单中选择 PDF。

f. 使用 Acrobat Reader 打开报告。注意,报告包含了所分析项目的信息,所报导的问题的类

型和数量,以及被审计的个别问题的摘要。

深入讨论

探讨其他问题。查看其他类别中的问题,并阅读审计员对这些问题的相关注释。有关每一类问题的更

多一般信息,请参见 Issue Auditing (文体审计) 面板中的 Details (详细信息) 选项卡。

42 Fortify Source Code Analysis 入门

Page 47: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 2:人工审计源代码

理解静态分析工具为什么重要的一个 好的办法是不借助任何分析工具来检查一组代码。该练习演示

了在不使用任何支援工具的情况下,对一个小型 web 应用程序进行基础安全审计所涉及到的步骤。

任何形式的代码检查都需要耐心,仔细查看细节,还需要具有对那些会造成风险的问题类型的丰富

知识。安全审计没有什么不同,但在考虑 “什么东西可能出错?”的问题上,审计员必须转而考虑

“什么东西会在攻击者的影响下出错?”审计员的职责就是将无穷大的搜索范围缩小,找出应用程序

中 危险的问题和 容易受到攻击的漏洞。经验是无价的,而经验来自于实践。

应用程序的根目录是:

<install_directory>/Tutorial/c/source/qwik-smtpd/

注意:有关更多信息,请参见 README 和 INSTALL 文件。

1. 回答下列问题:

a. 应用程序有多大?

b. 包含了哪些技术?

c. 应用程序的基本设计是怎样的?

d. 谁是可能的攻击者?

e. 攻击者想要达到什么目的?

f. 开发人员如何保护应用程序?

g. 攻击者会使用什么类型的技术来破坏应用程序?

h. 成功的攻击会对公司造成什么样的风险?

2. 检查源文件 qwik-smtpd.c,位于以下路径中:

<install_directory>/Tutorial/c/source/qwik-smtpd/

3. 回答下列问题:

a. 执行 main() 的方式和时间?

b. 对程序输入的哪一部分会被攻击者所控制?

c. 程序开发者是否假设过攻击者可能会违反程序规则?

d. 该代码易于受到攻击么?

4. 回顾答案。

直接跳到本章节 后的答案部分,寻找在上面文章中提到的相关问题的答案

现在,您已经检查了一个现存的审计,且手动执行了一个自身的简单的审计,您能想象手动审计一

个由 100,000 条代码所组成的项目所需要的资源吗?而 500,000 或 5,000,000 又是怎么样?人工完

成大规模的代码审计的资源要求是非常庞大的,而且审计员理解不同代码领域中复杂的相互作用的

能力又相当有限。在现实中,对企业系统的人工代码检查要求非常小心地进行选择和检查应用程序

的少部分。虽然人工审计能够有效地查找到漏洞,但是却没有办法涉及到那些未经检查的代码部分。

接下来的练习介绍了分析和审计源代码以便查找出安全漏洞的工具,并通过具体示例演示了如何有

效利用这些工具来审计企业系统规模的代码的主体部分。

Fortify Source Code Analysis 入门 43

Page 48: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 3:运行 Fortify Source Code Analyzer本练习介绍了 Fortify SCA。请您检查已经正确安装该工具,并用它来分析一个小程序。随后,本练

习将会帮助您理解工具产生的输出,并且向您展示通过不同的方式来分析一个真实的项目。

1. 分析单个源代码文件。

切换到以下目录:

<install_directory>/Tutorial/c/source/winner

输入以下命令:

sourceanalyzer gcc winner.c

2. 与预期结果相比较。您将会从屏幕终端上看到类似于下面的输出信息:

[# : low : Unchecked Return Value : semantic]

winner.c(16) : read()

[# : medium : String Termination Error : dataflow ]

winner.c(21) : ->sprintf(2)winner.c(16) : <- read(1)

[# : medium : Memory Leak : controlflow ]

winner.c(12) : start -> allocated : inBuf = malloc(...)winner.c(12) : allocated -> allocated : inBuf refers to dynamically allocated memorywinner.c(13) : Branch not taken: (inBuf != null)winner.c(18) : Branch taken: (outBuf == null)winner.c(19) : allocated -> allocated : returnwinner.c(19) : allocated -> allocated : inBuf no longer refers to dynamically allocated memorywinner.c(19) : allocated -> leak : inBuf end scope : Memory leaked

注意:为了保持可读性, 32 位十六进制的实例标识符已经用哈希标记 (#) 进行了取代。

3. 把您分析的输出结果与上述做比较。练习 4 将会详细描述列出的每个问题。

练习 4:理解未处理的分析结果

本练习将会引导您浏览一下在练习 3 中为小程序 winner.c 分析产生的分析结果 Fortify SCA。检查

构建在 Fortify SCA 中的各种分析器生成的问题,以及比较由 Fortify SCA 生成的不同输出格式。

1. 请考虑 winner.c 的内容:

44 Fortify Source Code Analysis 入门

Page 49: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 31:winner.c 的代码

2. 检查该语义问题。

下列图示突出显示了在练习 3 的 winner.c 中检测到的 unchecked return value 问题中的各种

元素。

图 32:语义问题中的元素

在 winner.c 中检测到的 unchecked return value 问题中的各种元素如下:

唯一标识符:开头的十六进制数 (在此文本中以哈希标记 (#) 代替)是一个全局性唯一标识符,

也称为实例标识符。这些标识符以分析器找到问题的路径、漏洞类型以及其他一些不受细小的代码变动影响的因素为基础而计算得出。例如,唯一识别符不依赖于代码行数。除了唯一性,实例识别符还提供了其他十分有价值的功能,它们可以标识出在多次分析中或不同代码版本之间的相同问题,因此可以被用来追踪审计过的问题。

严重性:因为该问题本身并不能使得攻击者攻击程序,所以 Fortify SCA 把它的严重级别设为

“低”。

漏洞类别:当一个返回错误信息,或者其它重要数据被使用,但程序忽略了它的返回值时,就会报告 Unchecked Return Value 类问题。

分析器:问题由语义分析器报告出来。语义分析器以与编译器稍后分析其语义短语的相近方式来检查代码。请参见 《Fortify Source Code Analyzer 用户指南》,以获取有关分析器的更多信息。

文件名/行号:Fortify SCA 会报告带有忽略返回值的函数调用的位置。

易受攻击的函数:对 read() 的调用是该问题的根源。

Fortify Source Code Analysis 入门 45

Page 50: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

3. 检查数据流问题。

使用下列图示来理解 string termination 问题:

图 33:数据流问题

请注意,这有许多字段和上面语义问题中提到的一样。这些字段的含意在数据流问题 (和在下面要讨论的其他类型的问题)中是相同的。在这里,您将更加关注那些没有在语义问题中出现的字段。数据流问题比语义问题更复杂,因为它们牵涉到源代码中的多个地方。这是一个 string termination 问题,它发生在受攻击者控制的缓存没有包含 null 中止符,但它却被用作有这样一

个 null 中止符的字符串。数据流分析器将会跟踪那些潜在的恶意输入数据,从数据被输入到程

序中一直到它被用来作为攻击的一部分。

Sink:该 sink 的文件名、行号及函数名称指出了将受攻击者控制的缓存用作为字符串的位置。

紧随在行号之后而在函数名称之前的右箭头 (->) 指出被感染的数据流入了 sprintf。方法名后

括号内的数字是这个方法的参数编号。数字 2 表示攻击者可以控制 sprintf 的第三个参数(从 0 开始编号)。在本例中,第三个参数即变量 inBuf。

Source:该 source 的文件名、行号及函数名称指出了受攻击者控制的数据 先进入程序的位

置。紧随在行号之后而在类名和方法名之前的左箭头 (<-) 指示 read() 引入了被感染的数据。

函数名称之后的数字 1 (括号之内)表示第二个函数参数在函数调用后持有了被感染的数据

(从 0 开始编号)。在本例中,第二个参数即变量 inBuf。

4. 检查控制流问题。

使用下列图示来理解 memory leak 问题。

图 34:控制流问题

控制流问题看上去类似于数据流问题,因为它们通常包含多个结点,不同点在于这些结点所代表的操作步骤是不安全的。 Control flow 漏洞被表述为一系列状态的转换。

46 Fortify Source Code Analysis 入门

Page 51: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

开始状态/结束状态:第一个状态转换项显示了从 start 状态到 allocated 的状态转换发生在

第 12 行。 后一个状态转换项显示了从 allocated 状态到 leak 状态的转换发生在第 19 行。

转换表达式:转换表达式紧跟在开始和结束状态之后。它给出了触发转换的代码构成。从 start 到 allocated 的转换由调用 malloc() 引起。从 allocated 到 leak 的转换由变量 inBuf 到达其域的终止处而引起。

控制流分析器找到了一个路径,可导致在没有调用 free() 的情况下引起分配内存的泄漏。虽

然 free() 调用发生在第 24 行,但是由于函数可能会在第 19 行返回,所以并不能保证对 free() 的调用总是会被执行。

5. 生成一个 Fortify Project Results (FPR) 文件。

Fortify SCA 不但能够生成可以直接被审计员阅读的输出,还能够生成一个 FPR 文件,此文件可

以用 Audit Workbench 或者其他工具进行使用。

再次执行 Fortify SCA,但是这次只生成 FPR 输出。使用 -f 选项将输出发送给 FPR 文件,如

下所示:

sourceanalyzer -f results.fpr gcc winner.c

深入讨论

重写 winner.c 来解决您检查到的安全问题。再次执行 Fortify SCA 来验证您的工作。

练习 5:分析一个完整的应用程序

本练习演示了如何使用 Fortify SCA 来分析一个完整的应用程序。分析需要三个步骤:

1. 配置项目使得它可以进行编译。

2. 把所有源代码文件转译为 SCA 中间文件。

切换到以下目录:

<install_directory>/Tutorial/c/source/qwik-smtpd

输入以下命令:

sourceanalyzer -b qsmtpd -clean

sourceanalyzer -b qsmtpd make

向 Fortify SCA 指定的命令行参数:

clean 构造整合选项:删除所有 Fortify SCA 中间文件和构造记录。当同时指定了构造 ID 时,仅

会删除与这个构造 ID 相关的文件和构造记录。

构造标识符:参数 -b qsmtpd 表示即将构造的项目名称为 "qsmtpd"。在扫描的过程中,您提

供相同的构造标识符来指明所有与 qwik-smtpd 相关的文件都应该被分析。

make 命令:Fortify SCA 会识别 make 命令,并且在 make 执行时自动检查所有被编译的源代码。

3. 执行扫描。

输入以下命令:

sourceanalyzer -b qsmtpd -scan -f qwik-smtpd.fpr

该命令可能需要数分钟来完成执行。

命令行参数为 Fortify SCA 指出了三个事项:

构造标识符:-b qsmtpd 参数指明了项目的名称。Fortify SCA 现在会把所有在上一步中使用该

命令编译的代码关联起来。

扫描标记:-scan 标记会告诉 Fortify SCA 去分析项目。

输出文件:-f qwik-smtpd.fpr 参数会告诉 Fortify SCA 把它的输出写到文件 qwik-smtpd.fpr 上。因为文件名以 .fpr 扩展名结尾,Fortify SCA 会自动以 FPR 格式写入其输出。

您将会在下个练习中使用 Audit Workbench 来检查分析结果。

Fortify Source Code Analysis 入门 47

Page 52: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 6:使用 Audit Workbench 调整结果

本练习描述了如何使用 Audit Workbench 来调整由 Fortify SCA 生成的分析结果。这样调整的目的是

要限制检查的问题,以更适合应用程序和审计员的检查方式。一般而言,一个专业的代码审计员和一

个有安全意识的软件开发者不会检查同一组结果。显示过程允许不同的审查员按他们的目的来配置 Fortify SCA。

1. 启动 Audit Workbench。

在 Windows 中:从 开始 菜单中,导航至开始 - 程序 - Fortify Software - Fortify SCA 5.0 - Audit Workbench。

在其他平台上:在终端或命令提示界面中,运行 auditworkbench。

系统会显示 Audit Workbench 开始画面,然后会显示启动页。

2. 加载审计。

选择 Open Project (打开项目)。

选择您在练习 5 中建立的 FPR文件,单击 Open (打开):

<install_directory>/Tutorial/c/source/qwik-smtpd/qwik-smtpd.fpr

系统会显示 Project Summary (项目汇总)面板。

请注意,在 Hot (严重) 文件夹中有 12 个问题,在 Warning (警告) 文件夹中有 15 个问题,

在 Info (信息) 文件夹中有 10 个问题,而在 All (所有) 文件夹中有 37 个问题。

图 35:项目汇总面板

3. 使用 Audit Guide (审计指南)向导来过滤与质量相关的问题。

a. 选择 Tools (工具)菜单中的 Audit Guide (审计指南),或单击 Audit Guide (审计指

南)按钮。

系统会显示“Audit Guide (审计指南)”设置面板。

48 Fortify Source Code Analysis 入门

Page 53: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 36:审计指南设置面板

b. 单击 Advanced Mode (高级模式)。

系统会显示 “Advanced Audit Guid (高级审计指南)”面板。

c. 选择 Poor Programming Style Issues,检查相应的复选框,然后单击 OK (确定)。

Fortify Source Code Analysis 入门 49

Page 54: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 37:高级审计指南面板

d. 单击 OK (确定)隐藏 code quality 问题。

e. 选择 Options (选项) - Show Hidden Item (显示隐藏项)来查看隐藏的结果。

50 Fortify Source Code Analysis 入门

Page 55: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

图 38:隐藏的问题

4. 应用另一组过滤器。

从 Filter Set (过滤器组)下拉菜单中选择 Medium (中)。

注意,已经删除了不少的问题。过滤器组可使得结果看上去像是只用一部分规则分析出来的一样,这样可以让您在寻找所有可能的问题和寻找那些 严重、级别 高的问题之间找到平衡。

图 39:过滤器组

如果您将继续下一个练习,请不要关闭 Audit Workbench。

深入讨论

从 Tools (工具) 菜单选择 Audit Guide (审计指南),并且尝试提供的选项。研究每一个设置都

隐藏了哪些问题 (如果有)。

Fortify Source Code Analysis 入门 51

Page 56: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

练习 7:审计某个问题

您应该已完成了练习 6 而且有了在 Audit Workbench 中打开的 qwik-smtpd 分析结果。

该练习是从上一个结束的练习继续下去的,并解释了审计问题的步骤,强调 Audit Workbench 中对完

成审计极为重要的各种功能。您需要确切地理解 Fortify SCA 报告的内容,以及包含问题的代码的行

为。与人工审计一样,使用静态分析工具的审计员需要提出合适的问题,以充分利用各种可能的结果。

1. 收集在 Issues (问题) 面板中报告的关于各种问题的高级信息。

三个严重级别选项卡, Hot (严重)、 Warning (警告)和 Info (信息),显示在每个严重级别

上检测到的问题的数量。单击其中一个严重级别选项卡,可在 Issues (问题)树中显示属于此

严重级别的问题。选择 Hot (严重),并注意这些条目是一组 format string 问题。

在 Issues (问题) 树中整理项目的方法是通过在 Group by (分组方式) 下拉菜单选择进行控制

的。项目可以按以下方式进行分组:Category (类别)(默认分组方式)、 File name (文件

名)、Analyzer(分析器)、New issue(新的问题)、Sink、Source、Package(包)、Taint flag(感染标记)、Analysis(分析)、OWASP Top Ten 2004、OWASP Top Ten 2007、Fortify Priority Order (Fortify 先后顺序) 或 Category Analyzer (类别分析器),或直接显示在平面结

构中,不进行任何分组。从 Group by (分组方式) 下拉菜单中选择 Source,注意到问题 2 是数据通过函数 fgets() 进入程序的结果。

“Issues (问题)”面板底部的文本域是用来搜索显示在 Issues (问题) 树中的问题,仅留下和

搜索相匹配可见的问题。搜索可以在 Any Field (任何域)(默认情况)下执行,或者使用高级

查询语句。有关 Audit Workbench 支持的查询语言的更多信息,请参见 《Audit Workbench 用户指南》。在搜索字段中输入查询字符串 'sprintf' ,然后按 Enter 键。因为 Group by (分组方

式) 菜单仍设置为 Source, Issues (问题) 树显示所有涉及到由问题源函数整理的 sprintf()。

单击搜索字段旁的 X,再次显示所有问题,并选择 Group by (分组方式)菜单下的 Category(类别)返回到默认视图。

当展开一个类别时, Issues (问题)树会列出属于该类别的每个问题,并显示出现该问题的源

文件和行号。我们会先检查 Hot (严重) 文件夹中的 format string 问题。单击 Hot (严重) 选项卡,然后单击以在 Issues (问题) 树中展开 Format String 类别。

选择在 qwik-smtpd.c 中第 434 行的第二个 format string 问题。请注意 Analysis Trace (分析

跟踪) 和 Issue Auditing (问题审计)面板的 Summary (总结)选项卡是如何来显示有关所选

问题的信息。同时注意在源代码面板中打开的 qwik-smtpd.c,带有被感染数据突出显示为蓝

色的行。简单定位一个问题中的各种结点和快速检查相关源代码的能力,使得理解一个问题比起人工检查整篇代码要简单得多。

右键单击选中的问题。注意,在此菜单中,您可以抑制问题、根据该问题生成一个过滤器,或自动生成一个错误报告。一旦您完成审计该问题,判定它是否属于 Hot (严重) 文件夹。如果该

问题的结果是一个出现在编码环境中的合法 Format String 漏洞,它应该仍然在 Hot (严重) 文件夹中。

2. 使用 Analysis Trace (分析跟踪) 面板检查从 source到 sink 的路径。

Analysis Trace (分析跟踪)面板中的每个结点对应所选问题中的一步。对于数据流问题,每个

结点对应于被跟踪的数据从 source 到 sink 过程中的一次函数调用、分配或返回语句。虽然一些

分析跟踪看起来很像堆栈跟踪,但应避免以堆栈的方式来看待它们。而是将它们当作沿时间线的一系列事件。时间从 Analysis Trace (分析跟踪)面板的顶部开始,一直往后到 后一个结点,

即出现问题的地方。当选中一个新问题时,“Source Code Viewer (源代码查看器)”面板中将

默认显示Analysis Trace (分析跟踪)中的 后一个结点。

选择 Analysis Trace (分析跟踪)中的第一个结点,该结点与数据流的 source 相对应。相对应

的源代码会显示在“Source Code Viewer (源代码查看器)”面板中。这种情况下,源是对 getc() 的一次调用,利用从 stdin 中读取的数据填充缓冲区。

52 Fortify Source Code Analysis 入门

Page 57: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

选择在 source (第一个结点)和 sink ( 后一个结点)之间的每个结点。注意没有通过数据流

分析跟踪感染值的表达式执行任何验证,或者减轻 format string 攻击的危险。下列图标出现在

数据流路径中,表示每个结点上的表达式的类型:

1. 检查摘要信息并给问题做注释。

“Issue Auditing (问题审计)”面板的 Summary (摘要) 和 Details (详细信息) 选项卡提供

了双重目的,既提供有关在 Issues (问题) 面板中选中的问题的附加信息,同时允许用户对该

问题加注注释。在面板右边的粗体文本提供了问题的类别,该类别跟在括号之中,根据漏洞所属类型进行划分,并提供了检测出该问题的具体分析器。在该信息之下,跟有一个对该漏洞的简单描述, More Information (更多信息) 链接可打开 Details (详细信息) 选项卡,

Recommendations (建议) 链接可打开“Recommendation (建议)”选项卡。

表 3: 图标图示

图标 描述

数据被分配到一个字段或变量

信息读取自某个代码的外部数据源 (如 HTML 格式和 URL 等)

数据被分配到一个全局字段或变量

已执行比较

函数调用收到被感染的数据

函数调用返回被感染的数据

Pass-through,被感染的数据在函数调用中从一个参数传递到另一个参数

为某个内存位置创建一个别名

从一个变量读取数据

从一个全局变量读取数据

从一个函数返回被感染的数据

创建一个指针

取消一个指针

变量范围终止

执行跳跃

在代码执行中引入分支

代码执行中未引入分支

常规

Fortify Source Code Analysis 入门 53

Page 58: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

选择 Details (详细信息)选项卡,获取有关该问题的详细描述,包括带有示例的问题的解释。

选择 Recommendations (建议)选项卡,获取有关如何解决问题的建议,在审计类似问题上

的有用提示,以及作为深入了解该主题的参考。当您完成对 format string 漏洞的阅读后,再次选

择 Summary (摘要) 选项卡继续。

在 Comment (注释) 的底部区域中,写一个问题的简要描述及为什么您认为它是漏洞。完成对

该问题的注释后,按 Enter 键。该注释会被贴上时间戳,且添加至注释列表中。

该注释应该包括您在审计问题期间所学到的信息,如引发问题的数据类型 (getline()中的用

户输入),执行验证 (没有)时该怎么办,和问题在上下文中出现的重要意义 (如果这个代码出现在编码环境下会很严重)。此外,当检查问题或该问题生成的报告时,还要考虑 Details(详细信息)选项卡中的部分相关描述。在这个例子中, 好包括来自 Recommendations (建

议)区域中的谈论参数查询的正确使用的建议。

在 Summary (总结)选项卡的左边有一个下拉菜单和两个按钮。下拉菜单用来记录审计的结

果。从“Analysis (分析)”菜单中选择 Exploitable (可利用),表明该问题是可以被攻击者

利用的。

如果在审计问题后,您判断它实际上是安全的,能够通过点击 Suppress (废除) 按钮来废除

该问题。然而,如果问题需要由开发者来解决,您可以单击 File Bug (报告错误)按钮来自动

生成一个需要进行配置的错误报告。

2. 选择 File (文件) 菜单上的 Save Project (保存项目) 保存您的项目。 Audit Workbench 项目

文件存储 初的问题信息和您在审计中所做的更改。

保持 Audit Workbench 运行以继续下一个练习。

练习 8:执行一次完整的审计

您应该已经完成了练习 7,而且有在 Audit Workbench 中打开的 qwik-smtpd 分析结果。

在过去的练习中,您已经检查了一个已完成的审计,执行了对应用程序的分析,并从分析结果中审计

了一个问题。现在,可以执行您自己的安全审计了。配备有需要源代码审计员花费好几年去学习的分

析能力,该练习允许您通过检查一遍在执行安全审计时可能采用的软件安全步骤,练习使用 Fortify SCA 和 Audit Workbench。

1. 审计 Format String 问题。

审计 format string 问题和其他数据流结果时,您需要回答两个重要的问题:(1) 输入源允许攻击

者包括危险字符或内容吗? (2) source 和 sink 之间是否有校验逻辑用来排除输入中的危险内容?

在练习 7 中,您已经审计了 qwik-smtpd.c 中第 434 行的 format string 问题。这个审计步骤由

以下的几步组成:

- 选择问题。

- 检查感染输入源。通过攻击者是否能够控制该输入来确定方法。

- 单击数据流路径中的每个结点,从程序的 source 到 sink 跟踪受感染的数据。寻找程序员可能

减轻由输入带来的安全危险的方法。

设置问题总结中的 Analysis (分析) 字段,以表明问题的重要性。在 终审计报告中输入任意

与该问题一起出现的注释。如果您非常肯定,可以废除该问题。

2. 检查 Buffer Overflow (数据流) 问题。

选择在 qwik-smtpd.c 中第 621 行报告的 buffer overflow 问题。为审计该问题,该论证可判

断它是否可能为攻击者去强制数组索引超出数组的边界。您将按照这四个类似于 Format String 问题的审计步骤。

注意,数据源来自于第 614 行的 getc() 调用的输出。

跟随数据流路径,继续了解您正在跟随的字符串的 大长度;在这种情况下,为数组索引的 大值。在这种情况下,程序不会在索引值上强加一个上界。

54 Fortify Source Code Analysis 入门

Page 59: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

当您到达了数组索引的位置,判断编入索引的数组的大小。它是一个 128 大小的局部声明堆栈

缓冲。

因为数组索引潜在地大于目标缓冲区,这是一个合理的 buffer overflow 发现。该问题被这样的

事实缓和下来,即攻击者不应该被允许去控制充当输入源的配置文件。写下一个注释来解释该情况。

用同样的方法检查余下的 buffer overflow 问题。请注意,不是所有的 buffer overflow 问题都是

危险的,因为在某些情况下,程序逻辑会阻止溢出的发生。

3. 检查在 Warning (警告)和 Info (信息)中余下的问题。

既然您正在审计问题并正试着找出真正的缺陷,那么可以从 Warning (警告) 和 Info (信息) 中继续审计余下的问题。如果您碰到一个使您感到很困扰的问题,请打开您在第一次练习中检查的已完成的审计,并将您的结果和在那里标记的地方相比较。

深入讨论

1. 为了更好地理解在您审计期间发现的问题,用一个搜索引擎去研究 qwik-smtpd 中的已知漏洞。

将您的审计结果与公开揭露的漏洞进行比较。

答案本节包含了对在练习 2 (人工审计源代码)中列出的问题的答案。为了方便,我们再次列出了这些

问题。

1. 开始提问。

应用程序有多大?

该应用程序有一个源文件和两个头文件,总共大约 2300 行的文本组成。像这么小的应用程序现

实中已经很少存在了。

包含了哪些技术特性?

该程序是用 C 语言编写的。它希望能通过 inetd 或 xinetd 实现调用。

应用程序的基本设计是怎样的?

收到的至 25 号端口的请求会通过 inetd 或 xinetd 路由到程序,所以程序的标准输入来自网络。

程序读取它的配置文件,然后在 stdin 上关联它所找到的电子邮件。

谁是可能的攻击者?

由于应用程序可以用于网络,且 SMTP 协议经常被允许通过防火墙,因此任何在 internet 上的

人都可能攻击此应用程序。

攻击者想要达到什么目的?

从历史来看,攻击者利用了另一个 SMTP 服务器的漏洞,发送邮件,以获取到某个计算机的 root 访问。 Spammer 可能也会对这个程序感兴趣,如果他们可以把它当作一个“开放中继”来

使用的话。对于服务器来说,即使不知道发送者是谁,也愿意转发电子邮件。

开发人员如何保护应用程序?

README 文件中写到 “一旦完成,它就会很安全,作为 qmail,很有希望拥有相同的声誉。”但

当编写该代码时,没有证据显示安全代码实践非常有效。代码确实试图实现了一些 security features。例如,它既试图限制电子邮件继电器到达本地主机,也试图限制它到达配置文件中指

定的机器。

应用程序的什么地方会引起攻击者的注意?

有可能的被攻击大都是恶意的 SMTP 请求,但如果攻击者能够找到一种方法去操纵配置数

据,那么他们就可以实现多种攻击方式。

攻击者会使用什么类型的技术来破坏应用程序?

攻击者可能会尝试提交一个包含元字符或有异常长度,又或是畸形字段的 SMTP 请求。

Fortify Source Code Analysis 入门 55

Page 60: Fortify Source Code Analysis 入门 - paper.seebug.org fileFortify Source Code Analysis 入门 1 前言 本指南简要介绍了 Fortify Source Code Analysis 软件,并且提供了用于演示分析和审计源代码基本

成功的攻击会对公司造成什么样的风险?

如果攻击者控制了电子邮件服务器,那么公司可能至少会失去对电子邮件的访问。而攻击者将可以读取公司的电子邮件。如果一个 spammer 能够通过服务器发送消息,那么其他 ISP 将不再从

该公司接收电子邮件。可能更为重要的是,如果公司的客户发现该应用程序被攻击者所利用,他们可能会对公司的安全性失去信心。这会导致收入减少,并可能会使吸引新客户变得更加困难。

2. 回答下列问题:

执行 main() 的方式和时间?

main() 函数在数据包到达 25 号端口时执行。 Inetd 执行 qwik-smtp 并将网络数据传送到 stdin 上的 qwik-smtp。

对程序输入的哪一部分会被攻击者所控制?

攻击者已经完全控制了 SMTP 请求。他们可能会通过他们的邮件代理 (而不是他们自己的软

件)来发送恶意请求。

程序开发者是否假设过攻击者可能会违反程序规则?

开发者声明了许多不同大小的固定尺寸的堆栈缓冲区。一般来说,这是避免灾难的诀窍。

该代码容易受到攻击吗?

攻击者可以利用代码中的 buffer overflow 来强制服务器作为开放中继进行运行。通过发送如下

命令:

HELO AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA127.0.0.1

攻击者能欺骗程序,使它确信该消息来自本地机器 (http://lists.virus.org/securesoftware-04/msg00015.html)。

56 Fortify Source Code Analysis 入门