安全简报

向 Microsoft Team Foundation Server 2010 中添加安全错误评级

Bryan Sullivan

软件开发团队在其产品生命周期过程中面临的一项最有争议的任务就是会审错误。对于产品开发中涉及的每个人来说,确定任何给定错误的相对重要性级别(进而确定该错误在发布之前无法及时修复的可能性)都是一件严肃的事情。

编程人员、测试人员、架构师和项目经理都有不同观点,并且其各自的会审决策以下面一些分散的因素为基础:

  • 修复后,有多少代码必须进行回归测试。
  • 距离发布项目有多长时间。
  • 多少用户会受到更改的影响。
  • 错误是否阻止了其他问题的测试或修复。

我承认,在会审产品功能中的功能错误时,这些都是重要的考虑因素。不过,在确定是否修复安全错误(也就是可能导致产品中出现安全漏洞的错误)时,这些不应作为考虑因素。安全错误的分类必须客观一致。对于一名攻击者来说,您是否是在代码完成里程碑的前一周发现的漏洞无关紧要,因为攻击者会同样地利用这个漏洞。

本专栏介绍由 Microsoft 内部产品和在线服务团队使用的客观安全错误分类系统(“错误评级”),这是安全开发生命周期 (SDL) 所需要的。本文还介绍您如何可将此分类系统纳入自己的使用 Microsoft Team Foundation Server 2010 的开发环境中。

DREAD

在我讨论 Microsoft 内部现在存在的错误评级之前,有必要介绍一下 Microsoft 早期的安全错误分类举措:DREAD。DREAD 是一个助记手段,代表:

  • 潜在破坏性
  • 可再现性
  • 可利用性
  • 受影响的用户
  • 可发现性

记录新安全错误的任何人都将为每个 DREAD 参数分配一个从 1 到 10 的值,10 表示程度最严重,1 表示程度最不严重。然后对这些值取平均值形成一个总体 DREAD 评级。例如,假设一位名叫 Doug 的开发人员在其团队的新 Web 应用程序管理门户页发现了一个 SQL 盲注攻击漏洞。Doug 可能会如图 1 所示对该漏洞进行分类。

图 1 一位开发人员的安全漏洞分类

DREAD 参数 评级 基本原理
潜在破坏性 5 攻击者可以读取和更改产品数据库中的数据。
可再现性 10 每次都可再现。
可利用性 2 需要专业知识和大量的时间投入。
受影响的用户 1 仅影响一小部分用户群。
可发现性 1 所有用户页面都无法链接到受影响页面。
总计评分 3.8  

 

图 1 所示的分类看似颇为简单、有效。但是考虑一下,Doug 的测试人员同事 Tina 可能会以一种完全不同的方式看待同一漏洞,如图 2 所示。

图 2 一位测试人员对同一错误的分类

DREAD 参数 评级 基本原理
潜在破坏性 10 攻击者可以读取和更改产品数据库中的数据。
可再现性 10 每次都可再现。
可利用性 10 通过使用 Internet 上找到的自动化工具可轻松利用。
受影响的用户 10 影响关键的管理用户。
可发现性 10 攻击者可轻松猜出受影响页面“admin.aspx”。
总计评分 10.0  

 

由于 Tina 知道有工具可自动进行 SQL 盲注攻击,因此将“可利用性”评级为 10,而 Doug 将其视为困难的手动攻击,因此将“可利用性”评级为 2。Doug 将“受影响的用户”评级为 1,因为只影响一小部分系统用户,但 Tina 将其评级为 10,因为受影响的用户具有管理权限。可能最令人关注的参数就是“潜在破坏性”:Doug 和 Tina 给出的基本原理完全相同,但评分值却大不相同!

此时,我们要问的问题不是“哪个团队成员的 DREAD 评级更好?”,而是“我们怎么能依赖于一个产生这样主观、可变结果的系统?”。如果 Tina 第一个发现该错误,则在发布前确实可以修复该错误,但如果 Doug 第一个发现,则很可能会将其延误,导致应用程序带着该漏洞发布。SDL 团队得出我们不能依赖这此类系统的结论,因此 Microsoft 开发了一个更加一致的方法:安全错误评级。

Microsoft 安全错误评级

Microsoft 安全错误评级基于漏洞的影响对其进行分类。记录错误的人员首先会给错误分配一个来自 STRIDE 值列表的安全影响值。STRIDE 是另一个助记手段,在本示例中用于对威胁进行分类。与 DREAD 不同,STRIDE 仍被 SDL 经常使用,并且是多个 SDL 工具的核心组件(包括 SDL 威胁建模工具)。STRIDE 值为:

  • 假冒
  • 篡改
  • 否认
  • 信息泄露
  • 拒绝服务 (DoS)
  • 特权提升 (EoP)

不过,仅靠较大的 STRIDE 威胁类别不足以对一个错误进行分类和会审。在大多数情况下,我们需要知道该错误是影响客户端代码还是服务器端代码。例如,我们不会将涉及一个目标用户的拒绝服务攻击与涉及整个服务器的拒绝服务攻击视为具有相同的严重性。我们还需要知道该错误的一些特定范围信息,具体取决于 STRIDE 和客户端/服务器分类。

继续以拒绝服务漏洞为例,我们需要知道谁可以执行攻击(例如,什么权限级别)以及影响将持续多久。匿名用户可利用的漏洞比只有通过身份验证的用户方可利用的漏洞要糟糕,将受影响服务器锁定以致只能进行物理重新启动的漏洞比仅造成服务器在几秒时间内不能访问的漏洞要糟糕。

借助主要 STRIDE 分类和一些附加范围特性,会审错误的人员现在可以使用此信息来查找该错误在错误评级上的严重程度。图 3 显示了一个已在安全开发生命周期过程指南文档 4.1a 版中发布的示例安全错误评级。此错误评级定义了四种级别的安全性:关键、重要、一般和低。

图 3 示例安全错误评级

STRIDE 值 客户端/
服务器
范围 严重程度
假冒 客户端 攻击者能够提供一个不同的 UI,但该 UI 与用户在默认/常见方案中必须依赖其做出有效信任决策的 UI 在外观上相同。信任决策定义为任何时候用户在采取操作时相信某些信息是由特定实体(系统或某个特定的本地或远程源)提供的。 重要
    攻击者能够提供一个不同的 UI,但该 UI 与用户在特定方案中习惯于信任的 UI 在外观上相同。“习惯于信任”定义为用户通常根据与操作系统或应用程序的正常互动而熟悉、但通常不将其视为“信任决策”的任何内容。 一般
    攻击者能够提供一个不同的 UI,但该 UI 与属于较大攻击方案的一部分的 UI 在外观上相同。
  服务器 连接到服务器的计算机能够使用设计为提供强身份验证的协议伪装成攻击者选择的其他用户或计算机。 重要
    客户端用户或计算机能够使用设计为提供强身份验证的协议伪装成其他随机的用户或计算机。 一般
篡改/ 否认 客户端 永久修改在常见或默认方案中做出信任决策时所用的任何用户数据或数据,所做修改在重新启动操作系统/应用程序后继续保持。 重要
    临时修改任何数据,所做修改在重新启动操作系统/应用程序后不会继续保持。
  服务器 永久修改在常见或默认方案中做出信任决策时所用的任何用户数据或数据,所做修改在重新启动操作系统/应用程序后继续保持。 重要
    永久修改在特定方案中做出信任决策时所用的任何用户数据或数据,所做修改在重新启动操作系统/应用程序后继续保持。 一般
    临时修改常见或默认方案中的数据,所做修改在重新启动操作系统/应用程序后不会继续保持。 一般
    临时修改特定方案中的数据,所做修改在重新启动操作系统/应用程序后不会继续保持。
信息 泄露 客户端 攻击者可以找到并读取系统上信息(包括不打算或未设计进行公开的系统信息)。 重要
    攻击者可以从系统上的已知位置读取信息(包括不打算或未设计进行公开的系统信息)。 一般
    任何无目标的信息泄露(即随机泄露数据)。
  服务器 攻击者可以从系统上的任何位置找到并读取信息(包括不打算或未设计进行公开的系统信息)。 重要
    攻击者可以从系统上的已知位置轻松读取信息(包括不打算或未设计进行公开的系统信息)。 一般
    任何无目标的信息泄露(例如,随机泄露数据),包括运行时数据。
拒绝服务 客户端 “系统损坏 DoS”:需要重新安装系统和/或组件。 重要
    “永久 DoS”:需要冷重启或导致蓝屏/错误检查。 一般
    “临时 DoS”:需要重新启动应用程序。
  服务器 匿名,必须“容易利用”(通过发送少量数据)或通过其他方式快速引发。 重要
    不在默认/常见安装中扩大的匿名、临时 DoS。 一般
    通过身份验证的永久 DoS。 一般
    通过身份验证的临时 DoS,在默认/常见安装中扩大。 一般
提升权限 客户端 远程用户,能够执行任意代码或获得比预期更多的权限。 关键
    远程用户,通过大量的用户操作执行任意代码。 重要
    本地的低权限用户可以将自己的权限提升为其他用户、管理员或本地系统。 重要
  服务器 远程匿名用户,能够执行任意代码或获得比预期更多的权限。 关键
    通过身份验证的远程用户,能够执行任意代码或获得比预期更多的权限。 重要
    通过身份验证的本地用户,能够执行任意代码或获得比预期更多的权限。 重要

 

请注意,为了使此系统能够正常工作,使用的错误跟踪数据库必须有一个针对 STRIDE 安全影响的字段。这样,就可以轻松区分安全错误与功能错误,并确定正确的错误评级分类。跟踪错误的安全影响是如此重要,以至于实际上有一个单独的 SDL 要求来做这项工作。幸好,在大多数情况下,这都非常容易。如果您使用的是 Team Foundation Server (TFS),下一节将向您说明如何将安全影响字段和错误评级添加到团队项目中的 Bug 工作项目。

向 Team Foundation Server 中添加错误评级功能

要将错误评级添加到 TFS 团队项目,您需要对创建项目所依据的底层过程模板进行更改。对于本文来说,我们假设项目是根据 TFS 2010 beta 2 附带的 MSF-Agile for Software Development 5.0 版 (beta) 模板创建的。不过,如果您主要使用其他过程模板(如 MSF for CMMI Process Improvement 模板)或任何自定义第三方模板,用于编辑这些模板的方法将相同。

首先为要在其上工作的 TFS 2010 服务器打开过程模板管理器。可通过以下方法执行此操作:在团队资源管理器窗口中打开该服务器的上下文菜单,然后导航至“团队项目集合设置”|“过程模板管理器”,如图 4 所示。


图 4 适用于 TFS 2010 服务器的过程模板管理器

在过程模板管理器中,选择 MSF for Agile Software Development v5.0,然后单击“下载”按钮将该模板的源文件下载到本地。将它们保存到您自选的文件夹中。

下载完成后,关闭过程模板管理器。我们希望将错误评级添加到 Bug 工作项目类型,因此,打开保存刚才下载的 MSF-Agile 模板的文件夹,然后在所选 XML 编辑器中打开文件 \WorkItem Tracking\TypeDefinitions\Bug.xml。

第一个任务是为安全影响、安全影响范围和错误评级严重程度添加相应的字段。(用于错误评级严重程度的字段应有别于固有的 Severity 字段,稍后我将解释原因。)在 witd:WITD/WORKITEMTYPE/FIELDS 元素下,添加图 5 所示的 XML 块。

图 5 为安全影响、安全影响范围和错误评级严重程度添加相应的字段

<FIELD
reportable="dimension"
type="String"
name="Effect"
refname="MSDN.SDL.Security.Effect">
<HELPTEXT>The effect of the security bug</HELPTEXT>
</FIELD>
<FIELD
reportable="dimension"
type="String"
name="EffectScope"
refname="MSDN.SDL.Security.Effect.Scope">
<HELPTEXT>The scope of the effect of the security bug. This value is used to determine the default bug bar severity</HELPTEXT>
</FIELD>
<FIELD
reportable="dimension"
type="String"
name="BugBarSeverity"
refname="MSDN.SDL.Security.Severity.BugBar">
<HELPTEXT>The suggested severity of the bug as determined by the security bug bar</HELPTEXT>
</FIELD>

此代码定义了三个新字段(包括其名称、类型和帮助文本),但仍未实现逻辑。通过添加锁定该字段可能值的允许值约束,开始添加逻辑。

对于 Effect,允许值为每个 STRIDE 值:“Spoofing”、“Tampering”、“Repudiation”、“Information Disclosure”、“Denial of Service”和“Elevation of Privilege”。对于自身没有漏洞但可借此机会减少以后的潜在漏洞的情况,最好将“Attack Surface Reduction”也添加为允许值。最后,对于错误只是普通的功能错误而没有安全影响的情况,将“Not a Security Bug”添加为允许值(请参见图 6)。

图 6 添加 Effect 的允许值

<FIELD
reportable="dimension"
type="String"
name="Effect"
refname="MSDN.SDL.Security.Effect">
<HELPTEXT>The effect of the security bug</HELPTEXT>
<ALLOWEDVALUES>
<LISTITEM value="Not a Security Bug" />
<LISTITEM value="Spoofing" />
<LISTITEM value="Tampering" />
<LISTITEM value="Repudiation" />
<LISTITEM value="Information Disclosure" />
<LISTITEM value="Denial of Service" />
<LISTITEM value="Elevation of Privilege" />
<LISTITEM value="Attack Surface Reduction" />
</ALLOWEDVALUES>
<DEFAULT from="value" value="Not a Security Bug" />
</FIELD>

对于 EffectScope,汇总错误评级中每个可能的范围项目,并将这些汇总添加为 EffectScope 字段的允许值(请参见图 7)。

图 7 添加 EffectScope 的允许值

<FIELD
reportable="dimension"
type="String"
name="EffectScope"
refname="MSDN.SDL.Security.Effect.Scope">
<HELPTEXT>The scope of the effect of the security bug. This value is used to determine the default bug bar severity</HELPTEXT>
<ALLOWEDVALUES>
<LISTITEM value="Not Applicable" />
<LISTITEM value="Client - Spoofed trusted UI in common/default scenario" />
<LISTITEM value="Client - Spoofed trusted UI in specific other scenario" />
<LISTITEM value="Client - Spoofed UI as part of a larger attack scenario" />
<LISTITEM value="Server - Spoofed specific user or computer over secure protocol" />
<LISTITEM value="Server - Spoofed random user or computer over secure protocol" />
<LISTITEM value="Client - Tampered trusted data that persists after restart" />
<LISTITEM value="Client - Tampered data that does not persist after restart" />
<!-- additional allowed values omitted for brevity -->
</ALLOWEDVALUES>
<DEFAULT from="value" value="Not Applicable" />
</FIELD>

我们还希望根据 Effect 的当前值进一步限制 EffectScope 的允许值。如果 Effect 当前设置为 Spoofing,则仅假冒相关的 EffectScope 值应该有效。如果 Effect 设置为 Tampering,则仅篡改相关的 EffectScope 值应该有效,依此类推。我们可通过将 WHEN 子句元素添加到 FIELD 定义中来实现这个目的(请参见图 8)。

图 8 添加 WHEN 子句以限制 EffectScope 的允许值

<FIELD
reportable="dimension"
type="String"
name="EffectScope"
refname="MSDN.SDL.Security.Effect.Scope">
<HELPTEXT>The scope of the effect of the security bug. This value is used to determine the default bug bar severity</HELPTEXT>
<ALLOWEDVALUES>
<!-- omitted for brevity -->
</ALLOWEDVALUES>
<DEFAULT from="value" value="Not Applicable" />
<WHEN field="MSDN.SDL.Security.Effect" value="Not a Security Bug">
<ALLOWEDVALUES>
<LISTITEM value="Not Applicable" />
</ALLOWEDVALUES>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect" value="Attack Surface Reduction">
<ALLOWEDVALUES>
<LISTITEM value="Not Applicable" />
</ALLOWEDVALUES>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect" value="Spoofing">
<ALLOWEDVALUES>
<LISTITEM value="Client - Spoofed trusted UI in common/default scenario" />
<LISTITEM value="Client - Spoofed trusted UI in specific other scenario" />
<LISTITEM value="Client - Spoofed UI as part of a larger attack scenario" />
<LISTITEM value="Server - Spoofed specific user or computer over secure protocol" />
<LISTITEM value="Server - Spoofed random user or computer over secure protocol" />
<LISTITEM value="Not Applicable" />
</ALLOWEDVALUES>
</WHEN>

<!-- Additional WHEN elements for the other STRIDE values omitted for brevity -->

</FIELD>

现在来为 BugBarSeverity 字段实现允许值逻辑。BugBarSeverity 的逻辑与 Effect 逻辑略有不同,表现在我们不希望用户能够直接设置 BugBarSeverity 字段的值。实现此类错误评级的关键之处在于严重程度应反映漏洞的特性。如果用户可以自行将严重程度设置为任何值,这将完全违背初衷。

我们不创建 BugBarSeverity 允许值列表,而是使用 WHEN 字段根据 Effect 的当前值将相应的值复制到 BugBarSeverity 字段中(由我们之前定义的错误评级确定)。例如,错误评级指定应将常见或默认方案中的假冒信任 UI 视为“重要”错误,因此当 Effect 为“Client – Spoofed trusted UI in common/default scenario”时,我们将“2 – Important”复制到 BugBarSeverity 中(请参见图 9)。

图 9 实现 BugBarSeverity 字段的值逻辑

<FIELD
reportable="dimension"
type="String"
name="BugBarSeverity"
refname="MSDN.SDL.Security.Severity.BugBar">
<HELPTEXT>The suggested severity of the bug as determined by the security bug bar</HELPTEXT>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Not Applicable">
<COPY from="value" value="4 - Low"/>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Client - Spoofed trusted UI in common/default scenario">
<COPY from="value" value="2 - Important"/>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Client - Spoofed trusted UI in specific other scenario">
<COPY from="value" value="3 - Moderate"/>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Client - Spoofed UI as part of a larger attack scenario">
<COPY from="value" value="4 - Low"/>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Server - Spoofed specific user or computer over secure protocol">
<COPY from="value" value="2 - Important"/>
</WHEN>
<WHEN field="MSDN.SDL.Security.Effect.Scope" value="Server - Spoofed random user or computer over secure protocol">
<COPY from="value" value="3 - Moderate"/>
</WHEN>

<!-- additional WHEN clauses omitted for brevity -->

</FIELD>

您可能会奇怪,为什么我在值上添加了数字前缀如“1 – Critical”和“2 – Important”,而不是只将其定义为“Critical”和“Important”。答案是 TFS 会自动按字母顺序排列允许值列表,因此在没有数字前缀的情况下,这些选项将无序显示,从而可能让用户迷惑。

此外,固有 MSF-Agile Severity 字段 (Microsoft.VSTS.Common.Severity) 的值应用了相同的数字前缀,因此将前缀添加到 BugBarSeverity 字段可强调这两个字段之间有关系的事实。

谈到 Severity 和 BugBarSeverity 之间的关系,是时候在模板中强制实施该关系了。此过程中的下一步是限制 Severity 字段的值,以使其严重程度与 BugBarSeverity 字段至少相同。如果团队有特定的业务原因要让实际严重程度比错误评级确定的值更高,也没有关系 — 我们只是不希望出现相反的情况。

为此,我们基于 Effect 字段的值使用用来限制 EffectScope 字段的相同 ALLOWEDVALUES 方法(请参见图 10)。

图 10 限制 Severity 字段的允许值

<FIELD
name="Severity"
refname="Microsoft.VSTS.Common.Severity"
type="String"
reportable="dimension">
<HELPTEXT>Assessment of the effect of the bug on the project</HELPTEXT>
<ALLOWEDVALUES expanditems="true">
<LISTITEM value="1 - Critical"/>
<LISTITEM value="2 - High"/>
<LISTITEM value="3 - Medium"/>
<LISTITEM value="4 - Low"/>
</ALLOWEDVALUES>
<DEFAULT from="value "value="3 - Medium" />

<WHEN field="MSDN.SDL.Security.Severity.BugBar"value="1 - Critical">
<ALLOWEDVALUES expanditems="true">
<LISTITEM value="1 - Critical"/>
</ALLOWEDVALUES>
</WHEN>
<WHEN field="MSDN.SDL.Security.Severity.BugBar" value="2 - Important">
<ALLOWEDVALUES expanditems="true">
<LISTITEM value="1 - Critical"/>
<LISTITEM value="2 - High"/>
</ALLOWEDVALUES>
</WHEN>
<WHEN field="MSDN.SDL.Security.Severity.BugBar" value="3 - Moderate">
<ALLOWEDVALUES expanditems="true">
<LISTITEM value="1 - Critical"/>
<LISTITEM value="2 - High"/>
<LISTITEM value="3 - Medium"/>
</ALLOWEDVALUES>
</WHEN>
</FIELD>

您需要对 Bug 工作项目做最后一项更改:您需要为我们已添加的新字段添加 UI 控件,如以下代码段中所示。在此文档的 witd:WITD/WORKITEMTYPE/FORM/Layout 部分定义了工作项目控件。由您决定新字段的位置,但我建议将新的“Security”选项卡添加到主要 TabGroup 上,并在该处添加以下字段:

<Tab Label="Security">
<Control Field Name="MSDN.SDL.Security.Effect" Type="FieldControl" Label="Effect "LabelPosition="Top" />
<Control Field Name="MSDN.SDL.Security.Effect.Scope" Type="FieldControl" Label="Scope" LabelPosition="Top" />
<Control Field Name="MSDN.SDL.Security.Severity.BugBar" Type="FieldControl" Label="Bug Bar Rating" ReadOnly="True" LabelPosition="Top" />
</Tab>

现在您已完成编辑 Bug 工作项定义的工作。不过,必须将修改的过程模板定义导回到 Team Foundation Server,才能使用新的错误评级功能。完成此操作有两种方法。可以将现有 MSF-Agile for Software Development 模板替换为新模板,也可以添加新模板与旧版本模板并存。

如果选择替换现有模板,请打开过程模板管理器,选择 MSF-Agile for Software Development 模板,然后单击“删除”按钮。请注意,该操作不可逆。如果不重新安装 Team Foundation Server,将无法重新获得原始模板。删除现有 MSF-Agile 模板后,单击“上载”按钮,然后选择包含已编辑过程模板的文件夹。该模板将与以前一样在列表中显示为“MSF-Agile for Software Development”,但此后根据此模板创建的任何项目都将具有错误评级功能。

如果选择添加新模板与现有 MSF-Agile 模板并存而不是将其替换,则需要更改新模板的名称,以便它与现有模板无冲突。为此,需要多进行一次文件编辑。在选择的 XML 编辑器中,编辑 ProcessTemplate.xml 文件,该文件可以在最初将模板下载到的文件夹中找到。将 ProcessTemplate/metadata/name 元素的值更改为“MSF for Agile Software Development plus Bug Bar”之类的内容,保存文件,然后退出。打开过程模板管理器,单击“上载”按钮,选择包含已编辑模板的文件夹。新模板在列表中显示的名称将为给定的名称,此后根据此模板创建的任何项目都将包含错误评级。

使用错误评级确定退出条件

当然,如果没有组织策略的支持,世界上的任何过程模板功能都不会对您有帮助。Microsoft 内部开发团队的标准是:在错误评级“低”类别之上的任何安全错误都必须在发布之前得到修复。此标准从未放松过,不管距离产品发布时间有多近。此方法完全依据错误的可能影响和范围,因此可保证安全错误会审的客观性。

这就是为什么我们定义一个单独的 BugBarSeverity 字段,而不是仅基于 EffectScope 限制通用 Severity 字段的值的原因。从严格的安全角度来看,我们不关心产品是否附带任何严重程度为“关键”错误,只要这些错误没有安全影响即可。我们真正关心的是该错误的 BugBarSeverity 是否高于“4 – Low”。如果是这样,该错误必须在发布之前得到修复。

倡议

如果没有客观一致的过程来会审安全错误,您将无法创建安全的应用程序。使用 Microsoft 安全错误评级是实现此目标的一个绝佳方式,并且它是安全开发生命周期的关键组件,已证实能够减少软件中的漏洞。

此外,如果使用的是 Microsoft Team Foundation Server,您可以轻松将错误评级功能添加到团队项目。即使开发人员不一定是安全专家,这也可使您的团队更加轻松地对安全错误进行相应分类。

最后,我建议您下载适用于 Visual Studio 2010 的 MSF-Agile + SDL 过程模板。此过程模板在发布 Visual Studio 2010 之后不久即在 microsoft.com/sdl 免费提供。它包含了本文中介绍的错误评级,以及其他很多旨在帮助您创建更安全软件的功能。                                                                  

Bryan Sullivan 是 Microsoft 安全开发生命周期团队的一名安全项目经理,专门负责 Web 应用程序和 .NET 的安全问题。他是“Ajax Security”(Addison-Wesley,2007)一书的作者。

衷心感谢以下技术专家对本文的审阅:Brian Harry