作者:Jim McElroy
从发电厂到工厂再到供水,工业控制系统正在从专有和封闭的网络转变为物联网的一部分。安全的开发过程可以减少这些关键基础设施中的软件漏洞。
在一个可能让大多数软件开发人员感到震惊的情况下,计算机蠕虫已经成为电影明星。在新动作惊悚片《零日》中,反派炸毁了化工厂,关闭了核电冷却系统,破坏了火车,关闭了国家电网等等。这部快速移动的动作片的明星是臭名昭着的Stuxnet蠕虫,据报道,这是由美国和以色列情报部门开发的,旨在削弱伊朗的核计划。Stuxnet攻击了控制核电站内离心机的可编程逻辑控制器(PLC),但蠕虫及其变体可以针对一系列制造,运输和公用事业操作中的系统进行定制。
正在看电影的公众基本上没有意识到潜伏在我们互联基础设施中的危险——这些危险一直困扰着工程师和开发人员。通常,工厂自动化系统使用监控和数据采集(SCADA)系统运行,以实现人机界面和访问。IEC61508标准及其衍生物的实施是为了确保在广泛的行业中运行这些系统的软件的功能安全。但是,这些SCADA系统(通常基于Windows或Linux)又连接到企业管理,企业管理需要访问库存控制,营销,会计和许多其他目的。当然,这些都与外部互联网相关联,因此为来自外部的攻击提供了完美的途径。因此,虽然早期的封闭系统依靠不幸或恶意的个人来手动安装蠕虫,但今天的互联网连接工业系统提供了新的攻击面。由于这种高水平的连接性和攻击风险,如果系统不安全,则不能认为它是安全的。
IEC61508及其衍生产品没有专门针对安全性。开发人员需要解决从产品开发阶段到上市后管理的网络安全问题。为了遵守各种准则和要求,开发人员必须使用足够的工具来处理高复杂性。随着这些系统越来越受到认证要求的约束,编码的正确性必须与所需的功能一起得到证明和记录。
开发安全代码的核心是设计一个策略,该策略可以基于网络安全指南,例如美国国家标准与技术研究院(NIST)发布的指南,以及组织自己的方法,并将其构建到正在开发的系统的需求文档中。此外,该项目应采用MISRA C等编码标准,以防止可疑的方法和粗心大意的错误,这些错误可能会危及安全性,而不会立即显现出来,甚至导致功能错误。当然,下一个重要步骤是确保这种策略和编码标准实际上已经有效地执行。由于当今软件的规模和复杂性,这不再可以手动完成,必须使用一套全面的工具,可以在编译之前和之后彻底分析代码。
使用可追溯性和分析来验证安全性
虽然定义需求是必不可少的第一步,但必须有一个明确定义的方法来跟踪和验证是否满足需求。需求可追溯性和管理可提高代码质量以及应用程序的整体安全性、安全性和有效性。基于需求文档的双向可追溯性可确保每个高级需求都由一个或多个低级需求覆盖,并且每个低级需求都链接到代码、验证活动和流程中生成的工件。同样,这些链接必须追溯到从工件和代码到需求的上游,确保流程中任何阶段的任何更改都可以轻松检测、理解和适当地管理(图 1)。
图1 需求可追溯性工具提供了流程透明度,对于确定开发流程所有阶段的影响分析至关重要。
需求可追溯性工具允许团队处理单个活动,并将代码和验证工件链接回更高级别的目标。在双向需求可追溯性的监督下,在开发过程的早期和连续阶段应用了三个主要功能。这些是静态分析,功能测试和结构覆盖分析的动态分析以及单元/集成测试。后者在开发过程的早期应用静态和动态分析,也适用于后期集成的代码。
静态和动态安全分析合作伙伴
在确保安全性时,两个主要问题是数据和控制。必须考虑的问题包括,谁有权访问哪些数据?谁能从中读取,谁可以写信给它?与哪些实体之间的数据流是什么?以及访问控制如何影响控制?在这里,“谁”可以指开发人员和操作员以及黑客等人,也可以指应用程序中的软件组件或居住在网络架构中的某个地方。为了解决这些问题,静态和动态分析必须齐头并进。
在静态分析方面,这些工具使用未编译的源代码来检查代码的各种质量指标,例如复杂性,清晰度和可维护性。静态分析还可用于根据选定的编码规则检查代码,这些规则可以是支持的编码标准(如MISRA C或CERT C)的任意组合,以及开发人员或公司可能指定的任何自定义规则和要求。这些工具寻找可能危及安全性的软件构造,并检查内存保护以确定谁有权访问哪些内存并跟踪可能遍历内存位置的指针。理想情况下,结果应以图形屏幕显示,以便于评估结果,以确保代码干净、一致且可维护,并符合编码标准(图 2)。
此过程可以通过运行分析工具并针对应用程序的源代码进行编码标准定义来自动完成。几乎可以肯定的是,此类代码需要修改,以符合已添加到 MISRA C 中的最新安全要求(图 2)。
图2 编码标准合规性与文件/功能名称内联显示,以显示系统的哪些方面不符合标准。编程标准调用图显示了系统编码标准合规性的高级彩色编码视图。
另一方面,动态分析测试已编译的代码,该代码使用编译器生成的符号数据链接回源代码。动态分析,特别是代码覆盖率分析,可以提供对测试过程有效性的深刻见解。但是,开发人员通常尝试手动生成和管理自己的测试用例。从需求文档开始工作是生成测试用例的典型方法,它们可能会以不同程度的有效性刺激和监视应用程序的各个部分,但考虑到当今代码的大小和复杂性,这不足以使代码正确无误或获得可能需要的任何认证或批准。
自动生成测试用例可以大大增强测试过程,节省时间和金钱。但是,有效的测试用例生成基于代码的质量静态分析。静态分析提供的信息有助于自动测试用例生成器在动态分析期间为应用程序中的软件组件创建适当的激励。可以手动创建功能测试以扩充自动生成的测试用例,从而提供更好的代码覆盖率和更有效和更高效的测试过程。手动创建的测试通常是从需求生成的,即需求驱动的测试。这些应该包括任何功能安全测试,例如模拟尝试访问控制设备或向其提供会改变其任务的错误数据。基于创建的测试的功能测试应包括鲁棒性,例如测试不允许的输入和异常条件的结果。此外,动态分析不仅提供代码覆盖率,还提供数据流/控制分析,反过来可以使用双向需求可追溯性来检查其完整性。
除了测试是否符合标准和要求外,还有必要检查可能是“血统不明的软件”或SOUP代码的任何部分。例如,存在与“死”代码区域相关的危险,这些区域可能被黑客激活或系统中的晦涩事件用于恶意目的。尽管从头开始实现安全性是理想的,但大多数项目都包含预先存在的代码,这些代码可能具有看起来只是所需的功能。开发人员需要抵制自动引入此类代码(甚至是来自同一组织的代码),而无需对其进行与他们自己的代码完全相同的严格分析。静态和动态分析一起使用可以揭示死代码的区域,这些区域可能是危险源,也可能只是占用空间。有必要正确识别此类代码并进行处理,通常是通过消除它。当开发团队(可能在完全不同的位置)开发、测试、修改和重新测试单元时,可以存储、共享和使用从综合工具套件生成的测试记录,同时将单元集成到更大的项目中。
为了使系统可靠和安全,它们还必须是安全的。为此,它们必须被编码为不仅遵守语言规则,而且还要遵守确保安全和保障的明确定义的策略。将一套全面的测试和分析工具应用于组织的开发过程,可以大大提高安全措施的彻底性和准确性,以保护重要系统。它还使团队为共同目标而共同努力并对最终产品充满信心的努力变得顺利。由此产生的产品将有更好的机会获得客户批准,如果需要,还可以获得当局的认证 - 并且它不太可能成为下一部大片的明星。