史上最荒谬 BUG 诞生了!零测试、直接将正则表达式扔进内核,CrowdStrike 卖惨不成反被喷

科技   2024-08-09 11:11   浙江  

转自:InfoQ -褚杏娟 核子可乐

距闹得沸沸扬扬的由第三方 CrowdStrike 软件引发的微软“蓝屏”事件过去了半个多月了,当地时间 8 月 7 日,CrowdStrike 发布了长达 12 页的根本原因分析 (RCA),详细介绍了该事件的调查结果、缓解措施和技术细节。

不过,CrowdStrike 看似诚意满满,但网友们并不买账:

这不是一份 RCA,你只是告诉我们发生了什么。一份 RCA 应该告诉我们为什么会发生。不要说“我们有一个 bug”:当然你们有一个 bug。解释一下这个 bug 是如何泄露到全球的、是什么样的实践和流程出了问题,以及为什么这个 bug 会泄露到生产环境。

CrowdStrike 还打起了感情牌:“对于任何仍受影响的客户,请知道,在所有系统恢复之前,我们不会休息。”但网友们并没有接招:“你们应该退出这个行业,就这么简单。”

但其实,真正让网友们感到气愤的还是 CrowdStrike 揭示的问题,用网友精辟的总结就是,“根本原因:没有测试。解决方案:下次确保在发布前进行测试。”而且,其披露出来的在内核代码中使用正则表达式的做法也被网友群嘲。

那 CrowdStrike 到底做了些什么引得大家更加不满了?


“讲真,都没有做测试吗?

先看下 CrowdStrike 设想的流程:


CrowdStrike Falcon 传感器负责提供强大的传感器 AI 与机器学习模型,用以识别并修复最新高级威胁,来保护客户系统。这些模型始终保持最新状态,并通过从传感器端传来的最新威胁遥测结果与来自 Falcon Adversary OverWatch、Falcon Complete 和 CrowdStrike 威胁检测工程师的 AI 中学习以持续加强。这套丰富安全遥测体系的起点,就在于来自各个传感器,并通过过滤和聚合以形成本地图存储的数据。


每个传感器将其本地图存储中的上下文与实时系统活动相关联,进而汇总为行为与攻击指标(IOA),并不断实施改进。此改进过程还涉及一套传感器检测引擎,负责将内置传感器内容与云端提供的快速响应内容相结合。这部分快速响应内容用于收集遥测数据、识别对手行为指标,并增强传感器上的新型检测与预防功能,且无需更改传感器代码。快速响应内容采取行为启发式方法,与 CrowdStrike 的传感器 AI 预测与检测功能并不相同。


快速响应内容通过通道文件形式传送,并由传感器的内容解释器使用基于正则表达式的引擎进行解释。每个快速响应内容通道文件,都与传感器版本中内置的特定模板类型相关联。模板类型为内容解释器提供活动数据和图上下文,从而与快速响应内容进行匹配。


随着 2024 年 2 月传感器版本 7.11 的发布,CrowdStrike 引入了一种新的模板类型,以便查看并检测滥用命名管线及其他 Windows 进程间通信(IPC)机制的新型攻击技术。IPC 模板实例通过编号为 291 的相应通道文件作为快速响应内容被传送至传感器。

新的 IPC 模板类型定义了 21 个输入参数字段,但使用通道文件 291 的模板实例调用内容解释器的集成代码,仅提供了 20 个输入值以实现匹配。 此参数计数不匹配无法被多层构建验证与测试所发现,因此在传感器发布测试过程、模板类型(使用测试模板实例)压力测试乃至现场前几次成功部署 IPC 模板实例时均未暴露。造成这种情况的部分原因在于,测试期间及初始 IPC 模板实例中对第 21 项输入使用了通配符匹配标准。

2024 年 7 月 19 日,CrowdStrike 部署了两个额外的 IPC 模板实例。其中之一为第 21 项输入参数引入了非通配符匹配标准。这些新的模板实例产生了新版本的通道文件 291,因此需要传感器检查第 21 项输入参数。在将此通道文件传送给传感器之前,原有通道版本中的 IPC 模板实例从未使用过第 21 项输入参数字段。内容验证器评估了新的模板实例,但评估过程同样以 IPC 模板类型能够提供 21 项输入为前提和基本预期。

一旦收到带有问题的内容,新版本的通道文件 291 会导致传感器在内容解释器遭遇越界读取问题。在操作系统发出的下一条 IPC 通知中,会对新的 IPC 模板实例进行评估并指定与第 21 项输入值进行比较。而内容解释器的预期为只处理 20 个值。因此在尝试访问第 21 个值时会超出输入数据数组末尾的越界内存读取,并导致系统崩溃。

总之,这些问题综合起来共同导致了系统崩溃:内容验证器验证的 21 项输入与提供给内容解释器的 20 项输入不匹配,内容解释器中存在潜在越界读取问题,而且第 21 个字段缺少针对非通配符匹配条件的特定测试。 虽然通道文件 291 上的这种情况目前无法重现,但其仍然为 CrowdStrike 部署的流程改进与缓解步骤提供了参考,旨在进一步增强系统弹性。

对于上述解释,有网友并不认可:“一如既往,一切都归结为测试。”

还有网友认为 CrowdStrike 是故意的:“你们确实有办法测试真实世界条件下的输入,但故意选择不这样做,你们不会发布如此未经充分测试的东西,除非是故意保持沉默。”

“我没有看到‘房间里的大象’被解决”

CrowdStrike 在文件讲述了六个自己的“发现”与“缓解措施”,但更暴露了自己犯了本不该犯的错误。

“根据 RCA,问题的核心是一个数组越界错误,这是缓冲区溢出的特殊情况,在开发 Crowdstrike 系统的 C++ 语言中被视为未定义行为。”工作 15 年的工程师 Eduardo Bellani 表示,“对于这种关键性的软件,这样的问题不应该发生。

“RCA 中提出的所有技术缓解措施都只是堵塞漏洞。但安全不能以这种方式实现,此类努力需要在一开始就将安全性融入设计、工具和语言中。如果我是 Crowdstrike 的客户,我会担心未来。”Bellani 说道。

“我没有看到‘房间里的大象’被解决:Crowdstrike 是否会在没有进行本地测试来确保‘正确’运行的情况下,就将做出的更改推向生产中?”有网友表示。

那我们具体看下 Crowdstrike 自己的“发现”与采取的具体措施,不难发现网友们的吐槽还是“在理”的。

1. 在传感器编译时,未验证 IPC 模板类型中的字段数量

为此,在 7 月 19 日,CrowdStrike 为用于验证模板类型提供的输入数量的传感器内容编译器开发了一个补丁,并于 2024 年 7 月 27 日作为 CrowdStrike 内部构建工具的一部分投入生产。该传感器内容编译器补丁还验证了在任意平台上,均不存在其他可能提供不正确输入数量的模板类型。

 2. 通道文件 291 上的内容解释器输入字段,缺少运行时数组边界检查机制。

由于 IPC 模板类型仅生成 20 项输入,因此一旦交付使用非通配符匹配标准作为第 21 项输入的快速响应内容,则内容解释器就会执行输入数组的越界读取。此情况并不属于任意内存写入问题,且已经过独立审查和确认。

为此,7 月 25 日,CrowdStrike 在检索输入字符串的内容解释器函数中添加了边界检查,同时添加了额外的检查,以确保输入数组的大小与快速响应内容所需的输入数量相匹配。

CrowdStrike 认为,添加的边界检查机制可以防止内容解释器执行输入数组的越界访问并导致系统崩溃。额外的检查增加了一层额外的运行时验证,以确保输入数组的大小与快速响应内容所需的输入数量相匹配。

另外,定义 IPC 模板类型的传感器代码已经更新,旨在提供正确的输入数量(21 项)。此修复程序正通过传感器软件修复程序版本,反向移植至所有 Windows 传感器 7.11 以及更高版本。此版本将于 8 月 9 日正式发布。

 3. 模板类型测试应涵盖更广泛的匹配标准

此前的 IPC 模板类型的开发过程中,CrowdStrike 进行了手动与自动测试。此番测试侧重于模板类型的功能验证,包括安全相关数据能否通过其正确流动,以及对数据内容的评估,以根据开发测试用例中创建的标准生成适当的检测警报。

其中,在自动测试当中,CrowdStrike 选择了一组 12 个静态测试用例以代表更广泛的操作预期,并验证了遥测与检测警报是否正确创建。通道文件中的数据选择以手动方式完成,并且在所有模板实例的第 21 个字段中包含正则表达式通配符匹配标准,这意味着在开发和发布版本期间执行这些测试,不会在提供 20 项(而非正确的 21 项)输入时导致内容解释器中出现潜在的越界读取。

CrowdStrike 为此创建了使用非通配符匹配标准对每个字段进行测试的自动流程,增加测试覆盖率。据悉,此步骤已经针对全部现有模板类型完成,并且成为一切未来模板类型的必要测试选项。

4. 内容验证器中包含逻辑错误

目前,内容验证器已经过修改,目前仅允许第 21 个字段中的通配符匹配条件,从而防止仅提供 20 个输入的传感器触发越界访问。此项修复将于 2024 年 8 月 19 日之前发布至生产环境。

5. 模板实例验证应进行扩展,以涵盖内容解释器内的测试

CrowdStrike 表示新发布的模板类型在多个方面均经过压力测试,然而,内容验证器测试的模板实例并未观察到当 IPC 模板类型被提供给内容解释器时会因输入数量不匹配而导致系统崩溃。为此,团队更新了内容配置系统的测试程序。

6. 模板实例应分阶段部署

CrowdStrike 的这一“发现”描述很少,他们直接给出了缓解措施:更新内容配置系统,增加了额外的部署层与验收检查,同时让客户控制对快速响应内容更新的部署。

其中,网友们对 CrowdStrike 在内核代码中使用正则表达式的做法非常震惊:“这是一个正则表达式!?!Crowdstrike 提交了一份长达 12 页的报告,只是为了说明他们的正则表达式通配符匹配失败并导致关键服务离线!”

“我还以为我是个糟糕的工程师呢,原来不只是我一个人有这个问题!”还有哭笑不得的网友说道,“在观看 Crowdstrike RCA 视频的过程中睡着了,因为其中 90% 都是废话(就像我写 RCA 的时候一样,哈哈),主要原因是:正则表达式。”

还有网友已经开始担心了:“Crowdstrike 开发人员更新了正则表达式并将其推送到生产版本。他们在内核级代码中使用正则表达式让我感到害怕。”

结束语

对于 CrowdStrike 的解释,网友们充满了嘲讽:“明确一点,CrowdStrike 针对通道文件 291 的测试和部署流程是基于一种可以成为‘希望与梦想’的算法运作的。明白了。”

还有网友犀利总结,“CrowdStrike:我们自己调查了一下,发现这其实是个小错误,不是大问题。都散了吧。”

“一想到你们‘保护’选举服务器,我就不寒而栗。”这次 CrowdStrike 算是痛失人心了。

CrowdStrike 在最后也大概解释了通道文件 291 中的新模板实例是如何导致系统崩溃的,感兴趣的读者可以查看:

https://www.crowdstrike.com/wp-content/uploads/2024/08/Channel-File-291-Incident-Root-Cause-Analysis-08.06.2024.pdf

参考链接:

https://www.crowdstrike.com/blog/channel-file-291-rca-available/

https://ebellani.github.io/blog/2024/analyzing-crowdstrike-s-root-cause-analysis-or-on-missing-the-point-about-quality/


推荐阅读  点击标题可跳转

1、C++20 std::format 替换 fmtlib 的关键点

2、Linux启动流程 梳理| 思维导图 | 流程图  | 值得收藏

3、“剑指 C/C++”,美国 CISA 等机构再发警告:Linux 中 95% 没用内存安全代码!

CPP开发者
我们在 Github 维护着 9000+ star 的C语言/C++开发资源。日常分享 C语言 和 C++ 开发相关技术文章,每篇文章都经过精心筛选,一篇文章讲透一个知识点,让读者读有所获~
 最新文章