ELFs Fall into the Dump

The newest hole when I was writing this chapter was the vulnerability in the ELF loader, which was detected on May 11, 2005. It is typical for the entire range of kernels : 2.2.27-rc2, 2.4, 2.4.31-prl, 2.6, 2.6.12-rc4, etc.

Here the error is with the elf_core_dump () function in the binfmt_elf. c file. The key fragment of the vulnerable listing appears as shown in Listing 14.2.

Listing 14.2: Key fragment of the elf_core_dump() function vulnerable to overflow
image from book
 static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) {           struct elf_prpsinfo psinfo; /* NT_PRPSINFO */          /* First copy the parameters from user space  */  memset(&psinfo, 0, sizeof(psinfo));          {                  int i, len;             /* 1 */                  len = current->=->arg_end - current->=->arg_start;                  if (len >= ELF_PRARGSZ) / * 2 * /                          len  =  ELF_PRARGSZ - 1;                          copy_from_user(&psinfo.pr_psargs,/* 1167 */                          (const char *)current->mm->arg_start, len);          ...          { ... { 
image from book
 

This is typical buffer overflow. The programmer declares the signed len variable (see /* 1 */ ), and some time later passes it to the copy_from_user function, which copies the data from the user memory into the kernel dump. The check for a negative value is not carried out (see /* 2 */). What does this mean? If current->=->arg_start is greater than current->=->arg_end, then a large region of the user memory space will be copied into the kernel.

How is it possible to achieve this? Analysis has shown that the current->=->arg_start and current->=->arg_end variables are initialized in the create_elf_tables function (Listing 14.3). Therefore, if the strnlen_user function returns an error, then only the current->=->arg_start variable is initialized and current->=->arg_end retains its value inherited from the previous file.

Listing 14.3: Key fragment of the create_elf_tables function
image from book
 static elf_addr_t * create_elf_tables(char *p, int argc, int envc,         struct elfhdr * exec,         unsigned long load_addr,         unsigned long load_bias,         unsigned long interp_load_addr, int ibcs)         {                 current->mm->arg_start = (unsigned long) p;                 while (argc-->0)                 {                         __put_user((elf_caddr_t)(unsigned long)p, arg++);                         len = strnlen_user (p, PAGE_SIZE*MAX_ARG_PAGES);                         if (!len   len >  PAGE_SIZE*MAX_ARG_PAGES)  return NULL; /* * */  p += len;                 }                 __put_user (N[ILL, argv) ;                 current->=>arg end- - current->mm->env_start = (unsigned long) p; ...         } 
image from book
 

Now it only remains tweak the strnlen_user function by placing both variables into the section of the ELF file that has been protected against access (PROT_NONE) . After that, an attempt at accessing that section will cause an exception. To create the core dump, the kernel would create the core_dump function, which, in turn , will call elf_core_dump . Overflow will take place at that point. Overwriting the core area opens practically unlimited possibilities for the hacker, because shellcode is executed in ring 0.

An example of this exploit can be found at http://www.isec.pl/vuhierabilities/isec-0023-coredump.txt .



Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net