跳转到帖子

Linux Dirty Pipe(CVE-2022-0847)权限边界绕过的验证、留痕与修复

精选回复

发布于

背景

CVE-2022-0847,通常称为 Dirty Pipe,是 Linux 内核管道缓冲区处理缺陷。攻击者在已获得本地低权限账户或受限服务执行权限后,可能绕过文件系统的只读权限,通过页缓存覆盖可读文件的部分内容,进一步修改认证配置、替换可执行文件或突破容器权限边界。

该漏洞适合归入漏洞库,而不是作为通用提权教程:实际排查重点应放在受影响内核识别、安全验证、权限边界分析、日志留痕和补丁闭环。以下步骤仅用于已授权主机,不提供针对系统关键文件的利用代码。

问题定位

Dirty Pipe 影响 Linux 5.8 之后的部分内核,主线修复版本包括 5.16.11、5.15.25 和 5.10.102。仅比较 uname 输出并不完全可靠,因为 Debian、Ubuntu、RHEL 等发行版可能将修复补丁回移到较低版本内核。

先收集正在运行的内核、发行版和已安装内核包:

uname -a
cat /etc/os-release

# Debian、Ubuntu
dpkg-query -W 'linux-image*' 2>/dev/null | grep "$(uname -r)"

# RHEL、CentOS、Rocky、AlmaLinux
rpm -q kernel-core 2>/dev/null
rpm -q --changelog kernel-core 2>/dev/null | grep -i -E 'CVE-2022-0847|dirty pipe'

# SUSE
rpm -q kernel-default 2>/dev/null

# 检查是否存在“已安装新内核但尚未重启”的情况
printf 'running: %s\n' "$(uname -r)"
ls -1 /boot/vmlinuz-* 2>/dev/null

判断时应以发行版安全公告和软件包修订号为准。常见误区是补丁包已经安装,但业务主机仍运行旧内核;这种情况下漏洞并未真正完成修复。

技术分析

漏洞核心位于匿名管道的 pipe_buffer 标志处理。特定操作可使 PIPE_BUF_FLAG_CAN_MERGE 状态残留,随后写入管道的数据可能被合并到引用文件页缓存的缓冲区中。

这意味着攻击者不需要以常规 write 系统调用打开目标文件进行写入。只要对文件具有读取权限,并满足偏移限制,就可能改变页缓存中的数据。受影响场景通常具有以下特征:

  • 攻击者已经能够在主机或容器中执行本地代码。
  • 目标文件对攻击者可读,但正常权限不允许写入。
  • 覆盖位置不能位于页边界,单次覆盖不能跨越页面边界。
  • 不能借此直接扩大文件长度,只能覆盖文件已有内容。
  • 修改可能先体现在页缓存中,传统文件写入审计不一定完整记录。

在实际攻防链路中,该漏洞通常不是初始入口,而是低权限命令执行之后的权限提升环节。例如 Web 服务账户被文件上传漏洞控制后,攻击者可能尝试覆盖被高权限进程读取的配置文件或可执行文件,最终从 www-data、nginx 等账户提升到 root。

安全验证步骤

生产环境不建议直接运行公开提权 PoC。更稳妥的方法是先通过补丁状态、内核构建信息和隔离测试机完成验证。

  • 记录 uname -r,并确认当前启动内核对应的软件包版本。
  • 查询发行版安全公告,确认该软件包是否包含 CVE-2022-0847 回移补丁。
  • 检查近期是否安装过内核更新但未重启。
  • 复制相同镜像到隔离环境,以普通账户对临时文件进行非破坏性验证。
  • 验证前后计算关键文件哈希,避免把系统关键文件作为测试目标。

可使用以下命令建立基线。该过程不会触发漏洞,只用于核对系统状态和发现异常变更:

mkdir -p /tmp/cve-2022-0847-check
printf 'AUTHORIZED-LAB-TEST-0001\n' > /tmp/cve-2022-0847-check/sample.txt
chmod 0444 /tmp/cve-2022-0847-check/sample.txt

stat /tmp/cve-2022-0847-check/sample.txt
sha256sum /tmp/cve-2022-0847-check/sample.txt

# 对高价值文件建立只读基线,禁止在生产环境修改这些文件
sha256sum /etc/passwd /etc/sudoers /usr/bin/su /usr/bin/sudo 2>/dev/null

# 检查关键文件的软件包完整性
rpm -Va 2>/dev/null | grep -E '/(sudo|su|passwd)$' || true
dpkg -V sudo login passwd 2>/dev/null || true

若必须运行验证程序,应限定在快照可回滚的测试机内,使用普通账户和专用临时文件,并在测试后重启主机以清除可能残留的页缓存影响。

日志与入侵排查

Dirty Pipe 对页缓存的修改不一定表现为目标文件的常规写入,因此只给 /etc/passwd 配置 audit 写监控并不足以证明主机未被利用。排查应结合进程执行记录、文件完整性、提权行为和后续持久化痕迹。

可以先检查关键文件元数据及账户变化:

# 关键文件时间与权限
stat /etc/passwd /etc/shadow /etc/sudoers /etc/ld.so.preload 2>/dev/null

# UID 0 账户
awk -F: '$3 == 0 {print $1, $3, $6, $7}' /etc/passwd

# 最近新增或修改的提权配置
find /etc/sudoers.d /etc/systemd/system /etc/cron.d \
  -xdev -type f -mtime -7 -ls 2>/dev/null

# SUID/SGID 文件变化,建议与历史基线比较
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) \
  -printf '%m %u %g %TY-%Tm-%TdT%TH:%TM:%TS %p\n' 2>/dev/null

# Debian、Ubuntu 登录与 sudo 记录
zgrep -h -E 'sudo:|session opened|authentication failure' \
  /var/log/auth.log* 2>/dev/null | tail -n 200

# RHEL 系列
zgrep -h -E 'sudo:|session opened|authentication failure' \
  /var/log/secure* 2>/dev/null | tail -n 200

# systemd 日志中的异常提权和账户操作
journalctl --since '-7 days' --no-pager | \
  grep -E 'sudo|su:|useradd|usermod|passwd|setuid' | tail -n 200

如果主机部署了 auditd,可增加面向后续行为的监控。规则重点应是认证文件、sudo 配置、动态链接器配置和持久化目录,而不是只监控单一漏洞特征:

auditctl -w /etc/passwd -p wa -k identity_change
auditctl -w /etc/shadow -p wa -k identity_change
auditctl -w /etc/sudoers -p wa -k sudoers_change
auditctl -w /etc/sudoers.d -p wa -k sudoers_change
auditctl -w /etc/ld.so.preload -p wa -k linker_hijack
auditctl -w /etc/systemd/system -p wa -k persistence_change
auditctl -w /etc/cron.d -p wa -k persistence_change

ausearch -k identity_change -i
ausearch -k sudoers_change -i
ausearch -k linker_hijack -i

上述规则主要捕获攻击后的落地操作。若需要识别 splice、管道和异常进程链,应在测试环境使用 eBPF 或 EDR 采集系统调用上下文,并关联执行用户、父进程、容器 ID、命令行和文件哈希。单纯记录 splice 调用会产生较多噪声,不宜直接作为高置信告警。

容器与权限边界

容器内核由宿主机共享,因此判断是否受影响时必须检查宿主机正在运行的内核,而不是只查看容器镜像中的软件包。即使容器使用只读根文件系统,内核缺陷仍可能破坏原本依赖文件权限建立的隔离假设。

检查对象重点
宿主机当前运行内核是否包含修复补丁
容器账户是否以 root 运行,是否保留不必要能力
挂载是否挂载宿主机敏感目录、Docker Socket 或运行时 Socket
安全策略是否启用 seccomp、AppArmor 或 SELinux
监控是否能够关联宿主机进程、容器 ID 和镜像摘要

容器内 root 不等同于宿主机 root,但特权容器、hostPID、hostPath 敏感挂载以及过量 capabilities 会显著放大漏洞影响。修复内核之前,不应把容器隔离作为主要缓解措施。

风险与修复建议

  • 安装发行版提供的安全内核,并确认软件包明确修复 CVE-2022-0847。
  • 完成维护重启,使用 uname -r 验证新内核已经实际运行。
  • 清点所有共享同一宿主机内核的容器和工作负载,不要只修复容器镜像。
  • 限制低权限账户、编译器和任意代码执行环境,减少漏洞利用前提。
  • 移除容器的 privileged、SYS_ADMIN 等非必要权限,禁止暴露运行时 Socket。
  • 对认证文件、sudo 配置、SUID 文件、系统服务和计划任务执行完整性核查。
  • 若已发现异常覆盖或权限提升迹象,应隔离主机并从可信镜像重建,不要只恢复单个文件。

临时缓解措施无法等价替代内核升级。文件权限、只读挂载和常规访问控制正是该漏洞可能绕过的边界,真正有效的处置方式是安装修复内核并重启。

总结

Dirty Pipe 的危险点不只是“本地提权”,而是它绕开了传统文件写权限和部分文件审计假设。漏洞验证应先确认发行版补丁状态,再在隔离环境使用普通账户和临时文件测试;事件排查则需要结合文件完整性、进程链、账户变化及持久化痕迹。完成内核升级后,还应确认实际启动版本,并对关键权限边界进行一次完整复核。

漏洞验证与修复流程示意图
漏洞成因、验证条件与修复闭环示意
代码审计与漏洞定位示意图
代码审计、调用链与关键函数定位示意

这类问题建议把“内核是否受影响”和“是否发生过利用”分开验证。只看 uname -r 容易误判:发行版可能回补补丁但保留原版本号,应以发行版安全公告和已安装内核包的修订号为准。

uname -r
cat /etc/os-release

# Debian / Ubuntu
dpkg-query -W 'linux-image*' 2>/dev/null | grep -v '^linux-image.*(none)'

# RHEL 系
rpm -q kernel

修复后确认当前运行的内核确实是已修补版本;仅安装新内核但未重启,运行中的旧内核仍可能受影响。维护窗口内更新并重启,再核对 uname -r。上游修复版本可作为参考(5.16.11、5.15.25、5.10.102),但最终以对应发行版公告为准。

留痕方面,Dirty Pipe 是本地提权,单靠常规登录日志未必能确认。可先保全认证日志、审计日志和进程执行记录,重点查看异常提权、可疑二进制及时间线;若此前没有启用进程审计,事后通常无法补出完整执行链。

# 查找近期新增的 setuid 文件,结合基线核验,避免只凭结果判定入侵
find / -xdev -type f -perm -4000 -printf '%TY-%Tm-%Td %TH:%TM %u:%g %m %p\n' 2>/dev/null

# 查看近期认证记录(路径依发行版而异)
journalctl --since "7 days ago" | grep -Ei 'sudo|su:|session opened|authentication failure'

这些检查只能提供线索,不是 Dirty Pipe 的利用证明。若发现异常文件或提权记录,先保留镜像、日志和文件元数据,再隔离主机并按事件响应流程处理;不要为了“验证漏洞”在生产机上运行公开提权 PoC。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。