生成可靠且安全的 C++ 程序

美国政府出版物 NISTIR 8397:软件开发人员验证最低标准指南包含有关如何在任何编程语言中构建可靠安全的软件的优秀指南。

本文档遵循与 NISTIR 8397 相同的结构。 每个部分:

  • 总结了如何使用适用于 C++ 和其他语言的 Microsoft 开发人员产品来满足该部分的安全需求,以及
  • 提供了获取每个区域中最多值的指南。

2.1 威胁建模

摘要

威胁建模是一个有价值的过程,尤其是在以符合开发需求和降低噪音的方式应用时。

建议

威胁建模应是动态安全开发生命周期 (SDL) 的一部分。 建议针对整个产品、特定功能或重大设计或实现更改:

  • 拥有一个坚实、动态的 SDL,可提前与开发人员团队接触并实现方法的授权。
  • 以定向方式应用威胁建模。 将威胁建模应用于所有功能,但从战术上开始于公开、复杂或关键特征。 请定期应用它,作为自上而下产品评审的一部分。
  • 如果仍有机会更改设计,请尽早应用威胁建模(与所有安全要求一样)。 此外,威胁模型充当其他进程的输入,例如攻击面减少或设计安全性。 稍后创建的威胁模型顶多是笔测试(渗透测试)或需要安全测试的区域(例如模糊)的“调查”。 创建基线威胁模型后,计划随着攻击面的变化继续循环访问它。
  • 使用资产清单和符合性来适当跟踪构成产品的内容,以及跟踪安全项目(包括威胁模型)及其适用的资产。 此方法可更好地进行自动化风险评估,并将安全工作重点放在更改的特定组件或功能上。
  • 在 Azure 中,Microsoft Threat Modeling Tool 已在 2022 年更新,用于 Azure 开发。 有关详细信息,请参阅 Microsoft Threat Modeling Tool 概述 - Azure

支持因素和做法

为了正确应用威胁建模并避免过度使用,我们发现需要首先解决以下核心概念。

开发方法

首先,了解团队的开发方法。 对于使用敏捷开发工作流(每天将数十项更改推送到生产环境)的团队,每个功能更改都需要威胁模型更新是不可行的或不合理的。 相反,从编写功能的功能要求开始,请考虑包括安全要求问卷。 调查问卷应侧重于有关该功能的特定问题,以确定 SDL 的未来方面。 例如:

  • 关于如何在多租户环境中提供客户隔离,此功能是否在设计上做出了重大更改? 如果是这样,请考虑执行完整的威胁模型。
  • 新功能是否允许文件上传? 如果是这样,也许更合适的是 Web 应用程序安全评估。
  • 此更改主要是功能 UI 更改吗? 如果是这样,也许除了传统的自动化工具之外,不需要什么。

安全问卷结果告知开发单元与 SDL 技术对应的挂钩关系。 它还通知开发合作伙伴该功能的 SDL 时间线,以便他们可以在正确的时间进行协作。

产品库存

其次,维护你负责评估的产品的强大资产库存。 产品在复杂性方面正在增长。 通常为已连接的设备编写软件,这些设备具有:

  • 传感器(如客运铁路和车辆),
  • 与车辆中的其他组件通信的基于总线的网络(如 CANBUS 或 PROFIBUS),
  • 无线/手机/蓝牙,用于与客户设备和云后端通信,
  • 云中的机器学习回送回设备或机群管理应用程序,
  • 等等。

在此类复杂产品中,威胁建模至关重要。 使用强大的资产库存,可以查看整个产品堆栈,以查看完整图片,并查看需要评估的关键位置,以了解新功能或更改的功能如何影响产品安全性。

粒度和集成

建立系统,以使用明确的指标来衡量合规性。

  • 定期衡量功能级别开发的合规性。 功能合规性通常应以更高的频率和更小的粒度进行测量,有时甚至是在开发人员的系统或代码提交/合并时。
  • 定期评估使用功能或组件的更广泛产品的安全性。 更广泛的评估通常以较低的频率和更广泛的粒度完成,例如在模块或系统测试时间。

缩放

保留适当的资产清单系统,以捕获并保留安全项目以及威胁模型评审的输出。 使用明确的清单,可以评估模式的评审输出,并就如何定期优化产品安全计划做出智能决策。

尝试组合要求阶段安全问卷、威胁建模结果、安全评估结果和自动化工具的结果。 结合它们,你可以自动了解给定产品相对风险的观点,理想情况下是“仪表板”,以通知安全团队要专注于什么来充分利用威胁建模。

2.2 自动测试

摘要

自动测试是确保代码质量和安全的重要方法。 它们是支持本文档提及的其他区域(如威胁建模)中不可或缺的一部分。 与其他安全编码做法配对时,它们有助于防范代码库中引入的 bug 和漏洞。

密钥属性

测试应可靠、一致且隔离。 这些测试应尽可能多地涵盖代码。 所有新功能和 bug 修复都应具有相应的测试,以确保代码的长期安全性和可靠性(如果可能)。 定期在尽可能多的环境中运行自动测试,以确保其运行并涵盖所有方面:

  • 他们应首先在进行更改的计算机上运行。 运行测试最容易在 IDE 中完成,用于编辑,或者在开发人员进行更改时作为命令行上的脚本。
  • 下一个应运行的位置是作为拉取请求提交/合并过程的一部分。
  • 运行测试的最后一个位置是持续集成和持续部署 (CI/CD) 管道的一部分,或发布候选版本。

测试的范围应该在每一步都有所增加,最后一步全面覆盖了其他步骤可能遗漏的任何内容。

持续使用和维护

测试可靠性是维护测试套件有效性的重要组成部分。 应分配和调查测试失败,潜在安全问题具有较高的优先级,并在提示和预先确定的时间范围内更新。 忽略测试失败不应是一种常见做法,但应该需要强有力的理由和批准。 由于测试套件本身中存在的问题,测试失败应与其他故障相同,以防止产品问题丢失的覆盖范围失误。

各种测试,尤其是单元测试

有多种类型的自动测试,虽然并非所有应用程序都适用,但良好的测试套件包含多种不同类型的选择。 基于代码的测试用例(如单元测试)是最常见的和最不可或缺的,适用于所有应用程序,并有意覆盖尽可能多的代码路径,以便获得正确性。 这些测试应较小、快速且不会影响计算机的状态,以便可以快速、频繁地运行完整的测试套件。 如果可能,请在具有不同硬件设置的许多计算机上运行测试,以捕获在单种类型的计算机上无法重现的问题。

Visual Studio

Visual Studio 测试资源管理器原生支持许多最常用的 C++ 测试框架,并且可以选择为更多框架安装扩展。 这种灵活性有助于运行涵盖所处理代码的测试子集,并便于在测试失败出现时进行调试。 Visual Studio 还可以轻松地为现有项目设置新的测试套件,并提供有用的工具(如 CodeLens),以便更轻松地管理这些测试。 有关使用 Visual Studio 编写、运行和管理 C/C++ 测试的详细信息,请参阅针对 C/C++ 的写入单元测试 - Visual Studio (Windows)

在 Azure 和 GitHub CI/CD 中

执行更深入验证且运行时间更长的测试(例如静态分析、组件检测等)非常适合拉取请求测试或持续集成测试。 通过 Azure DevOps 和 GitHub Actions,可以轻松地自动运行验证,并在验证失败时阻止代码检查。 自动化强制措施有助于确保基于这些更严格的检查运行,确保签入的所有代码都安全。 此处介绍了 Azure Pipelines 和 Azure DevOps 生成验证:

2.3 基于代码或静态分析

摘要静态代码/二进制分析应默认启用,默认为安全。 静态分析分析在生成程序时分析所需的安全和安全策略,而不是在客户计算机上发生攻击时执行。 静态分析可以分析源代码表单或已编译的可执行表单中的程序。

建议Microsoft 建议:

  • 为所有 C++ 程序启用静态分析,同时针对输入源代码(编译前)和可执行二进制文件(编译后)。 “启用”可能意味着在开发人员计算机上每个生成期间运行分析,或者作为单独的生成来检查以后的代码或作为检查要求。
  • 将静态分析合并到 CI 管道中,作为一种测试形式。
  • 根据定义进行静态分析附带误报,并准备将该事实纳入质量反馈循环。 提前快速启用所有低误报警告。 然后,主动增加代码库编译警告清理的规则数,因为定期添加更多规则来标记重要 bug 的代价是逐渐提高误报(最初,在为这些规则清理代码库之前)。
  • 始终使用 Visual Studio 的最新支持版本,并设置工程环境,以便在最新修补程序版本可用后立即快速使用,而不会延迟到下一个开发阶段/周期。

关键工具请注意并使用以下内容:

注意:

  • /analyze 支持在编译时对 C++ 代码进行静态分析,以识别关键的安全性和可靠性代码漏洞。 应该在整个 C++ 程序的整个开发时间线中启用它。 首先,默认至少启用“Microsoft Native Recommended”作为最低基线。 然后,请查阅文档,了解如何根据工程策略的要求指定更多规则,尤其是 C++ Core Guidelines。 源代码静态分析功能可在 Visual C++ IDE 和命令行生成工具中使用。
  • 应尽可能启用 /W4/WX,以确保在较高警告级别(W4)上完全编译代码,并将警告视为必须修复的错误(WX)。 这些选项允许查找其他静态分析工具无法检查的非初始化数据错误,因为只有在编译器后端执行过程间分析和内联之后,这些错误才可见。
  • BinSkim 二进制分析可确保项目能够实现广泛的安全功能。 BinSkim 生成 PDB 和其他输出,以便更轻松地验证保管链并有效地响应安全问题。 Microsoft 建议运行 BinSkim 工具来分析程序生成或使用的所有可执行二进制文件(.sys.dll.exe)。 BinSkim 用户指南包含受支持的安全标准列表。 Microsoft 建议解决 BinSkim 工具报告为“错误”的所有问题。 应该有选择地评估报告为“警告”的问题,因为解决这些问题可能会影响性能,或者可能没有必要。

在 Azure 和 GitHub CI/CD 中,Microsoft 建议始终在发布 CI/CD 方案中启用源代码和二进制静态分析。 在本地开发人员的计算机上立即运行源分析,或者至少针对每个提交或拉取请求运行源分析,以尽早捕获源 bug 并最大程度地降低总体成本。 二进制级别 bug 往往引入得更慢,因此在不太频繁的预发行 CI/CD 方案中(例如夜间或每周生成)中运行二进制分析可能已经足够了。

2.4 查看硬编码机密

摘要

不要在软件中硬编码机密。 可以使用可扫描整个源代码库的可靠工具有效地查找和删除源代码中的机密。 找到机密后,请遵循安全存储和机密使用准则将其移动到安全位置。

问题

“机密”是指建立标识并提供对资源的访问权限或用于对敏感数据进行签名或加密的实体。 示例包括密码、存储密钥、连接字符串和私钥。 在软件产品中保留机密是诱人的,以便软件在需要时可以轻松获取它们。 但是,这些硬编码的机密可能会导致严重或灾难性的安全事件,因为它们很容易被发现,并可用于损害服务和数据。

防护

源代码中硬编码的机密(纯文本或加密 Blob)是安全漏洞。 下面是有关如何避免源代码中机密的一般准则:

  • 在提交源代码管理之前,使用预检查工具扫描和捕获代码中潜在的硬编码机密。
  • 不要在源代码或配置文件中放置明文凭据。
  • 请勿在 SharePoint、OneNote、文件共享等中存储明文凭据。 或者通过电子邮件、即时消息等共享它们。
  • 不要使用易于发现的解密密钥加密机密。 例如,不要将 PFX 文件与包含其密码的文件一起存储。
  • 不要使用弱解密加密机密。 例如,不要使用弱密码或通用密码加密 PFX 文件。
  • 避免在源代码中放置加密凭据。 请改用源中的占位符,让部署系统将其替换为已批准的存储中的机密。
  • 与在生产部署中一样,对测试、暂存等环境中的机密应用相同的原则。 攻击者通常以非生产系统为目标,因为它们管理得不太好,然后使用它们透视到生产环境。
  • 不要在部署之间共享机密(例如测试、暂存、生产)。

虽然与硬编码的机密不直接相关,但还要记得为测试、开发和生产保护机密:

  • 定期轮换机密,并且每当机密可能公开时,都进行轮换。 证明轮换/重新部署机密的能力是安全系统的证据。 更值得注意的是,缺乏此功能甚至更有力地证明了不可避免的漏洞。
  • 不要屈从于“我的测试凭据不会带来风险”的常见开发人员理由。在实践中,他们几乎总是这样做。
  • 请考虑完全优先使用 RBAC/身份驱动的解决方案作为可以完全回避机密管理错误的工程解决方案(例如密码、持有者密钥)。

检测

产品的旧组件可能包含其源代码中隐藏的硬编码机密。 有时,开发人员桌面计算机的机密可以爬进远程分支并合并到发布分支中,无意中泄露机密。 若要发现可能隐藏在源代码中的机密,可以使用可扫描代码中的硬编码机密的工具:

修正

在源代码中找到凭据时,迫切需要使公开的密钥失效,并根据暴露情况执行风险分析。 即使系统需要保持运行状态,也可以使用以下步骤启用机密管理器进行修正:

  1. 如果修正允许切换到托管标识,或者要求删除机密管理器(例如 Azure Key Vault (AKV)),请先执行此操作。 然后使用更新的标识或密钥重新部署。
  2. 使公开的机密失效。
  3. 对因泄露造成的潜在损害执行审核/风险评估。

若要保护云应用和服务使用的加密密钥和其他机密,请使用 Azure Key Vault 和适当的访问策略。

如果公开损害了某些客户数据/PII,则可能需要其他合规性/报告要求。

从源代码中删除现已失效的机密,并将其替换为不直接在源代码中公开机密的替代方法。 使用 Azure AD 等工具查找在可能的情况下消除机密的机会。 可以更新身份验证方法,通过 Azure Active Directory 利用托管标识。 仅使用批准的存储来存储和管理机密,例如 Azure Key Vault (AKV)。 有关详细信息,请参阅:

Azure DevOps (AzDO)

AzDO 用户可以通过 Azure DevOps 的 GitHub Advanced Security (GHAzDO) 扫描其代码。 GHAzDO 还允许用户通过在存储库上启用推送保护来防止机密泄露,从而在泄露之前捕获潜在风险。 有关如何在 Azure DevOps 中检测代码中的硬编码机密的详细信息,请参阅以下每个链接中 Azure DevOps 的 Github Advanced Security 机密扫描

在 GitHub 中

可通过两种形式在 GitHub.com 上使用机密扫描:

  • 合作伙伴的机密扫描警报。 在所有公共存储库上自动运行。 与机密扫描合作伙伴提供的模式匹配的任何字符串都将直接报告给相关合作伙伴。
  • 用户的机密扫描警报。 可以为使用 GitHub Enterprise Cloud 且具有 GitHub Advanced Security 许可证的组织拥有的存储库启用和配置额外的扫描。 这些工具还支持专用存储库和内部存储库。

GitHub 为可以配置为满足需求的合作伙伴和用户提供已知的机密模式。 有关详细信息,请参阅:

注意

适用于 Azure DevOps 的 GitHub Advanced Security 带来了适用于 GitHub 用户的相同机密扫描、依赖项扫描和 CodeQL 代码扫描解决方案,并将它们本机集成到 Azure DevOps 中,以保护 Azure Repos 和 Pipelines。

其他资源

2.5 使用语言和 OS 提供的检查和保护运行

摘要

二进制强化是通过应用编译时安全控制来完成的。 其中包括以下缓解措施:

  • 防止代码中可利用的漏洞,
  • 启用运行时检测,以触发漏洞利用的安全防御,以及
  • 启用数据生产和存档,以帮助限制安全事件造成的损害。

二进制使用者必须选择使用 Windows 安全功能,才能获得强化的全部优势。

Microsoft 提供了一组特定于 C++ 项目的设施,以帮助开发人员编写和交付更安全的代码。 C++ 开发人员还应遵守生成可执行代码的语言通用的安全标准。 Microsoft 维护 BinSkim,这是一个公共 OSS 二进制检查程序,可帮助强制使用本节中所述的许多保护。 有关 BinSkim 的详细信息,请参阅 Binskim 用户指南 | GitHub

二进制级控件因工程过程中应用的位置而异。 应区分编译器和链接器选项:严格编译时间、使用运行时开销更改代码生成,以及更改代码生成以实现与 OS 保护的兼容性。

开发人员设置应希望尽可能多地启用静态分析,使专用数据生产能够加速调试,等等。 发布版本应调整为安全、性能和其他代码生成问题的适当组合。 必须将发布过程配置为正确生成和管理公共生成数据与专用生成数据(例如,公共与专用符号)。

保持最新状态:始终使用最新的编译器和工具

使用当前工具集编译所有代码,以便受益于最新的语言支持、静态分析、代码生成和安全控制。 由于编译器会影响每个生成的组件,因此在工具更新上回归的可能性相对较高。 如果使用过时的编译器,在响应安全事件时会给纠正措施带来特定的风险,因为团队可能没有足够的时间来升级编译器。 Microsoft 建议团队开发工具来定期刷新和测试编译器更新。

使用安全开发方法、语言版本、框架/API

代码应利用开发方法、语言版本、框架、API 等,通过促进 C++ 中的安全性和简单性来最大程度地降低风险,包括:

使用安全依赖项

二进制文件不应链接到不安全的库和依赖项。 开发团队应跟踪所有外部依赖项,并通过更新到更安全的版本来跟踪这些组件中的所有外部依赖项,并解决这些组件中已识别的安全漏洞。

最大化代码证明保证和安全响应的效率

编译应启用强代码证明保证,以帮助检测和防止引入后门器和其他恶意代码。 对于所有软件版本而言,生成的数据(对调试和调查至关重要)应存档,以便在泄露时驱动高效的安全响应。 以下编译器开关生成对安全响应至关重要的信息:

  • /ZH:SHA_SHA256在 Visual C++ 中 - 确保使用加密安全算法生成所有 PDB 源文件哈希。
  • /Zi/ZI Visual C++ 中(调试信息格式) - 除了发布用于收集崩溃数据和其他公共使用方案的带状符号外,请确保为所有已发布的二进制文件生成和存档专用 PDB。 二进制分析工具需要完整符号来验证编译时是否启用了许多安全缓解措施。 专用符号在安全响应中至关重要,当工程师争先试时评估和限制损坏时,调试和调查成本更低。
  • /SOURCELINK 在 Visual C++ 链接器中 - 在 PDB 中包含 Sourcelink 文件:源链接是一种语言和源代码管理不可知的系统,为二进制文件提供源调试。 源调试极大地提高了预发布安全验证和发布后事件响应的范围的效率。

启用编译器错误以防止代码创作时出现问题

编译应启用与安全相关的编译器检查作为中断性错误,例如:

将二进制文件标记为与 OS 运行时安全缓解兼容

编译器和链接器设置应选择使用检测和缓解恶意代码执行的代码生成功能,包括:

防止敏感信息泄露

编译器设置应选择启用敏感信息发现防护。 近年来,研究人员发现了源自硬件功能(如推理执行)的意外信息泄漏。

在软件级别,如果意外泄露,机密数据可能会传输给攻击者。 未能零初始化缓冲区和其他缓冲区滥用可能会向调用受信任 API 的攻击者泄露专用机密数据。 通过启用额外的静态分析并使用安全资源容器(如前所述),可以最好地处理此类问题。

  • /Qspectre - 缓解推理执行侧通道攻击 - 插入屏障指令,以帮助防止推理执行生成的敏感数据泄露。 应为在内存中存储敏感数据并跨信任边界运行的代码启用这些缓解措施。 由于在性能关键块或循环中引入运行时检查的可能性,Microsoft 始终建议在启用 Spectre 缓解措施时根据适当的基准来衡量性能影响。 这些代码路径可以通过 spectre(nomitigation)declspec 修饰符禁用缓解措施。 启用 /Qspectre 的项目还应链接到也使用这些缓解措施编译的库,包括 Microsoft 运行时库。

2.6 黑盒测试用例

摘要

黑盒测试不依赖于知道测试组件的内部工作原理。 黑盒测试旨在测试产品中任何层或级别的功能的端到端功能。 黑盒测试可以是功能测试、UI 测试、性能测试和集成测试。 黑盒测试对于衡量一般可靠性和功能正确性具有价值,并确保产品按预期运行。

与其他部分的关系

这些类型的基于要求的测试可用于验证威胁模型中做出的假设,并涵盖在该部分中提出的潜在威胁。 这些测试可用于测试产品的各个组件之间的集成,尤其是跨信任边界的集成,如威胁模型中所述。 黑盒测试用例也可用于测试各种边缘用例,以便进行用户输入验证。 测试已知的边缘事例和错误事例都很有用。 模糊处理也可用于测试不太明显的事例。

自动化和回归

定期运行这些测试,并将结果与以前的运行进行比较,以捕获中断性变更或性能回归。 此外,在许多不同的计算机和安装设置上运行这些测试可帮助解决可能因不同体系结构或设置更改而导致的任何问题。

故障转储

这些测试有助于查找可靠性问题,能够测试许多可能遇到崩溃、挂起、死锁等问题的不同场景。 通过将故障转储作为测试失败的一部分进行收集,可以将转储直接导入 Visual Studio,以进一步调查代码中哪些部分遇到这些问题。 如果在 Visual Studio 中运行功能测试,则可以通过查看测试失败的黑匣子内的确切位置轻松复制和调试失败,并且可以快速测试修复。

若要开始调试测试,请参阅使用测试资源管理器调试单元测试 - Visual Studio (Windows)

在 Azure 中

Azure DevOps 还可以通过测试计划来帮助管理和验证这些测试。 这些测试可用于确保通过手动验证进行审批,并运行与产品要求关联的自动测试。 有关 Azure Test Plans 以及如何使用它们运行自动测试的详细信息,可在此处找到:

2.7 基于代码的测试用例

摘要

基于代码的测试用例是维护产品安全性和可靠性不可或缺的一部分。 这些测试应较小且快速,不应相互影响,这样它们可以并行运行。 只要开发人员更改代码,就可以在开发计算机上本地运行基于代码的测试,而无需担心其开发周期变慢。

类型以及与其他部分的关系

基于代码的测试用例的常见类型包括:

  • 单元测试,
  • 参数化测试以涵盖具有多个输入类型的函数,
  • 组件测试,使每个测试组件保持独立,并且
  • 模拟测试以验证与其他服务通信的代码部分,而无需扩展测试范围以包含这些服务本身。

这些测试基于编写的内部代码,而黑盒测试基于产品的外部功能要求。

目标

通过这些测试,目标是实现代码的高水平测试覆盖率。 应积极跟踪此覆盖范围以及存在差距的位置。 添加更多测试来练习更多代码路径时,代码的安全性和可靠性的整体信心将增加。

Visual Studio

通过 Visual Studio 中的测试资源管理器工具,可以轻松地频繁运行这些测试,并快速获取关于通过/失败率和故障位置的反馈。 许多测试框架还支持 CodeLens 功能,以便查看测试位置本身的测试状态,从而使添加和维护测试套件变得更轻松。 测试资源管理器还使管理这些测试变得简单,允许测试组、自定义测试播放列表、筛选、排序、搜索等。

有关详细信息,请参阅:

Visual Studio 还附带用于跟踪代码覆盖率的工具。 借助这些工具,可以确保现有测试涵盖所做代码更改,或添加新测试以涵盖新的和未测试的代码路径。 这些工具还显示代码覆盖率百分比,以确保它保持在目标级别之上,以确保对总体代码质量的信心。

有关这些工具的信息,请参阅代码覆盖率测试 - Visual Studio (Windows)

在 Azure 中

Azure DevOps 还有助于在生成管道过程中跟踪整个产品的代码覆盖率结果。 有关详细信息,请参阅查看代码覆盖率 - Azure Pipelines

2.8 历史测试用例

摘要

历史测试用例,也称为回归测试用例,防止旧问题再次浮出水面,并增加产品的整体测试覆盖率。 应确保修复 bug 时,项目还会添加相应的测试用例。 随着时间的推移,随着修复的进行,测试套件的整体稳定性将不断改进,从而更好地保证可靠性和安全性。

关键品质以及与其他部分的关系

由于这些测试是 bug 回归测试,因此应快速且易于运行,以便可以与基于代码的测试用例一起运行,并有助于产品的整体代码覆盖率。 此外,使用客户的真实示例来激励新的测试用例是提高测试覆盖率和质量的好方法。

Visual Studio

借助 Visual Studio,你可以在进行更改以修复 bug 的同时轻松地向套件添加测试,并快速运行测试和代码覆盖率,以确保考虑所有新情况。 在编写测试的代码中引用问题跟踪系统中的 bug ID 是将回归测试连接到相应问题的好方法。 偏向于将 Azure Boards 和测试计划与 Visual Studio 配合使用:

  • 关联测试、测试用例和问题;以及
  • 跟踪问题及其相应测试的各个方面。

有关详细信息,请参阅:

最终,将这些测试集成到本应涵盖代码部分的单元测试区域有助于使测试套件保持有序且更易于管理。 可以使用测试资源管理器的测试分组来有效跟踪属于一起的测试。 有关详细信息,请参阅使用测试资源管理器运行单元测试 - Visual Studio (Windows)

2.9 模糊

摘要模糊(也称为模糊测试)是一种自动化软件测试技术,涉及提供无效、意外或随机数据作为程序输入。 然后,程序会监视异常,例如崩溃、内置故障或编译器注入的代码断言和潜在的内存泄漏。

指南

对所有可能处理攻击者可以控制的不受信任的输入的软件使用模糊处理。 如果要生成新应用程序及其关联的测试套件,请尽早为关键模块添加模糊。 首次在一个软件上运行模糊,几乎总是会发现以前未知的实际漏洞。 一旦你开始模糊,永远不要停止。

与其他部分的关系

模糊报告失败时,它总是自然地提供可重现的测试用例来演示该 bug。 可以重现、解析此测试用例,然后将其添加到历史测试用例。

使用两种消毒器(例如地址净化器 (ASan))和模糊处理时:

  • 首先运行启用了消毒器的正常测试,以查看是否存在问题,然后,一旦代码为清理器清理开始模糊。
  • 对于 C 或 C++,有编译器可以自动注入运行时断言和启用 ASan 的元数据。 为 ASan 编译时,生成的二进制文件链接与运行时库链接,该库可以精确诊断 15 个以上的内存安全错误类别,且没有误报。 对于具有源的 C 或 C++,请使用 LibFuzzer,这要求首先启用 ASan。
  • 对于用 Java、C#、Python、Rust 等编写的库,请使用 AFL++ 框架

关键品质

  • 模糊查找静态程序分析、详尽的功能测试和手动代码检查通常错过的漏洞。
  • 模糊是查找软件中的安全性和可靠性 bug 的有效方法,因此,Microsoft 安全开发生命周期需要对每个产品的每个不受信任的接口进行模糊处理(另请参阅威胁建模)。
  • 始终对可能处理不受信任的输入的软件使用模糊处理。
  • 模糊对于具有大型数据分析器的独立应用程序有效。

Azure 和 GitHub CI/CD

修改内部版本以支持使用 LibFuzzer 或 AFL++ 的可执行文件的持续创建。 可以在 OSS-Fuzz 或 OneFuzz 等服务中添加模糊处理所需的额外计算资源。

2.10 Web 应用程序扫描

摘要

在 Windows 上的 Microsoft Visual C++ 范围内,Microsoft 建议:

  • 首选适用于 Web 应用程序的 TypeScript、JavaScript 和 ASP.NET。
  • 不要使用 C++ 编写 Web 扩展。 Microsoft 已弃用 ActiveX。
  • 将代码编译为 Emscripten/WASM 时,不再应用 C++ 和其他工具。
  • Microsoft 提供 RESTler,这是一个有状态 REST API 模糊处理

概述和关键品质

Web 应用程序扫描程序通过其网页进行爬网来浏览 Web 应用程序,并检查其是否存在安全漏洞。 此爬网涉及自动生成恶意输入和评估应用程序的响应。 关键是,Web 应用程序扫描必须涵盖/支持:

  • 将网络中的所有 Web 应用(包括新 Web 应用和未知应用)编录到数千个。
  • 深入扫描移动设备使用的软件版本、SOAP、REST API 服务和 API。
  • 在 DevOps 环境中将安全基元插入到应用程序开发和部署中。 这些基元适用于爬网程序。
  • 恶意软件检测。

2.11 检查包含的软件组件

摘要

处理 C++ 代码与其他编程语言编写的代码相同,并将公司采用的任何软件组合分析 (SCA) 和源分析 (OA) 工具应用于 C++ 代码。 工作流和安全扫描应设计为 CI/CD(持续集成和持续交付)系统的一部分。

上游防御

为了缓解对上游依赖项的攻击风险,应将第三方源/组件存储在企业控制的资产中,以便对其运行 SCA 和 OA 工具。

  • 识别漏洞(包括公共数据库)时,工具应扫描并发出警报,例如:主页 | CVE
  • 对应用程序/存储库中包含的所有软件组件运行静态分析,以识别易受攻击的代码模式。

依赖项防御

执行和维护依赖项审核,以验证 SCA 和 OA 工具是否考虑并涵盖所有此类事件。

  • 组件应定期审核并更新到最新的已验证版本。
  • 包源依赖项。
  • SCA/OA 工具涵盖和审核来自单个源的所有包依赖项。

SBOM

生成 SBOM(软件材料清单),其中列出了所有依赖项,例如:

  • 源(例如 URL(统一资源定位符))
  • 版本
  • 一致性(例如 SHA-256 源哈希)和其他验证一致性的方法,例如确定性生成。
  • 要求和审核软件依赖项中的 SBOM 文件,或作为生成(包括 OSS(开源软件))的一部分生成的。
  • Microsoft 正在标准化并推荐 SPDX(软件包数据交换)2.2 或更高版本 | Linux Foundation作为 SBOM 文档格式。
  • 生成确定性可用于独立生成位相同的二进制文件,并提供完整性的独立验证:
    • 第一方或第三方可重现性证明
    • 其他技术(如通过受信任的证书源进行二进制签名)也可以提供二进制完整性的一些保证。

其他资源

Microsoft 解决方案包括以下指南和产品: