needhelp
← 返回博客

ssh-keysign-pwn:ptrace 逻辑漏洞让普通用户读取 root 文件

作者 xingwangzhe
Linux
内核
安全
Qualys
ptrace
CVE

ssh-keysign-pwn:内核 __ptrace_may_access() 函数中存在六年的逻辑漏洞,由 Qualys 报告,Linus Torvalds 于 2026 年 5 月 14 日修复。非特权用户可读取 root 所有的文件,包括 SSH 主机私钥和 /etc/shadow。所有 31e62c2ebbfd 之前的内核版本均受影响。


又补一个

2026 年 5 月对 Linux 内核来说不太好过。Dirty Frag、Fragnesia,现在又是 ssh-keysign-pwn——Qualys 在 5 月 14 日披露,Linus Torvalds 当天就修了。

这次跟前几个”往页缓存里写东西”的漏洞不太一样。它是一个纯粹的 __ptrace_may_access() 逻辑 bug——这是内核里决定一个进程能否检查另一个进程的函数。

指标
发现者Qualys 安全团队
修复者Linus Torvalds
修复 commit31e62c2ebbfd
潜伏时间~6 年
首次发现Jann Horn(Google),2020 年 10 月
PoC 发布者_SiCk
影响普通用户读取 root 文件
利用难度100–2000 次尝试可窃取一次

漏洞原理

问题出在 __ptrace_may_access()。这个函数是进程自省的看门人——它检查一个进程是否有权限探查另一个进程的状态。

有一个特殊情况:当 task->mm == NULL 时(目标进程没有内存描述符——线程正在退出时会发生,内核线程也永远没有),函数完全跳过了 dumpable 检查

可被利用的代码路径:

  1. 进程调用 do_exit() 准备终止
  2. do_exit() 先跑 exit_mm()——拆除内存描述符(mm
  3. 然后跑 exit_files()——但此时文件描述符仍然活着
  4. 此时 task->mm == NULL 但 fd 还在,pidfd_getfd(2) 就能偷走这些 fd——只要调用者的 uid 匹配

正常情况下,ptrace 访问检查会阻止低权限进程触碰 root 进程的打开文件句柄。但 mm == NULL 这个旁路把 dumpable 检查跳过了,剩下的交给 pidfd_getfd(2)

这是一个典型的 TOCTOU 竞态,但窗口足够大——PoC 在 100–2000 次尝试内就能 hit。

攻击目标

发布了两个工具:

sshkeysign_pwn——攻击 ssh-keysign,一个签名主机认证挑战的辅助二进制。它会在调用 permanently_set_uid() 降权之前先打开 SSH 主机密钥文件(/etc/ssh/ssh_host_{ecdsa,ed25519,rsa}_key,0600 权限)。然后检查 sshd_config 里是否设置了 EnableSSHKeysign——如果没设,它直接退出,而密钥 fd 还开着。这个设计从 2002 年 起就在 OpenSSH 里了。

chage_pwn——攻击 chage -l <user>。它通过 spw_open(O_RDONLY) 打开 /etc/shadow,然后调用 setreuid(ruid, ruid)——两个参数都是真实 uid,所以完全降权。在降权和关闭文件之间的窗口里,fd 可以被偷走。


时间线

日期事件
~2020 年Jann Horn 发现 FD 窃取模式并提出补丁(未合入)
2026-05-14Qualys 报告漏洞;Linus Torvalds 提交修复(31e62c2ebbfd
2026-05-14Brad Spengler 发布分析
2026-05-14_SiCk 在 GitHub 发布 PoC
2026-05-15Qualys 向 oss-security 发送披露邮件

从 2020 年 Jann Horn 的补丁提案到 2026 年 Qualys 的报告,这个 gap 很值得注意。补丁五年前就写好了,但从来没有合入主线。


修复方案

Linus 以 commit 31e62c2ebbfd 提交了修复。他在 commit message 里写道:

“我们有一个特殊的边缘情况:ptrace_may_access() 使用 ‘dumpable’ 来检查各种完全独立于 MM 的东西(典型如使用 PTRACE_MODE_READ_FSCREDS 标志),包括那些已经没有 VM 的线程(甚至可能从来没有过,比如大多数内核线程)。这不是这个标志设计时的初衷,但事实就是如此。”

补丁调整了 ptrace 行为以正确处理 mm == NULL 的情况,实际上关闭了这个旁路窗口。

检查你的内核

uname -r
# 修复内核包含 commit 31e62c2ebbfd
# 所有 2026-05-14 之前的内核都受影响

值得注意的点

三件事让我印象深刻:

  1. 当天报告当天修复。 Linus 几小时内就搞定了。这对内核补丁来说快得不寻常——说明一旦理解了 bug,修起来很直接。

  2. Jann Horn 2020 年就发现了。 社区在邮件列表存档里放着五年前的补丁提案。FD 窃取的模式早就知道,但没人推动它合入。

  3. 攻击目标是远古设计。 ssh-keysign 的 fd 遗留模式始于 2002 年。chagespw_open + setreuid 序列也同样历史悠久。这不是 SSH 或 shadow-utils 的 bug——这是内核 bug 把特权二进制中既有的 fd 处理模式武器化了。

这是 2026 年 5 月第三个主要的 Linux 内核漏洞了,排在 Copy FailDirty Frag 之后。披露节奏在加速——一方面因为 AI 辅助审计工具在更快地挖出老漏洞,另一方面因为披露生态在碎片化(embargo 被打破、补丁还没出 PoC 就公开了)。


参考

分享本页