CSE 5380:信息安全论文 CVE-2022-0847(脏管道)
作者
Karan Vasudevamurthy (UTA ID: 1002164438)
什么是 CVE?
通用漏洞与暴露(CVE)是一个公开披露的信息安全漏洞和暴露的列表。MITRE 公司于 1999 年引入 CVE,用于识别和分类软件和固件中的漏洞。MITRE 是一家非营利组织,在美国运营由联邦资助的研究与开发中心。CVE 旨在促进关于已知漏洞的信息共享,以便网络安全计划能够更新以反映最新的安全问题和弱点。为此,CVE 为每个漏洞或暴露分配一个唯一标识符。这些标识符也称为 CVE 名称或 CVE 编号。通用漏洞评分系统(CVSS)是一套开放标准,用于为漏洞分配数字以评估其严重性。CVSS 评分的范围是 0.0 到 10.0。数字越大,安全严重程度越高。每个 CVE ID 的格式为 CVE-YYYY-NNNNN。YYYY 部分是指定 CVE ID 的年份或漏洞公开的年份。
什么是管道?
在 CVE-2022-0847 的背景下,理解管道的内部工作原理至关重要,特别是与管道缓冲区相关的属性。Linux 中的管道有助于在进程之间传输数据,一个进程的输出成为另一个进程的输入。这种机制促进了系统上运行的不同进程之间的通信和协调。Linux 中的管道是单向的,意味着数据只能朝一个方向流动。管道缓冲区通常由一个固定大小的先进先出(FIFO)数据结构组成,临时保存正在进程之间传输的数据。当一个进程向管道写入数据时,数据存储在缓冲区中,直到另一个进程读取它。数据被读取后,会从缓冲区中移除,从而允许写入新数据。
漏洞
对于 CVE-2022-0847,理解管道缓冲区中的两个函数非常重要:
copy_page_to_iter_pipe:此函数负责将数据从页复制到与管道缓冲区关联的迭代器。在通过管道进行进程间通信的上下文中,当一个进程向管道写入数据时,需要将数据复制到管道缓冲区,以便另一个进程可以读取。copy_page_to_iter_pipe 函数促进了这一复制过程,确保数据在进程之间正确且高效地传输。在此函数中,使用 "flags" 参数来指定或控制与复制过程相关的某些属性或行为。这些标志可能包括是否执行额外的检查或验证、如何处理特定类型的数据,或是否应用优化以提高效率。push_pipe:push_pipe 函数涉及将数据推入管道缓冲区。当一个进程向管道写入数据时,数据需要插入到管道缓冲区中,然后其他进程才能读取。push_pipe 函数负责处理此插入过程,确保数据正确放入缓冲区并可供其他进程读取。Max Kellermann 发现 Linux 内核错误地处理了 Unix 管道。该漏洞源于 copy_page_to_iter_pipe 和 push_pipe 函数中某些属性(特别是 "flags" 参数)的初始化不充分。这一疏忽导致标志可能被分配过时或不正确的值,从而可能危及系统的安全性和完整性。一个非特权本地用户可以利用此缺陷向由只读文件支持的页面缓存中的页写入数据,从而提升其在系统上的权限。
攻击方法
该漏洞类似于 CVE-2016-5195 "Dirty Cow",但更易于利用。利用 CVE-2022-0847 需要本地访问目标系统,并且影响 Linux 内核版本 5.8 及更新版本。由于缺乏正确初始化,我们可以创建新管道缓冲区,其 PIPE_BUF_FLAG_CAN_MERGE 标志被错误设置。此标志控制对管道缓冲区写入的合并,从而允许写入已拼接进管道中的现有页。如果文件允许这种拼接页,则修改将在内存中文件共享的系统级视图中可见。任何后续的缓存刷新将忽略当前的 Linux 权限设置,并将修改后的数据复制到磁盘。这将使低权限用户能够更改文件(无论是磁盘上还是内存中)的特定内容,即使该文件仅受只读访问控制(如 SELinux、标准 Linux 权限、高级访问控制和不可变文件)保护。因此,我们可以假设攻击者是任何具有基本 Linux 系统知识并能够执行恶意代码的低权限本地用户。这样的个人可以提升其权限并可能危及整个系统,构成重大的安全风险。
概念验证
下面是我在运行 Linux 的虚拟机上利用 CVE-2022-0847 所遵循的步骤。
检查您的 Linux 发行版是否可被利用
任何内核版本高于 5.8 的 Linux 都会受到影响。但是,版本 5.16.11、5.15.25 和 5.10.102 无法利用 CVE-2022-0847。要查找您的内核版本,只需运行 *uname -r*。如果您不确定目标系统是否存在漏洞,也可以运行这个 bash 脚本。
下载正确的 Linux 内核
为了演示,我决定使用 Ubuntu 20.04.1 LTS。但是,此版本的 Ubuntu 目前运行在 Linux 内核 5.15 上,CVE-2022-0847 无法在此内核版本上利用。要下载 Linux 内核 5.8,只需运行 *sudo apt install linux-image-5.8.0-63-generic linux-headers-5.8.0-63-generic*
下载漏洞利用程序
漏洞利用代码可以在 GitHub 上找到。它演示了如何覆盖页面缓存中的任何文件内容,即使文件不允许写入、是不可变的或位于只读挂载点上。您也可以在终端中运行 *git clone https://github.com/karanlvm/Infosec.git。
复制原始的 passwd 文件
我们可以运行 *cp /etc/passwd /tmp/passwd.bak*。这将帮助我们识别运行漏洞利用前后 passwd 文件的差异。
编译漏洞利用程序
要成功编译漏洞利用程序,您需要安装 GCC。您可以使用 *sudo apt-get install gcc* 来安装 GCC。要编译漏洞利用程序,可以运行 *gcc exp.c -o exp*。
运行漏洞利用程序
要运行漏洞利用程序,需要提供的参数是只读文件、偏移量以及将要插入的一些字符。在本例中,我们将运行 *./exp /etc/passwd 1 ootz:*。如果您看到输出 “It worked !”,则表明我们已成功利用 Dirty Pipe 漏洞,现在可以在没有密码的情况下获得 root 访问权限。
限制
此漏洞利用有两个主要限制:
当前状态与修复
截至 2024-01-12,未来 30 天内利用活动的概率为 7.58%(利用预测评分系统 (EPSS))。以下是 CVE-2022-0487 的 CVSS(通用漏洞评分系统):
此漏洞可以在任何内核版本高于 5.8 的 Linux 上利用。然而,该漏洞已在 Linux 5.16.11、5.15.25 和 5.10.102 中修复。因此,我们只需应用 Linux 发行版维护者提供的补丁或更新即可修复该漏洞。为此,我们可以直接运行以下命令:*sudo apt update* 和 *sudo apt upgrade*。
参考文献
切换到 root 访问权限
现在,我们可以直接运行 *su rootz*,应该可以获得 root 访问权限。为了确认,我们可以运行 id 命令。