这是 过去几个月我们在 Azure Functions 中发现 的第二个特权升级 (EoP) 漏洞。原文地址:https://www.intezer.com/blog/cloud-security/royal-flush-privilege-escalation-vulnerability-in-azure-functions/
资产过渡到云服务最常见的好处之一就是可以共同承担安全风险,但是云服务商也不能避免出现安全问题,例如:通用漏洞或者错误配置。这是过去几个月我们在 Azure Functions 中发现 的第二个特权升级 (EoP) 漏洞。
漏洞有时候是未知的或者是超出云消费者的控制,所以建议使用双保险的方式来夯实云安全:
- 做好基础工作:例如及时修复已批漏的漏洞,从而来降低被攻击的可能性。
- 实施运行监控:当云服务被攻击时,可以通过检查响应以确定攻击方式或是其他内存攻击操作。
披漏 Azure Functions 容器中的漏洞
Azure Functions容器运行时会带有 –privileged Docker 的标识,这便造成在/dev目录下的设备文件在容器主机和容器来宾之间被共享,这是标准的特权容器行为,但是,这些设备文件对“其他”具有“rw”权限,如下所示,这是我们提出的漏洞的根本原因。
Azure Functions容器赋予用户的是低权限运行。容器的主机名包含单词Sandbox,这意味着:给用户赋予低权限是很重要的。容器运行时会带有 –privileged Docker 的标识,这意味着如果用户能够升级到 root,他们将能够使用各种 Docker 转义技术逃逸到Docker 主机。
设备文件的可访问权限不是标准行为。从我自己的本地特权容器设置中可以看出,/dev 中的设备文件默认情况下不可随意访问:
Azure Functions 环境包含 52 个带有 ext4 文件系统的“pmem”分区。起初,我们怀疑这些分区属于其他 Azure Functions 客户端,但进一步评估表明,这些分区只是同一操作系统使用的普通文件系统,包括 pmem0,它是 Docker 主机的文件系统。
为了进一步研究如何在不影响其他 Azure 客户的情况下利用此可写磁盘,我们在自己的容器中设置了一个本地环境来模仿该漏洞,以及非特权用户“bob”:
利用设备文件 o+rw
在我们的本地设置中,/dev/sda5 是根文件系统,它将是我们的目标。
正如我们上面成功演示的那样,攻击者可以使用debugfs实用程序遍历文件系统。debugfs还通过-w标志 支持写入模式 ,因此我们可以将更改提交到底层磁盘。请务必注意,写入已安装的磁盘通常不是一个好主意,因为它可能导致磁盘损坏。
通过直接文件系统编辑进行利用
为了演示攻击者如何更改任意文件,我们想要控制/etc/passwd。起初,我们尝试使用zap_block 命令直接编辑文件系统块的内容来编辑文件的内容。在内部,Linux 内核将这些更改处理为 *设备文件 * /dev/sda5 ,并将它们写入缓存在与 *常规文件 * /etc/passwd更改不同的位置。因此,需要将更改刷新到磁盘,但此刷新由 debugfs 实用程序处理。
同样,Linux 内核托管一个读取缓存页面,该页面为最近加载到内存中的页面。
不幸的是,由于我们在写入缓存中解释的相同约束,对/dev/sda5的更改不会传播到/etc/passwd 文件的视图,直到它的缓存页面被丢弃。这意味着,我们只能覆盖最近未从磁盘加载到内存的文件,或者等待系统重新启动以应用我们的更改。
皇家同花顺
经过进一步研究,我们能够找到一种方法来指示内核丢弃读取缓存,以便我们的zap_block 更改可以生效。首先,我们通过debugfs创建了一个硬链接 到我们容器的diff 目录,以便更改会辐射到我们的容器:
这个硬链接仍然需要root权限才能编辑,所以我们仍然必须使用zap_block来编辑它的内容。然后我们使用posix_fadvise 指示内核从读取缓存中丢弃页面,灵感来自一个名为 pagecache management 的项目。这导致内核加载我们的更改,我们终于能够将它们传播到 Docker 主机文件系统:
总结
通过编辑属于 Docker 主机的任意文件,攻击者可以 通过类似地更改/etc/ld.so.preload并通过容器的diff 目录提供恶意共享对象来发起预加载劫持。该文件可以预加载到 Docker 主机系统中的每个进程中(我们之前使用这种技术记录了 HiddenWasp 恶意软件),因此攻击者将能够在 Docker 主机上执行恶意代码。
总结一下这个漏洞的 PoC 是: