源头安全与设计安全:保障软件安全的积极策略,减少被动响应
ZDNET核心观点安全软件的打造需在编码前就开始。威胁建模有助于团队尽早发现有风险的假设依赖管理能预防隐藏的供应链风险。软件有其生命周期从创意萌生到编码、测试、部署、客户使用再到最终修订或停用每一行代码、每个模块和组件都会在整体解决方案中变得更加根深蒂固。因此一旦后期出现问题修复起来会非常困难。然而我们往往仅根据后期的使用情况来修复软件。本文将探讨在部署前预防软件缺陷进入生产阶段的积极策略。有两个关键术语与这种方法相关“源头安全”secure - at - the - source和“设计安全”secure - by - design。这两个术语都指的是在软件生命周期的最早阶段将安全性和可靠性融入代码的过程。我们将重点关注如何在从需求和设计到编码、依赖选择、构建管道、部署和维护的所有阶段中融入安全设计。预防从编码前开始编码总是始于对预期结果的设想。这一过程会引发设计阶段在此阶段设计师和编码人员有时是同一人或同一批人会规划如何进行编码。正是在编写第一行代码之前漏洞开始显现。这种情况的出现是因为设计决策会影响实现。在进行设计时要仔细考虑以下因素信任边界用户、服务、网络或系统之间定义不明确的边界可能意味着一个受攻击的区域会影响本应隔离的应用部分。身份验证如果系统不能可靠地识别发出请求的对象那么后续的所有安全决策都将受到质疑。授权如果架构不能始终如一地执行每个用户或服务被允许执行的操作攻击者可能会获得他们不应有的操作或数据访问权限。数据暴露如果敏感数据流经过过多的系统、日志、API或客户端组件就更容易发生数据泄露或滥用。日志记录如果日志记录缺失、过多或设计不当团队可能会错过攻击或者意外地将敏感信息存储在不应该存储的地方。故障模式如果系统在数据处于开放状态时发生故障在出错时泄露细节或者在压力下表现出不可预测的行为停电和攻击可能会演变成安全事件。我们都听过“可能会出什么问题呢”这句话通常是在提出某个大胆且可能不明智的计划后说的。但如果你认真地思考这个问题就可以开始对软件进行威胁建模。在确定设计方案之前你还可以问以下问题谁会使用这个系统它会处理哪些数据它会信任哪些服务攻击者可能会尝试哪些恶意行为如果某个部分出现故障或被攻击会发生什么尽早考虑设计决策将威胁和安全问题放在首位有助于在设计仍具灵活性时尽早发现有风险的假设。这样团队就可以在这些选择变成昂贵的代码、生产依赖或面向客户的漏洞之前做出更安全的选择。在开始编码之前要思考“足够安全”意味着什么。提前规划安全考虑因素意味着从一开始就要将身份验证、授权、加密、可审计性、数据保留、滥用情况和恢复行为等因素纳入设计。美国网络安全与基础设施安全局CISA是美国主要的网络防御机构。CISA正在推广“设计安全”策略即供应商在技术产品的设计和制造过程中融入网络安全。根据CISA的说法“遵循设计安全原则设计的产品将客户安全作为核心业务要求而不仅仅将其视为一项技术功能。”如果你对这种方法感兴趣你真的应该感兴趣建议阅读CISA关于该策略的详细文档。开发者工作流程中的持续预防还记得几十年前编辑器演变成交互式开发环境IDE并真正发挥作用的那一天。当时的关键特性是符号调试器它允许你跟踪代码流、检查变量并设置断点。IDE立即提高了代码质量因为可以持续监控每个变量了解变量何时发生了变化。从那时起IDE不断改进。后来开发者添加了在编写代码时监控代码的功能会在输入时标记错误。对于非程序员来说这个功能就像文字处理器中的拼写检查器在单词下方显示波浪线一样只不过这里针对的是整段代码。尽管有关于氛围编码的炒作但人类仍将继续编写代码。也许不是所有的代码也许不是所有的程序员但仍会有经验丰富的开发者逐行编写代码。对于这些开发者来说“源头安全”意味着IDE应该能够在编写代码时像标记语法问题一样标记安全问题。开发者工作流程中其他“源头安全”的补充措施包括合并前在拉取请求中进行检查、在代码仓库中设置依赖警报、在提交代码前检测机密信息以避免安全事件、在CI/CD管道中进行自动化测试、在选择库时提供更安全的包指导、将发现的问题与实际工作关联起来的问题跟踪以及防止有风险的更改在不知不觉中进入生产环境的部署检查。就在今年亚马逊一家本应更了解情况的公司推送了一个代码更改导致客户无法结账、查看产品和访问他们的账户。尽管有些人可能希望这种情况更频繁地发生以免把钱都给了贝索斯但事实是仅仅一个部署错误就让亚马逊损失了数百万美元。这个昂贵的失误凸显了在发布前未发现错误和漏洞的代价。在部署过程中的某个环节亚马逊没有采取预防性安全措施其防护机制如果有的话也没有发挥作用。作为开发过程的一部分程序员和编程团队可以通过采用既定的安全编码模式来确保代码的安全性。使用经过批准的框架、可重用的身份验证和授权库、安全的默认设置、安全模板和平台服务为代码提供了一个标准化的基础开发者无需为每个模块选择实现模式。美国国家标准与技术研究院NIST是美国商务部下属的非监管联邦机构它提出了一个“减轻软件漏洞风险”的框架。NIST SP 800 - 218提出了可以减少漏洞的软件开发生命周期最佳实践其中一些实践包括组织准备定义角色、标准、培训和安全工作流程。定义安全需求在开发前明确安全期望。使用安全默认设置减少开发者必须手动做出的有风险的选择。保护开发环境保护工具、代码仓库、管道和凭证。审查源代码尽早发现设计和实现中的弱点。测试可执行代码使用动态测试、模糊测试和运行时检查。保护软件完整性验证工件、来源和发布的真实性。分析漏洞了解根本原因而不仅仅是个别漏洞。NIST指南还建议跟踪、评估和更新依赖项接下来将深入讨论这一点。管理供应链风险在过去几年里我们都深切体会到了供应链中断的后果。例如我们都还记得2020年的卫生纸短缺事件。供应链描述了像卫生纸这样的物品如何从原材料经过制造、运输最终到达分销和消费环节。软件开发也有供应链我们称之为“依赖项”。没有人会编写产品或服务中的所有代码大多数情况下软件是由其他公司或开源开发者编写的软件构建块组成的。这些构建块本身通常又由其他构建块和模块组成它们几乎完成了幕后的所有工作。问题在于这些以开源库、容器、API、构建工具、SaaS组件和AI生成代码形式存在的构建块都可能给最终解决方案带来漏洞和缺陷。有时恶意行为者会向开源工具提交更改而核心开发者可能会忽略这些更改。其他时候简单的编码错误也可能导致漏洞。对于大多数开发者来说这些依赖项就像黑匣子更糟糕的是它们是不断变化的目标。随着它们的更新这些更新会被包含在生产软件中。这意味着曾经完全安全的依赖项在后续更新中可能会受到损害。可以这样想虽然你的代码可能存在漏洞但除非它被广泛使用否则威胁者可能需要一些时间才能发现这些漏洞。但那些依赖项呢它们的漏洞广为人知甚至经常在非法市场上出售。软件变得易受攻击的最容易的方式就是依赖有漏洞的软件。所有这些交互意味着必须大力推动依赖项管理。作为集成和审批过程的一部分要确保选择可验证维护的包锁定已知版本审查传递依赖项监控已知漏洞并避免使用维护不善、所有权变更可疑或安全信号不佳的库。如果这意味着更换依赖项或选择不同的供应商那么其好处将远远超过任何供应链切换成本。减少被动安全响应应对安全或软件紧急情况糟透了。当你刚喝了两口咖啡一封邮件或通知就告诉你一切都出了问题这时你能感觉到自己的心跳加速。如果这种情况发生在半夜那就更糟糕了。设计和交付安全的软件可以减少这些压力。这种方法还可以降低组织的整体责任减少负面新闻并提高客户信心。在发布前进行设计更改无疑比处理生产事故、通知客户、紧急修复或采取补偿控制措施要便宜和轻松得多。这是一种文化变革。“源头安全”使开发质量成为设计和编码的核心实践。安全必须成为编写软件的一部分。不要等到所有代码都编写和构建完成后才发现需要重新编码和重建的内容。当然如果可能的话也不要等到依赖你的客户因为某些东西严重故障而对你大喊大叫时才行动相信我有过这样的经历。你的胃会感谢你的。你的开发者会欢迎在日常工作流程中设置安全防护机制还是会将其视为额外的阻碍呢欢迎在评论区告诉我们。