源代码开发包括审查已批准的产品需求和设计文档,及实现这些要求的特性和功能。完成这个目标,要根据编写源代码策略和程序,使用特定的计算机编程语言(如C++、Java、Python、RUST等),在NIST SP 800-218,SSDF PO.1.1、PO.2.2和PW.1中做了说明。 当选择要使用的编程语言时,应该格外小心。考虑语言是静态类型还是动态类型,以及它内置了什么保护机制,以减轻漏洞并提供内存和线程安全操作。安全软件开发遵循Saltzer和Schroeder在《计算机系统中信息的保护》中总结的原则,其中包括: 开发人员还可以集成公共核心库,并重用被组织审查过的可信模块,SSDF PW.4对此做了定义。在许多情况下,这些指南总结了经批准的编译器安全设置,和部署标准化开发环境和工具,SSDF PO.3和PW.6做了规定。参照SSDF PS.1.1和PS.3,源代码通常会在源代码控制系统中按照指南进行版本控制和管理,在允许代码进入主存储库之前,按照SSDF PS.1.1和PW.7的规定,开发人员可能被要求对他们的源代码进行同行评审。有时,工程师需要在代码行和存储库之间比较和合并,在分布式团队模型中正确地管理源代码。 网络安全和基础设施安全局(CISA)将内部人员定义为“任何拥有或曾获得授权访问或了解组织资源的人,包括人员、设施、信息、设备、网络和系统。 CISA将内部威胁定义为“内部人员使用其授权访问或对组织的理解去伤害组织的可能性。”这包括有意以及无意的行为。 软件开发团队的管理者应该确保开发过程阻止有意或无意地在生产代码中注入恶意代码或设计缺陷。源代码修改可以发生在下述开发人员一个或多个场景:1. 心怀不满的工程师
牢骚满腹的工程师是一个难以发现和评估的威胁。这样的员工可能受到外界影响的压力,或者可能心生怨恨,伺机报复。槽糕的绩效评估、缺乏晋升、或纪律处分,只是可能导致开发人员对组织采取行动并破坏其开发成果的少数几个事件。此外,民族国家或竞争对手可以利用药物控制、失败的关系、或者债务等,指使内部人员破坏。 因为开发人员完全了解代码库,并且通常最了解他们的各自的编码语言、环境和风格,开发人员可以巧妙地设计难以检测到的漏洞。此外,访问不公开的设计细节能够提供薄弱架构的知识或存在被利用的安全缺陷代码。 一旦实现并注入到构建基础设施中,内置的漏洞被编译、签名和哈希,能够通过高级安全验证检查,而没有任何被入侵的迹象。 没有接受过安全设计和编码实践方面适当培训的工程师可以在源代码中无意地引入漏洞,一旦提交到源代码中存储库,就很难检测。漏洞的类型可以从缓冲区溢出到逻辑缺陷,后者更难发现。这些“零日漏洞”可以隐藏在产品中很长一段时间,为发现他们的对手提供了容易的入侵方式。 开发人员有时会在产品中添加调试功能,以方便通常在初始化之前执行的故障排除、安装、或问题报告过程。在许多情况下,这些功能是特权操作,允许开发团队获取统计信息和日志,并发出远程命令来重新配置正在开发中系统。虽然这些开发人员特性可能很有帮助,但它们通常紧密地集成到产品的核心组件中,难以移除。在某些情况下,它们导致组件被“滥用”,以促进正在使用的工具和功能,但这些没有在产品内部正式设计。 这些功能通常计划在发布前完全删除,但在某些情况下,由于核心组件的集成和工作级别,临近产品预定交货时间移除它们的风险,它们不会被删除。这些功能可以在发布时禁用,但当保留在已发布的产品中时,它们会有被发现和被利用的风险。另一个开发的问题是当只有部分或应用程序的功能需要提权,但整个应用程序是配置好的,要求以所需的特权运行,执行单个任务。权限提升应该在完成特定功能后再立即降低,以减少攻击面。 开发环境中的一个常见实践是允许员工远程开发,外包给第三方开发人员。许多这些远程开发人员在家里或分支办公室工作,使用公司提供的机器和资源通过VPN连接。当使用这种环境时,远程办公室就变成了组织网络的延伸,开发人员可以访问标准工作环境提供的所有开发资源,包括创建、编译和签入源代码更改。 虽然普及这种工作环境有很多好处,但远程工作也有其风险。家庭或远程办公网络可能无法提供和公司内部设施相同级别的保护。此外,远程办公的员工可能更倾向于使用受限制的网络应用程序,如社交媒体、网页冲浪、游戏,在某些情况下移除本地电脑保护措施以方便使用。在这种环境下,这些系统会被破坏,允许对手使用远程环境内的后门,来访问和修改组织内受保护的源代码基础设施内的源代码。 当员工被解雇,被分配到另一个项目,或长时间离开工作,他们的权限和帐户通常保持可用,并可在账户所有者不知情的情况下执行恶意活动。在这种情况下,该帐户所有者没有监视它的使用,也不知道使用它执行的任何恶意活动。以这种方式未经授权地使用帐户将授予和原始帐户所有者对所有开发资源的同等访问权。 特定的流程可以帮助在开发项目中降低有意或无意注入恶意代码的风险,包括:
保护源代码存储库及其内容的基础是使用访问控制方法,以及使用验证流程确定是否一个签入是“好的”。访问和验证从良好的源代码管理(SCM)原则开始,跟踪对源代码存储库的修改。这些原则包括更改代码库的操作历史,并解决多个贡献者合并更新时的冲突。举个例子,免费和开源软件的获取流程、开箱可用的商业软件源代码组件,安全软件代码库的管理总结如图3。图3:安全源代码库过程流
在所添加组件中,安全源代码库应该从开始并持续地查找新的漏洞和更新。保存所有开发人员及其组件下载日志。如果组件由于新的漏洞或更新而被标记将来,应该保留开发人员和已经下载组件的日志。如果由于漏洞或将来的更新,一个组件被提醒或报警,已经下载这个组件的开发人员会自动收到通知来解决这个问题。通过这种方式,当新的漏洞出现时,清楚地了解哪些程序/项目受到影响。 至少,应该使用行业认可多因素身份验证(MFA)来保护源代码控制系统,不仅记录签入,而是记录所有访问安全存储库的事件。当进行签入时,将创建日志,记录多因素身份认证开发人员ID、修改的文件、签入的日期和时间。取决于复杂性、安全需求、可用的开发资源和时间限制,当实现一个均衡的源代码签入过程时,请考虑以下几点:- 不允许任何没有经过同行或领导审查的代码签入到源代码控制库,
- 包括任何跨开发、取决于另一个开发工作的共同依赖,不应该单独签入,
为了控制所生产软件的质量,维护两个或两个以上的开发分支。在正常的软件开发过程中,所有的代码都可以存储在工作、通用、开发分支中。随着组件开发工作进展,支持交付功能的源代码被编码、测试,并由高级工程师审查,这保证满足功能集,不存在任何功能漂移。由高级工程师、构建工程师和设计师组成的开发工作完整性保证团队把经过批准的代码转移到生产分支。生产分支,有时称为发布分支,用作构建发布产品的唯一存储库。这个分支应该由审查者保护,和供应链管理部门在持续集成/持续交付(CI/CD)中使用SAST测试来加强。这个分支准备和转移的流程可以总结为:- 一旦集成代码经过测试和批准,它就被转移到生产分支中。
对产品分支的访问仅限于一小部分构建和开发团队成员。用于创建生产产品的所有构建都是来自于存储库生产分支。一旦产品被发布,产品分支应该被标记和锁定仅限受限客户访问或只读访问。实施锁定过程确保安全和可重复的构建。
对系统的所有组件执行自动化静态和动态漏洞扫描,每个已提交变更是构建过程的安全性和完整性,及验证产品发布准备情况的关键。这种自动化扫描以及其他与安全相关的扫描,可以执行代码分析以确定在源代码评估阶段,受限的应用程序编程接口(API)是否包含诸如缓冲区溢出或内存泄漏等漏洞。代码提交之前,执行静态分析,扫描机密凭证,CI/CD期间阻止来自代码库的机密凭证。这些静态扫描技术的复杂性和完全性差异很大。这些工具应该由测试团队以及本地开发工程师使用。最安全的开发流程推荐这种做法。 在产品构建环境中还应该使用独立和更高质量的扫描工具。还应该注意,静态分析程序在C++等静态类型语言上工作得更好,因为代码中使用的变量类型在编译时是已知的,而Python等动态类型语言在运行时解析变量类型。当功能和组件完成并能够运行时,动态测试可以找到额外的安全弱点。这些通常是用户输入错误或恶意的注入,只能在运行时通过测试发现。对于web应用程序,应该使用交互式应用程序安全测试(IAST)、动态应用程序安全测试(DAST)和运行时自防护(RASP Application Self-Protection)工具,参见NIST 800-53 v5。因为相比于SAST工具,IAST工具往往有更多的误报,特别是在web方面应用程序,在这种环境中实现测试需求时鼓励使用内省(introspection)的SAST工具。
为了确保开发过程的完整性和质量,应该每晚执行构建,包括手动和自动的安全和回归测试。测试用例应该在软件设计过程中实现,扩展到编码过程,在“好的”和“坏的”场景中验证所有功能区域。使用这个过程,任何缺陷或变更,无论是恶意的还是无意的,都可以被识别和解决。 带有回归测试的夜间构建应该由QA工程师操作,由构建工程师合并到构建环境中。这和开发人员自己的自动化单元测试的情况不同,那可以在编码期间手动运行,也可以在组件的“构建”过程中自动运行,通常由开发人员负责。 当回归测试失败,发送的日志和电子邮件自动通知,帮助通知并跟踪问题发生的时间和地点。每晚构建过程也是一个很好的性能矩阵,以评估开发人员的能力和遵守安全和开发过程。有关产品构建的更多细节,请参阅2.4节加固构建环境,文档记录了与产品的生产构建比较的本地开发构建。
使用安全设计实践,对产品的所有组件和功能进行架构设计使之与系统交互,非常重要,包括威胁建模和攻击面分析。一旦发现并减轻了所有安全风险,架构和设计文件最后定稿,分发给各开发小组执行。生成初级设计和功能说明直接映射到给定的架构和高层设计,开发任务和时间表被规划出来。在编码和系统实施过程中,必须慎之又慎,确保所有开发工作映射到特定的系统需求,这样就不会出现“功能漂移”破坏产品完整性或注入漏洞。 正式的、非正式的和同行审查有助于确保添加到存储库中的代码符合特定的要求,而且仅符合那些要求。这些审查还可以识别模块和作为较大的包或组件特性的一部分包含在内的未使用的代码。在可能的情况下, 应该只要求在产品中包含的模块。 此外,开发人员应该删除不使用的模块和超出需求及设计文档的代码。限制开发人员工具的添加,比如那些辅助调试,配置和监视,只含有那些批准的系统设计还减轻了攻击面。尽快报告和解决功能漂移问题也可能有帮助。 此外,构建环境应该支持扫描和检测所有系统内的插件。结果应该与一个允许的列表相互关联,以确保未添加未经授权的组件。这些扫描产生的制品描述产品中包含哪些组件和软件功能,更重要的是,确保所有组件都经过了分析,从而了解和记录每个组件的风险。
代码审查使用两种不同的过程执行,正式的和非正式的,并且在开发生命周期的不同阶段实现。 应该优先考虑代码审查,至少应该优先考虑最关键的代码,使用正式和非正式的审查过程进行识别和评审。关键代码包括以下组件: 除了正式和非正式的代码审查之外,自动化的代码审查工具也应该部署以提供完整的代码审查覆盖。 当在开发中,完成度量阶段或检查点时,内部开发小组使用非正式的代码审查过程。非正式审查是用来确保遵循安全编码策略和过程,在组件的初级设计时,源代码审查符合设计和功能要求。这些审查由开发团队的成员进行,包括项目负责人和高级开发人员确保在开发过程中安全和完整性。虽然是非正式的,但是进行代码评审的过程产生了关于审查的领域和结果的文档,可以用来帮助度量开发团队的成果。非正式的代码评审也被用作培训工具让团队成员了解如何实现安全编码实践。此外,非正式的代码评审可以用来衡量代码评审过程的质量和开发人员可交付成果。 正式的代码评审确保安全集成了使用最佳实践的关键组件。这些评审关注系统完整性、设计和架构,同时解决所有功能、安全性和可靠性方面的问题。他们还确定了关注任何可能被利用或入侵的领域。 工程小组,通常包括QA成员、构建专家、设计人员和架构师常常进行正式的代码评审。在正式的代码评审中,在评审源代码之前,组件的所有者描述了组件的功能及其与系统中其他组件的交互。指定人员做详细的记录,跟踪产品的核心组件的审查。 正式代码评审的结果是活动清单,产品发布前问题必须得到处理。正式的代码评审通过分享产品设计和实施的知识,以加强构建和开发环境的测试需求,来帮助开发工作。正式的代码评审还允许产品管理团队来衡量产品发布的准备情况,确保发布之前满足所有要求。
如第2.1节“建议的缓解措施”子章节“评估和培训”总结到,开发人员应该持续接受培训,以理解公司发展所需的安全开发实践。在开发生命周期中也必须提供这种资源,允许开发人员联系专家并解决他们可能存在的关于特定安全问题、实践或漏洞的问题。在日常开发活动中,应利用安全专家方便同行以及源代码审查,培训个人了解公司安全实践和评估他们的知识。一个实施良好的同行评审过程可以让工程师预防缺陷,最小化安全漏洞,促进团队协作和知识共享。
与构建环境一样,必须加固开发环境。第2.4节加固构建环境中定义的缓解措施也适用于开发环境。然而,虽然生产构建系统通常位于访问受限的受保护的分段网络中,开发中的构建环境可能驻留在隔离程度较低的端点系统中。例如,许多开发环境允许远程VPN访问内部开发机方便远程工作人员,并允许他们参与开发活动。在这种情况下,当从远程连接到公司开发环境时,VPN和MFA必须用于保护开发环境。应该安装端点安全软件用于防止、检测和响应针对主机系统的威胁。除了VPN,实施人员应该考虑使用“跳板机”,一个系统在不太安全的远程主机和受保护的开发环境之间充当门户。这允许对所有活动进行持续监测,并提供保护和/或限制可访问性以及远程开发人员的操作权限。威胁模型和漏洞需要对与产品开发相关的所有开发环境进行评估。 开发人员通常在应用程序开发中使用开源代码,开源代码库中可能存在多个有漏洞的依赖。 开发组织应该使用专门的系统来下载、扫描和执行定期检查开源代码库的新版本、更新、已知或新版本漏洞(参见上面的图3)。与所有软件一样,我们强烈推荐教育开发人员考虑使用开源软件、闭源软件和改进最佳实践缓解措施。详情请参阅SSDF,特别是PW .4.1,PW .4.4,PW .4.5和PO.1.3。 软件开发小组的管理人员应该确保能够生成、测试和保存源代码的开发过程都是使用定义良好且安全的实践完成的。这有助于在所使用的工程工具链和过程中建立信任。这些实践解决以下安全问题:
在确保开发环境的完整性时,必须小心地加固构建管道中的开发系统,如2.4节加固构建环境中所定义的。此外,所有的开发系统都必须仅限于开发活动本身,不应进行任何其他活动,如电子邮件,只能用于工作,不能用于个人。如果可能的话,开发系统不应该访问Internet,部署为本地虚拟系统,只提供主机访问。即使只用于本地开发使用,开发时安装的所有工具系统必须预先批准,包括调试器、测试工具、漏洞扫描器和建模软件。
许多漏洞使用常见的入侵技术,如缓冲区溢出、面向返回编程(ROP)执行小工具、延迟动态函数加载和重写软件异常处理程序。许多这些技术、编译器、汇编器、链接器、解释器工具已经扩展到包括防御来减少这些风险。以下是构建链防御技术的列表,应该部署以减少入侵方式:- 地址空间布局随机化(ASLR) -防止ROP/硬编码IP引用,
- 无执行位(NX) - CPU标志执行防止内存定位,
- 二进制文件剥离——从二进制文件中删除符号使文件变得更加难以逆向工程,
虽然上述阻止措施对于确保开发中的软件运行时保护至关重要,开发团队还应向最终用户提供一个他们的软件可以安全运行的建议环境。例如,许多杀毒产品提供行为分析引擎以提供额外的安全检查,例如:- ROP调用检测-检测JMP/RET(非常规程序流),
- DLL注入检测-动态链接库(DLL)的位置和签名验证,
- Root-Kit检测-阻止地址 hooking ,
还需要注意的是,虽然解释性语言通常没有上面概述的漏洞风险,解释器本身的实现和他们使用的底层系统库却有这样的风险,因此这些缓解措施也适用于他们。
在开发人员的构建流程中,各种任务通常集成在一个集成开发环境(IDE)。其中许多环境都是自包含的,允许所有开发活动,包括从工具内部执行编码、编译、链接、打包和调试。IDE甚至可以提供将源代码签入存储库的功能。在许多情况下,这些IDE支持多种编译器语言和环境,可以安装插件扩展IDE的能力。因为复杂和不可信源代码,IDE可能遭到入侵,导致不安全的本地开发环境。为了确保开发过程的完整性,开发人员环境中使用所有IDE及其相关的插件合并到任何开发人员机器之前,必须预先批准、验证和漏洞扫描。 构建环境可能需要使用特定操作系统的实用程序和命令。例如,在开发人员的主机上的构建过程中,Windows环境可能需要Linux操作系统命令。这样的构建环境可能需要在开发主机上安装第三方操作系统工具和实用程序,提供开发环境和生产构建之间的兼容性。此外,许多开发环境需要API转换库促进两个不同操作系统之间的通用编码环境,例如Windows和Linux。可以通过商业软件和开源软件获得工具链和兼容库。兼容性工具链和库也都需要在开发采用之前通过脆弱性评估。 开发经理希望确保集成到交付产品中的组件和软件在部署环境中进行测试。这过程包括合并所有必需的依赖项,包括源代码、组件和添加到单个系统中所需的元数据和实用程序。在代码集成期间,开发人员将确保代码能够成功构建,并监视和评估运行时的行为。软件集成应该使用推荐的零信任原则NIST SP800 - 207。 所有第三方模块都应该进行CVE测试。一个软件成分分析工具可以帮助实现这个过程的自动化。开发团队应该还订阅来自国家网络意识系统和其他来源的报警和报告,获取最新的软件漏洞信息。一旦模块完成漏洞检查,它们可以被添加到开发人员或开源代码审查委员会(OSRB)的存储库中以备下载。这个受信任的存储库应该继续进行测试,以识别模块内被报告的新漏洞。它还应该包含一个向最终用户提供漏洞更新和/或补丁的过程。应用程序包括来自其他来源代码的代码,有时为了特定的使用目的稍微修改或添加集成代码。 安全依赖分析程序和许多其他工具和服务可以帮助检测具有已知漏洞的重用组件。这些活动通常在集成开发环境(IDE)中进行,使用组织的安全编码实践和指南,例如SSDF的PW.3.1、PW.3.2和PW.4.1。代码集成应该是使用零信任原则实现。信任不应该被暗示,因此重要组件和函数应该检查代码中的使用和访问权限,只在必要时升级特权。开发人员应该确保代码和构建集成过程是可重复的。开发人员和QA工程师可以提供自动回归测试确保组件正确集成,实现设计和需求文档中的功能。它们还可以根据SSDF PW .5.1和5.2所定义的条件,提供额外的静态和动态扫描工具检测已开发代码中的编码错误和安全缺陷。 软件开发小组的经理应该确保他们开发的软件不存在高风险的已知缺陷和漏洞。当客户发现并报告漏洞时、开发团队应该对事件做出响应并提供组件更新以减轻与缺陷或漏洞相关的风险。 供应商应该有一个公开流程来接受来自客户和第三方研究人员报告的潜在缺陷和漏洞。供应商应该使用来自网络安全与基础设施安全局(CISA)等可信组织的自动漏洞通知,及时收取最新及高风险威胁的警报。所有通知都应该根据与产品的关系进行评估,并根据风险评估确定优先级。 然后,应被指派工程师审查、诊断和解决PW.8、RV.1.1和RV.1.3中定义的问题。为了减少攻击面,应该实施一个过程来识别漏洞类别,并检查可能受到同一类已确定事件影响的其他产品功能和组件。应该根据组织的内部漏洞管理策略,向客户提供及时响应,这应该基于如NIST SP 800-216指南的行业最佳实践文档。根据SSDF RV.2.1、RV.2.2的要求和规定,使用安全通道更新软件。更新也提供给产品的所有客户,并描述缺陷或弱点及其解决方法传达给客户。也可以基于客户配置的更新策略,自动应用到产品。 一旦发布,产品功能可以由初始开发团队之外的产品开发团队扩充。在许多情况下,这个外部开发团队,与负责产品的开发人员,可能需要为产品添加额外的功能或根据特定客户的需求定制,实现产品的所有者没有满足的功能。这个外部开发团队可能是生产该产品公司内部的解决方案团队或增值经销商(VAR)。一个这种活动类型的例子可能是向现有产品添加所需的身份验证方法。 当这种活动发生时,对产品的修改可以包括添加软件包来支持该功能,以及图形用户界面(GUI)更改来启用和管理新功能。在此活动中,新的开发工作、部署的新包、或修改设计时没有用到的API、都可能引入漏洞。 在可能的情况下,产品的扩展必须遵循所有原始产品开发根据SSDF PS.1.1、PW.4.1、PW.4.2、PW.5和PW.7定义的安全开发实践。此外,应提供一份软件物料清单(SBOM),详细说明添加的包和软件。如果需要签名,则使用的证书(如果不是来自同一产品的供应商)必须明确标识。原始代码中被修改的模块必须在新的SBOM清楚标明,原始组件信息、所有者、连同描述新修改模块的新信息,都要清楚标明,如同SSDF PS.1.1的要求。 当出现问题时,安全应急响应团队(PSIRT)必须可用并随时准备帮助最终用户,即使问题的原因与SSDF RV.2.1中按要求添加的扩展有关。在许多情况下,增值销售商(VAR)将作为客户和产品安全应急响应团队之间的“中间人”,帮助解决问题。 给工程师解决问题的反馈必须在客户和外部开发小组之间聚合提供及时、准确的信息以解决问题。任何由于所提供的API和功能中的漏洞而导致的代码修改必须被修改更正并发布给所有客户。这些活动提供符合SSDF活动的下列缓解措施:1. PS.1.1 -存储代码和可执行文件,审核和批准所有变更。2. PS.3.2 -为生成的每个软件包创建并维护一个SBOM。7. RV.2.1 -分析每个漏洞,以收集足够的信息来计划其补救措施。
文章来源: https://mp.weixin.qq.com/s?__biz=Mzg3NjU4MDI4NQ==&mid=2247485399&idx=1&sn=1616946e493efda5011aad0b02226d36&chksm=cf315b05f846d213ab934ab3282d51f448af4d64aec47cfababbfb70cdcbdba8d13db12014e3&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh