SSH 私钥裸奔漏洞曝光!你的服务器可能正在被偷密钥

📅 2026年05月19日 · 技术

🔥 核心漏洞:Linux 内核「空 MM」窗口期,SSH 私钥直接裸奔

2026 年 5 月 14 日,Linus Torvalds 亲自修复了一个潜伏长达 六年 的内核漏洞(CVE-2026-46333)。这个漏洞允许一个无特权本地用户利用内核在执行 do_exit() 时的竞争窗口,通过 pidfd_getfd(2) 系统调用读取其他进程中以 0600 权限打开的敏感文件——包括 SSH 主机私钥/etc/shadow

⚠️ 严重程度:CVSS 评分 7.8(高危)。受影响系统包括 Ubuntu 22.04/24.04/26.04、Debian 13、CentOS 9、Raspberry Pi OS、Arch Linux 等几乎所有主流 Linux 发行版。

📌 漏洞原理深度解析

1. 内核函数调用顺序的「时间差」

当一个进程调用 exit() 时,内核的 do_exit() 函数按以下顺序执行清理工作:

  1. exit_mm() → 释放内存描述符(mm_struct),将 task->mm 设为 NULL
  2. (其他清理步骤)
  3. exit_files() → 关闭所有文件描述符

问题出在 第 1 步和第 3 步之间:此时进程已经没有内存描述符了,但它的文件描述符(fd)仍然存在,且保持打开状态。

2. __ptrace_may_access() 的遗漏检查

内核中的 __ptrace_may_access() 函数负责检查一个进程是否有权限访问另一个进程。正常情况下,如果目标进程设置了 dumpable 标志为 0(即不转储),则非 root 用户不能访问其文件描述符。

但是,当 task->mm == NULL 时,该函数直接跳过了 dumpable 检查。而 Qualys 的安全研究人员恰恰发现了这个路径:

__ptrace_may_access() 流程简化:
1. 检查 caller 是否有 CAP_SYS_PTRACE → 无
2. 检查 caller 的 uid 是否匹配 target 的 uid → 匹配
3. 检查 target->mm 是否为 NULL → 是 NULL
4. ❌ 跳过 dumpable 检查!直接返回允许

3. pidfd_getfd(2) 的「完美风暴」

pidfd_getfd(2) 是 Linux 5.6(2020 年)引入的系统调用,允许一个进程通过 pidfd 获取另一个进程的文件描述符副本。结合上述两个问题,攻击者可以:

  1. 创建一个 pidfd 指向目标进程(例如 ssh-keysign)
  2. 反复循环调用 pidfd_getfd(2)
  3. 在目标进程执行 exit_mm() 之后、exit_files() 之前的窗口期,成功窃取文件描述符
  4. 用窃取的 fd 读取 SSH 主机私钥或 /etc/shadow 内容
💡 早有人预警:Google 安全研究员 Jann Horn 早在 2020 年 10 月就在内核邮件列表中指出了这种「fd 盗窃」的攻击面(lore.kernel.org)。但直到六年后的今天,才因 CVE-2026-46333 的公开利用而被彻底修复。

🎯 两个攻击目标:sshkeysign_pwn 和 chage_pwn

安全研究团队 0xdeadbeefnetwork 发布了一个名为 ssh-keysign-pwn 的 PoC 项目(⭐591),包含两个针对性的利用工具:

🔑 sshkeysign_pwn — 窃取 SSH 主机私钥

ssh-keysign 是 OpenSSH 的一个辅助程序,用于基于主机的认证(HostbasedAuthentication)。它在启动后会:

  1. 以 root 权限打开 /etc/ssh/ssh_host_{ecdsa,ed25519,rsa}_key(这些文件是 0600 权限,仅 root 可读)
  2. 然后调用 permanently_set_uid() 丢弃 root 权限
  3. 如果配置文件中 EnableSSHKeysignno,程序直接退出

问题就在第 3 步:程序退出时,那些私钥文件的 fd 仍然是打开状态!攻击者只需在 ssh-keysign 退出后的短暂窗口内调用 pidfd_getfd 即可获取私钥的 fd,然后直接读取文件内容。

🔓 chage_pwn — 窃取 /etc/shadow

chage -l <user> 命令在读取 /etc/shadow 后,通过 setreuid(ruid, ruid) 完全放弃 root 权限(三个 uid 都设为实际用户 uid)。然后立即退出。利用同样的技巧,攻击者可以在 chage 退出时窃取 /etc/shadow 的 fd。

🚨 现实威胁:一旦获得 /etc/shadow 中的 root 密码哈希,攻击者可以离线破解(使用 hashcat 等工具),如果 root 密码较弱,数小时内即可获得服务器完全控制权。

⚡ PoC 使用示例

# 编译
make

# 窃取 SSH 主机密钥
./sshkeysign_pwn
# 输出:/etc/ssh/ssh_host_ecdsa_key 内容
#      /etc/ssh/ssh_host_ed25519_key 内容
#      /etc/ssh/ssh_host_rsa_key 内容

# 窃取 /etc/shadow
./chage_pwn root
# 输出:/etc/shadow 中 root 用户的行

据作者测试,在实际环境中,通常在 100~2000 次 循环尝试内即可成功获取目标文件。

🖥️ 受影响系统验证

项目团队已在以下系统上验证漏洞有效:

所有内核版本低于 31e62c2ebbfd commit 的 Linux 系统均受影响——这基本上包括了 2026 年 5 月 14 日之前发布的所有稳定版内核

🛡️ 防护建议

  1. 立即更新内核:运行 uname -r 检查当前内核版本,确认是否包含 31e62c2ebbfd 修复。各发行版请运行对应的更新命令:apt upgrade / yum update / pacman -Syu
  2. 禁用未使用的 setuid 程序:检查系统中不需要的 setuid 程序,使用 chmod u-s 移除不必要的 SUID 权限。
  3. 最小化本地用户访问:仅授予必要的用户 shell 访问权限,使用 nologin shell 约束服务账户。
  4. 监控异常进程行为:部署 auditd 或类似工具,监控 pidfd_getfd 系统调用的异常使用。
  5. 使用更强的 SSH 密钥:如果私钥被窃取,攻击者可用其冒充服务器进行中间人攻击。务必使用高强度密钥,并考虑部署 SSH CA 基础设施。

📥 复现与验证

项目提供了一个可控环境下的 PoC,可用于安全研究人员测试:

# 编译目标程序(模拟高权限程序打开 shadow 后降权)
sudo install -m 4755 vuln_target /usr/local/bin/vuln_target

# 运行利用程序
./exploit_vuln_target /usr/local/bin/vuln_target
# EPERM → 目标进程存活时被拒绝
# SIGKILL → 目标被杀后,读取 fd 成功拿到 shadow

📚 参考来源

🔧 在线开发者工具 — JSON格式化 · Base64 · UUID生成 · 正则测试 等80+免费工具