CVE-2020-25860 -在RAUC嵌入式固件更新框架中发现重大漏洞

在RAUC嵌入式固件更新框架中发现漏洞

JFrog的安全研究团队(前身为Vdoo)不断研究领先的嵌入式设备及其供应链。作为这项研究的一部分,我们发现了CVE-2020-25860,这是一个潜在的关键漏洞,在鲁棒自动更新控制器中具有CVSSv3 8.8分(RAUC)的开源框架固件更新。JFrog负责任地披露了该漏洞,并与供应商Pengutronix密切合作,验证该漏洞的修复。penguin tronix已经通知客户,并发布了一份安全咨询在官方GitHub存储库上。此漏洞存在于RAUC的所有版本中,直到包含补丁的1.5版本。

此漏洞为“检查时间-使用时间”(cwe - 367)问题,该问题允许攻击者访问固件更新文件,在验证后(但在安装完成之前)覆盖它,从而允许安装任意固件更新,绕过加密签名检查机制。

此漏洞的影响

与供应链漏洞一样,很难准确估计有多少设备受到了影响。考虑到这是一个开源工具,并且可以由许多与供应商没有关系的不同公司使用,这种估计甚至更加复杂。因此,Pengutronix可以根据他们的客户来证明它的流行程度,他们估计在该领域有多达10万台设备,但我们相信这个数字要高得多,因为RAUC提供了大多数设备所需的核心功能。我们已经在工业、智能建筑和医疗等多个垂直领域的几种不同设备中看到了RAUC的应用。正如我们将在下面详细说明的那样,此漏洞也需要某些条件才能被利用,特别是远程利用。我们已经在至少一个真实世界的设备中看到了这些条件。然而,目前,据我们所知,这个漏洞没有在现场被利用,因此,没有导致任何具体的隐私侵犯或安全威胁任何人使用RAUC。

RAUC的背景

RAUC是一个始于2015年的项目,是为基于linux的嵌入式设备执行故障安全安全映像更新的轻量级工具。

RAUC允许嵌入式Linux开发人员在他们的嵌入式设备上集成一个健壮的更新客户端,只需最少的工作,同时避免编写任何样板更新代码。RAUC框架支持许多常用的引导加载程序(U-Boot、grub等)和开箱即用的存储技术(ext4、UBIFS等),因此它试图尽可能接近嵌入式设备固件更新的“交钥匙”解决方案。

RAUC的主要特性是安全性(原子性、故障安全更新操作)、安全性(加密签名检查)和可定制性(在安装过程中添加用户挂钩)。

技术深潜

RAUC使用捆绑文件作为保存新固件的存档。我们发现在固件升级过程中,这个文件可以被攻击者替换(在初始验证步骤之后),通过这样做,恶意固件将被安装,有效地允许攻击者控制系统。

运行时安装bundle.raucbRAUC运行以下内部函数:

  1. Check_bundle()—使用openssl库调用验证bundle
  2. Mount_bundle() -使用“mount”shell调用挂载包

在这些步骤之后,将提取挂载的包并覆盖当前固件。

关键的问题是,一旦check_bundle()完成运行,bundle文件就会关闭,验证过的数据不会以任何方式保留。

当mount_bundle()开始运行时,挂载shell调用导致重新读取bundle数据:

gboolean mount_bundle(RaucBundle *bundle, GError **error){…g_message(" mount bundle '%s' to '%s'", bundle->path, mount_point);Res = r_mount_loop(bundle->path, mount_point, bundle->size,…gboolean r_mount_full(const gchar* source, const gchar* mountpoint, const gchar* type, goffset size, const gchar* extra_options, GError **error){…如果(getuid () ! = 0) {g_ptr_array_add (args, g_strdup(“sudo”));g_ptr_array_add (args, g_strdup(”——非交互式“));} g_ptr_array_add(args, g_strdup("mount"));...g_ptr_array_add (args, g_strdup(源));... sproc = r_subprocess_newv(args, G_SUBPROCESS_FLAGS_NONE, &ierror); ...

因此,攻击者可以在调用check_bundle()和mount_bundle()之间切换bundle文件。这使得攻击者可以部署任意恶意固件,基本上在设备上提供根权限:

攻击流

图1:攻击流程,当进程到达mount_bundle()时,攻击者可以替换bundle文件,因此RAUC将挂载未经授权的bundle

赢得竞争条件(在check/mount bundle调用之间替换bundle文件)的几率非常高,因为在这两个操作之间有大量不可忽略的代码,包括shell调用(“mount”命令),这是一个非常慢的操作。

观察到的远程攻击场景

尽管在大多数情况下,我们认为该漏洞将被利用为本地特权升级,但我们已经观察到一个现实场景,该漏洞被远程攻击者利用,同时利用了一组默认硬编码的凭据。

目标设备使用一组默认的硬编码凭据(用户名和密码设置为“admin”),在首次登录时不需要更改这些凭据。

能够访问设备固件的攻击者可以很容易地提取这些凭据,或者通过简单的暴力攻击来猜测。

看看设备的攻击面:

  1. 目标设备公开了一个已验证的CGI端点upload.cgi允许任意文件上传到硬编码的文件路径-/ tmp / rauc / bundle.raucb
  2. 目标设备公开了一个已验证的CGI端点install.cgi哪个运行了硬编码的shell命令—rauc install /tmp/rauc/bundle.raucb . zip
  3. 在两个CGI端点之间没有适当的锁定机制

在这种情况下,攻击者可以远程接管设备,只需调用:

  1. upload.cgi使用正确签名的固件
  2. install.cgi
  3. (很快)upload.cgi使用恶意固件

观察到的远程攻击场景

本地攻击场景和PoC

假设本地用户拥有调用RAUC的特权(例如,通过只允许RAUC命令的sudo配置),但没有签名RAUC包所需的私钥,那么利用是微不足道的:

复制一个正确签名的固件到某个路径,例如:。/ bundle.raucb

调用RAUC -Sudo rauc install ./bundle.raucb

迅速取代。/ bundle.raucb使用恶意固件

如果本地用户不能调用RAUC命令,假设调用RAUC命令的特权用户使用的路径可以被攻击者写入,也可以利用这种场景。

我们已经开发了一个概念证明,利用这个确切的场景:

  1. PoC接受要替换的包文件的完整路径
  2. PoC等待另一个用户运行rauc安装通过监视默认目录(/ mnt / rauc),在验证步骤之后但在挂载步骤之前创建
  3. 一旦验证结束(创建目录),PoC就会用任意输入覆盖bundle文件

在真实的攻击场景中,攻击的bundle文件可以移动到经过正确签名的bundle文件之上(这比在正确的位置写入新文件要快)。

作为设备供应商,我如何知道我的设备是否受到此漏洞的影响?

您可以通过在设备上运行此命令来检查您的RAUC版本是否容易受到攻击

rauc——版本

如果报告的版本低于1.5,则您的设备包含易受攻击的代码。

实际上,只有当本地或远程攻击者有可能在安装包文件时修改包文件时,设备才容易受到攻击。

这可能发生,例如,在以下情况下:

  1. 非特权用户可以调用rauc命令,可以通过sudo机制、setuid机制或任何其他专有机制。示例中的下面一行/etc/sudoers文件将允许“vdoo”用户作为根用户调用RAUC:
    vdoo ALL=(root) /usr/bin/ raauc
  2. rauc安装在任何时候使用可以由非特权用户修改的包路径调用。例如:
    /usr/bin/rauc安装/tmp/mybundle.raucb
    由于/tmp默认情况下是全球可写的,通常任何用户都可以修改它下面的文件。

作为资产所有者,我如何知道我部署的任何设备是否容易受到攻击?

不幸的是,似乎很难判断这个漏洞是否存在,更重要的是,它只适用于网络工具,而不实际查看设备代码。

话虽如此,如果你的设备供应商确实为设备提供了软件物料清单(SBOM),请查看是否使用了RAUC,如果是的话,理论上你很可能是易受攻击的(除非版本明确列为1.5),因为存在易受攻击的代码。

但这并不意味着该漏洞是可以利用的(参见上面的详细信息)。如果设备供应商没有提供软件物料清单(SBOM),我们认为您应该要求他们提供一份关于此漏洞适用性的明确答复。

如何升级RAUC?

请使用此链接查看RAUC 1.5版本集成到基于Yocto/OE、ptxdist和builroot -的现有项目中的示例

https://github.com/rauc/rauc-1.5-integration/

您还可以按照以下说明编译最新版本的RAUC:

https://github.com/RAUC/RAUC#building-from-sources

如果无法升级RAUC,如何降低风险?

如上所述,这是一个典型的time -of- check -of- use漏洞,其中攻击利用了一个非原子操作,该操作涉及对资源和资源使用的检查。在本例中,检查是签名检查,用法是挂载/升级操作。

通过确保安装是原子的并且从安全路径进行,可以减轻攻击。

在运行之前rauc安装,将bundle文件从全局可写位置复制到安全位置(仅根用户可写),并从该路径运行安装。使用安全位置的存在作为锁定机制。这将确保没有特权的用户(本地或远程)可以干涉安装过程。

这可以用这个示例shell脚本完成:

#假设固件被上传到/tmp/uploads/bundle.bin #假设/data/fw_upgrade只能被root用户写入[!]-e /data/fw_upgrade/bundle.bin];cp /tmp/uploads/bundle.bin /data/fw_upgrade/bundle.bin /usr/bin/rauc install /data/fw_upgrade/bundle.bin rm /data/fw_upgrade/bundle.bin fi .bin

请注意,在使用像Yocto这样的构建系统时,更改安装脚本可能并不比切换到固定的RAUC版本容易得多。有关如何升级的详细信息,请参见下面。有关更多缓解措施的详细信息,请参阅官方咨询

鸣谢

我们要感谢企鹅团队高效而迅速地处理了这个安全问题,以及他们专业的沟通行为。我们高度重视他们的行为,他们应该在负责任的披露过程中为任何供应商的行为树立榜样。

问题吗?想法吗?如有任何问题,请通过research@www.si-fil.com与我们联系安全漏洞

除了发现和负责任地披露漏洞作为我们日常活动的一部分外,JFrog安全研究团队还致力于增强软件安全性,使组织能够通过自动化安全分析发现漏洞。有关JFrog DevOps平台安全特性的更多信息和更新-点击这里