随着物联网设备的普及,嵌入式安全攻击也随之增加。从历史上看,嵌入式系统工程师忽略了设备层的安全性,尽管嵌入式设备的许多领域都容易受到错误的影响。串行端口、无线电接口,甚至编程/调试接口都可能被黑客利用。模糊测试是工程师发现嵌入式设备弱点的重要场所,应考虑用于强化物联网设备接口。
什么是模糊测试?
模糊测试就像神话中的百万只猴子随机打字写莎士比亚。在实践中,小说作品需要许多随机组合来产生一个简单的短语,但对于嵌入式系统,我们只需要从一个已知的好句子中更改几个字母。
许多商业和开源工具可用于实施模糊攻击。这些工具生成随机字节串,也称为模糊向量或攻击向量,并将它们提交到正在测试的接口,跟踪可能表示错误的结果行为。
模糊测试是一个数字游戏,但我们不能尝试无限数量的可能输入。相反,我们专注于通过最大化模糊向量提交率、模糊向量的有效性和错误检测算法来优化测试时间。
模糊测试概念
由于许多模糊测试工具都是为测试 PC 应用程序而设计的,因此如果您将嵌入式代码作为本地编译的 PC 应用程序运行,则更容易适应它们。在 PC 上运行嵌入式代码会产生巨大的性能优势,但也有两个缺点。首先,PC 微处理器的反应与嵌入式微控制器不同。其次,我们必须重新编写任何涉及硬件的代码。然而,在实践中,在 PC 上运行的优势大于劣势。真正的障碍是移植代码以在 PC 上本地编译的困难。
我们如何知道模糊向量何时触发错误?崩溃很容易发现,但很难识别导致重置的模糊向量。内存溢出错误或杂散指针写入(对黑客最有价值的错误类型)几乎不可能从系统外部辨别出来,因为它们通常不会导致崩溃或重置。
许多现代编译器,例如 GCC 和 Clang,都有一个称为内存清理的功能。这将内存块标记为干净或脏,具体取决于它们是否正在使用,并标记任何访问脏内存的尝试。但是,内存清理会消耗闪存、RAM 和 CPU 周期,使其难以在嵌入式设备上运行。因此,相反,我们可以测试代码子集,构建具有更多资源的设备版本,或者使用 PC。
测试的有效性可以通过执行的代码量来评估。在这里,编译器也可以通过使用面包屑子例程调用来跟踪内存使用情况。代码覆盖率库为每个代码路径维护一个使用值表,在面包屑执行时递增它们。
然而,对于嵌入式模糊测试来说,代码覆盖率数字很难解释,因为大部分代码对于模糊向量来说是不可访问的;例如,独立于接口运行的外围设备的设备驱动程序。因此,很难为嵌入式系统定义“完整的代码覆盖率”——也许只有 20% 的嵌入式代码是可访问的。代码覆盖还消耗大量闪存、RAM 和 CPU 周期,并且需要专门的硬件或 PC 目标才能运行。
错误报告
当模糊测试发现导致不良行为的向量时,我们需要详细信息。错误发生在哪里?调用堆栈的状态是什么?错误的具体类型是什么?所有这些信息都有助于分类并最终修复错误。
错误分类在模糊测试中至关重要。新的 fuzz 项目经常会发现很多 bug,我们需要一种自动的方法来确定它们的严重性。此外,模糊错误往往会阻止错误,因为它们通常会在代码路径中进一步掩盖其他错误。我们需要快速解决模糊测试期间出现的问题。
嵌入式客户端不像 PC 那样愿意透露他们的信息。通常,崩溃只会导致设备重置并重新启动。虽然这在现场是需要的,但它会擦除设备的状态,从而难以了解是否发生了崩溃、发生的地点或原因,或者所采用的代码路径。工程师必须找到一致的再现向量,然后使用调试器跟踪不良行为并找到错误。
在模糊测试中,一个测试可能会为几个错误产生数千个崩溃向量,给人一种错误系统的错误印象。快速确定哪些向量与相同的潜在错误相关联非常重要。对于嵌入式设备,崩溃本身的位置对于错误通常是唯一的,通常不需要找到完整的调用堆栈跟踪。
连续模糊测试
由于模糊测试的随机性,长时间运行它们会增加他们发现问题的机会。但是,任何项目计划都不能吸收开发结束时冗长的模糊测试周期造成的延迟。
在实践中,模糊测试将在发布过程之后在其自己的分支上开始。任何新发现的错误都将在本地分支中修复,以便测试可以继续,而新错误不会阻止额外的错误发现。作为发布周期的一部分,从模糊测试先前版本中发现的错误将被评估以包含在新版本中。最后,应该将发现错误的模糊向量添加到正常的质量保证过程中,以验证修复并确保这些错误不会无意中重新引入代码中。
我们应该在不同场景下对设备进行模糊测试;例如,如果联网,设备对连接请求的响应会有所不同。在每个可能的场景上运行模糊测试是不切实际的,但我们可以为每个可能状态的值包括模糊测试。例如,对每种不同的设备类型运行模糊测试,同时保持其他变量相同。然后为一个设备类型的另一个变量(例如网络连接状态)运行不同的值。
模糊测试架构
两种突出的模糊测试架构是定向模糊测试,其中模糊向量由工程师在测试前指定,以及覆盖引导模糊测试,其中模糊工具从一组初始测试向量开始,并根据数据包的渗透程度自动改变它们编码。
此外,并非所有代码都可以在 PC 上运行,并且为嵌入式应用程序开发 PC 模拟器可能是不切实际的,具体取决于所测试的内容。
以下是四种模糊测试架构的总结:
嵌入式硬件上的直接接口测试——在嵌入式设备上运行正常的生产映像,并通过接口注入模糊数据包
数据包(堆栈)注入测试——直接调用传入的数据包例程,而无需通过无线运行接口
使用模拟器进行定向模糊测试——使用基于 PC 的模拟技术开发和测试嵌入式代码
使用模拟器进行覆盖引导的模糊测试(如下所示的 Libfuzz)
多个模糊测试器
在使用调试接口锁定和安全启动锁定嵌入式设备后,我们需要考虑对设备接口进行模糊测试。用于保护 Web 服务器的许多相同工具和概念可以适用于嵌入式设备。
为工作使用正确的工具。Coverage-guided fuzzing 对于连续模糊测试是必要的,但如果您的代码仅在嵌入式硬件上执行,那么定向模糊器可能是提供一定程度的模糊测试覆盖率的不错选择。
最后,您应该在尽可能多的场景中使用多个模糊测试器,因为每个测试器都会对设备进行略微不同的测试,从而最大限度地提高覆盖率,从而提高嵌入式设备的安全性。
审核编辑:郭婷
-
嵌入式
+关注
关注
5068文章
19013浏览量
303096 -
物联网
+关注
关注
2903文章
44253浏览量
371098 -
编译器
+关注
关注
1文章
1618浏览量
49045
发布评论请先 登录
相关推荐
评论