所讨论的设备是任何MX500系列SSD。这些SSD由慧荣科技SM2259控制器控制(较老批次使用较旧的控制器慧荣科技SM2258,但本文档主要关注较新的型号)。
SM2259是一款4通道SATA 6Gb/s微控制器,搭载基于ARC架构的32位小端CPU。
通过观察截至本文档编写日期的最新固件M3CR046,发现并静态和动态确认了一些问题。
所有问题均出现在控制器的固件更新机制中,对应于微控制器对ATA PIO DOWNLOAD-MICROCODE (0x92)命令的处理程序,特别是使用偏移量方法下载固件的逻辑,对应子命令0x03和0x0E。
本文档涵盖的所有漏洞均已在Crucial MX500 500GB SSD(CT500MX500SSD1)、SM2259H-AC控制器、运行M3CR046固件、NY112闪存芯片上验证,使用搭载x86_64 CPU的PC。
固件代码映射到基地址0x80020000,易受攻击的ATA处理程序位于地址0x80024A9C。为了方便,反编译后的函数版本可在resources/download_microcode_handler.c中找到。
对于那些不愿处理技术细节而只想了解底线的人,请参阅下面的FAQ部分。
由于M3CR046包含多个固件映像,固件更新机制会根据实际使用的闪存芯片或其他硬件特性选择合适的映像,本文档将涵盖第一个固件变体的细节(因为该固件支持我们的特定驱动器,因此我们只能测试该固件变体)。然而,本文档中呈现的漏洞似乎适用于所有固件变体,但在复现时具体细节可能会有所不同。
此问题涉及第一个发送的数据块大小超过0x200扇区的情况。我们查看ATA命令处理程序内部,特别是当数据块大小大于扇区大小且是第一个发送的数据块时执行的逻辑:

这根据下一个偏移量(在本例中,由于我们目前只发送了一个数据块,因此是数据块长度的扇区数)和一个名为lower_bound_fw_offset的变量设置一些变量,该变量是输入下载映像中预期找到固件映像的块偏移量(即按扇区粒度的偏移量)。这是每个固件变体的硬编码值,在我们的例子(第一个变体)中,等于0。
在这种情况下,计算some_index的减法结果时会发生下溢,导致some_index高达0xFFFF。这是意外行为,因为根据将数据移动到下载缓冲区的逻辑:

我们观察到,复制数据的源地址在计算出的some_index值异常时可能无效。
当通过发送第一个数据块大小超过0x200扇区的固件更新请求进行动态测试时,控制器挂起,甚至不响应原始请求。这现象一致且易于复现。
很可能是因为对计算出的源地址的无效引用触发了异常,导致控制器挂起。这尚未得到证实,仅是一种可能解释挂起原因的猜想。
输入下载映像(对于M3CR046)大小为0x242400字节,该映像内部包含3个内部固件映像,固件更新过程后只有一个最终写入闪存,每个此类映像大小为0xC0C00字节(或0x606扇区)。
这意味着,当固件更新机制从输入下载映像中提取正确的固件副本时,必须验证其大小不超过0xC0C00字节。
控制器确实尝试这样做,但存在一些可能导致意外行为的边界情况。我们看看以下片段(与前一个漏洞共享部分代码):

如果当前数据块大小大于0x200扇区且不是序列中的第一个数据块,则每次将复制0x200扇区(0x40000字节)。然后,有一个检查,如果固件映像的总大小超过higher_bound_fw_offset(在我们的例子中是0x606扇区,因为固件大小应恰好为此),则截断要复制的字节数中的多余字节。
总体而言,此逻辑是合理的,但存在缺陷——如果发送的最后一个数据块导致下一个偏移量变得过高,以至于多余字节数超过0x200扇区(或0x40000字节),则curr_bytes_to_copy会得到一个“负”值,下溢到约~4GB (~0xFFFFFFFF)。如我们之前所见,此变量用于确定要传输到下载缓冲区的字节数。
如果我们查看r_maybe_some_efficient_data_transfer内部,会看到以下代码:

这意味着复制大小被截断为32MB(从原始的~4GB复制大小),但这仍然是一个很大的数字,如果起始于0x40000000的内存范围大小小于32MB,也可能导致未定义行为。
当通过发送ATA数据块使偏移量达到0x600,然后发送大小为0x207扇区的大数据块以触发下溢进行动态测试时,控制器再次挂起,很可能是因为复制过程中访问了无效内存。
此漏洞比前一个更有趣,因为即使我们没有受控的覆盖(而是可能触发异常导致控制器挂起的大覆盖),如果将数据移动到下载缓冲区的函数在实际崩溃前成功传输了那么多数据(覆盖主内存中紧接下载缓冲区之后的内存范围),那么异常处理程序的行为可能会根据被覆盖的数据而改变。这种情况可能发生,例如,如果异常处理程序从被覆盖区域读取指针并跳转到该指针(这种情况不太可能,但通过更多研究,可能会发现类似的东西)。
如前所述,下载映像的大小为0x242400(或0x1212扇区)。固件通过验证下一个偏移量不超过0x1212扇区来确保传输的映像总大小不超过此大小。此检查合理,但下一个偏移量的计算存在缺陷:

如果当前偏移量为0x600扇区,并且要处理的下一个ATA命令的大小足够大(比如0xFC00扇区,ATA标准允许此大小),则下一个偏移量会回绕,使得上述检查无法正常工作:

换句话说,通常固件更新机制会重置其状态机并返回错误,但如果我们发送了一个非常大的数据块,我们会继续处理它。 以下代码片段显示了传输是如何进行的:

此时我们回想一下,如果要传输的扇区数大于0x200扇区且当前数据块不是第一个,则每次复制0x200扇区到下载缓冲区。这非常有趣,因为这意味着我们可以在下载缓冲区之后复制大约0x200扇区(或0x40000字节)的数据,覆盖主内存中的数据。例如,如果当前偏移量为0x605扇区,我们提供的数据块大小为0xF9FB扇区,那么__next_offset由于回绕而变为0。复制开始的源索引为0,curr_bytes_to_copy得到值0x40000。由于我们当前处于偏移量0x605扇区,g_blocks_copied得到值0x605。由于当前偏移量确实有效(下一个也是),因此触发到下载缓冲区的复制操作,导致对下载缓冲区末尾之后略小于0x40000字节的大规模覆盖。
这是一个强大的原语,允许更可控的控制器缓冲区溢出(不像之前的情况那样立即崩溃控制器),并且可以比前一个漏洞更确定地导致代码执行(但仍需对主内存中下载缓冲区后面的内容进行更多研究以确定利用特征)。
所有这些漏洞均在Ubuntu 22.04 64位机器上通过标准Linux SCSI驱动(通过SG_IO接口)验证。需要指出的是,要使用此特定驱动复现漏洞#3,必须启用大页面并分配单个1GB页面用于大请求。原因在于,该驱动似乎要求整个ATA请求位于连续的物理内存块中。由于请求大小接近~30MB,2MB页面不够,因此1GB页面是测试系统上下一个(也是最后一个)可用大小。
但还需注意,这并不意味着这是触发该漏洞的必要步骤,因为可能还有其他我们尚未涵盖的发送大ATA请求的变通方法。启用大页面只是确认此漏洞的最快途径。除此之外,触发所有这些漏洞的唯一前提是拥有发送ATA数据包的必要权限(通常是与控制器通信的PC的root访问权限)。
复现上述所有漏洞的源代码作为此仓库的一部分提供。 对于漏洞#1和#2,预期行为是驱动器挂起,直到下一次上电循环。 对于漏洞#3,提供的源代码不一定使控制器崩溃,但确实对下载缓冲区之外进行了大规模覆盖。
如前所述,由于漏洞在Ubuntu 22.04 64位机器上验证,编译过程必须在类似机器上进行。不保证其他发行版或操作系统的兼容性。
要构建,在项目根目录中运行以下命令:
cmake -B build && make
构建过程生成3个二进制文件,均位于build目录中,名称分别为CVE_MX500_BUG_1、CVE_MX500_BUG_2和CVE_MX500_BUG_3,分别对应触发漏洞#1、#2和#3的源文件。
每个二进制文件期望接收MX500 SSD的设备路径,并且必须以root权限运行。例如:
sudo ./build/CVE_MX500_BUG1 /dev/sda
这取决于潜在攻击者的最终目标。如果他们只想要完全读写驱动器存储,那么进入你的PC就足够了。但是,如果攻击者想更进一步呢?如果驱动器的固件经过数字签名,那么漏洞#3可以使攻击者绕过固件的签名验证,从而将恶意载荷插入驱动器的固件中。一旦进入,这种载荷隐藏得很好,可以经受驱动器格式化,甚至可以确保在控制器固件更新后仍然存在。这种载荷实际上能做什么超出了本文档的范围,因此不作讨论。
答案很可能是一个大大的“不”。实际执行此类攻击所需的研发量非常高,并且(非常)可能只能由非常严重的威胁行为者实现。除非你是政府通缉的目标,否则这极不可能对你产生任何影响。
供应商在数月内对关于这些问题的多封邮件未予回应。要使CVE实际发布,必须向分配CVE的CNA提供公开链接。遗憾的是,私下发送信息并非此流程的工作方式。
本文档中提到的漏洞最初于2024年5月发现。自那时起,美光公司已多次联系(通过其官方安全电子邮件),但未得到回复。2024年7月通知了MITRE,2024年8月分配了CVE。2024年8月底(CVE获得MITRE批准几天后),此仓库公开。
由于比M3CR046更旧的M3CR04X固件已无法下载,因此不清楚它们是否受影响,但如果让我猜测,我会说是的。 对于更旧的版本,例如M3CR033,基于静态分析,似乎存在非常相似的漏洞。
所讨论的控制器SM2259也嵌入在其他供应商的SSD中。供应商可能会修改部分固件代码,但我认为这些漏洞(或非常相似的漏洞)也很可能出现在其他供应商的SSD中。
此CVE已由MITRE发布。NVD也已对其进行分析,CVSS 3.0评分为6.7(中等)。
如果您发现描述中存在不准确或错误,或者难以复现这些漏洞,请通过[email protected]与我联系。