文章总结: 该文档详细分析了Linux内核权限提升漏洞CVE-2026-46333(ssh-keysign-pwn),该漏洞属于TOCTOU竞态条件类型,影响Linux内核4.14至6.19.11版本。攻击者可通过pidfdgetfd系统调用在setuid程序退出时窃取文件描述符,从而读取/etc/shadow或SSH主机私钥等敏感文件。文档提供了漏洞技术原理、完整利用链、影响范围评估,并给出了升级内核、设置ptracescope=2等修复与缓解措施。 综合评分: 85 文章分类: 漏洞分析,内核安全,实战经验,安全建设,漏洞预警
CVE-2026-46333 漏洞分析报告
原创
simeon的文章 simeon的文章
小兵搞安全
2026年6月11日 13:33 北京
在小说阅读器读本章
去阅读
#
一、漏洞概述
漏洞名称/代号
ssh-keysign-pwn
漏洞类型
Linux内核权限提升(Improper Privilege Management, CWE-269)
CVSS评分
- 基础评分:5.5 (Medium) – 按照本地访问、低复杂度、用户交互的常规评估
- 部分安全厂商评分:9.8 (Critical) – 考虑到实际利用成功率接近100%且影响范围广
发现者/披露方
Qualys威胁研究团队(Qualys Threat Research Unit)
披露时间
2026年5月14日
影响范围
- Linux内核版本:4.14 ~ 6.19.11
- 受影响主流发行版:Debian、Ubuntu、Fedora、RHEL、CentOS、AlmaLinux等
- 潜伏时长:约6-9年(2016年或2020年引入,取决于具体内核分支)
风险等级
高危。普通用户可稳定利用该漏洞读取root拥有的任意敏感文件,包括系统密码哈希、SSH主机密钥等,直接威胁系统安全。
二、技术原理深度分析
漏洞产生的根本原因
漏洞位于内核__ptrace_may_access()函数中,属于检查时间-使用时间(TOCTOU) 竞态漏洞的一种变体。根本原因是:当目标进程的task->mm指针为NULL时,内核会跳过dumpable安全检查,而攻击者可以利用进程退出时的时序窗口制造这一条件。
受影响的代码模块/函数
核心函数:__ptrace_may_access()(定义于kernel/ptrace.c)
关键代码路径:
do_exit()
- 进程退出处理函数
exit_mm()
- 释放进程内存描述符(mm)
put_files_struct()
- 关闭进程文件描述符
pidfd_getfd()
- 通过pidfd获取目标进程的文件描述符
漏洞关键逻辑:在__ptrace_may_access()函数中,当task->mm == NULL时,函数直接返回0(允许访问),跳过了对ptrace_mode和dumpable的安全检查。这一设计原本用于处理内核线程(内核线程没有mm),但被攻击者利用于用户态进程退出的中间状态。
漏洞触发条件
- 系统中存在setuid或setgid程序(如
ssh-keysign、chage等) - 攻击者拥有本地普通用户权限
- 内核支持
pidfd_getfd()系统调用(Linux 5.6及以上版本) - ptrace_scope未设置为2(限制性模式)
完整的攻击流程/利用链
攻击利用链(以ssh-keysign为例) :
步骤1:攻击者以普通用户身份启动setuid程序(ssh-keysign)
步骤2:ssh-keysign以root权限运行,打开/etc/shadow等敏感文件
步骤3:攻击者监控目标进程状态,等待其进入退出流程
步骤4:do_exit()先调用exit_mm()将task->mm置为NULL
步骤5:在文件描述符被关闭前的极短窗口内,攻击者调用pidfd_getfd()
步骤6:由于mm=NULL,__ptrace_may_access()跳过安全检查,允许窃取fd
步骤7:攻击者通过窃取的文件描述符读取敏感文件内容
技术细节
1. 进程退出的执行顺序
Linux内核中do_exit()函数的关键执行顺序:
do_exit()
├── exit_mm()// 释放mm结构,task->mm = NULL
├── exit_files()// 释放文件描述符表
├── exit_fs()
└── …
关键在于:exit_mm() 在 exit_files() 之前执行。这意味着在mm被释放后、文件描述符被关闭前,存在一个短暂的时间窗口,此时进程的task->mm == NULL,但文件描述符仍然有效。
2. pidfd_getfd 的权限检查
pidfd_getfd()系统调用在执行时会调用__ptrace_may_access()进行权限检查。当目标进程mm == NULL时,检查被绕过,攻击者即可获取目标进程的任意文件描述符。
3. 竞态窗口的利用
由于竞态窗口非常短暂(微秒级),攻击者需要:
- 使用
pidfd_open()获取进程文件描述符 - 通过
poll()或waitid()监听进程退出事件 - 在检测到进程即将退出时,快速循环调用
pidfd_getfd() - 利用Linux调度的不确定性增加命中窗口的概率
实际测试表明,通过反复执行,攻击成功率接近100% 。
4. 攻击目标的选择
攻击者需要选择在退出前会打开敏感文件的setuid程序。典型目标包括:
-
ssh-keysign
:SSH的主机认证辅助程序,会读取SSH主机私钥
-
chage
:修改用户密码过期信息,会读取/etc/shadow
-
passwd
:修改用户密码,会读取/写入/etc/shadow
-
su
:切换用户,会读取/etc/passwd和/etc/shadow
三、影响范围与风险评估
受影响的软件版本
| 发行版 | 受影响版本 | 修复版本 | | — | — | — | | Linux主线内核 | 4.14 ~ 6.19.11 | 6.19.12+ | | Debian | bookworm (12)、trixie (13) | 待发布安全更新 | | Ubuntu | 22.04 LTS、24.04 LTS、24.10 | 各版本已发布内核更新 | | Fedora | 39、40、41 | 已推送更新 | | RHEL | 8.x、9.x | 已发布RHSA | | AlmaLinux | 8.x、9.x | 已推送内核更新 |
受影响的平台/系统
- 所有运行受影响版本Linux内核的x86_64、ARM64等架构系统
- 物理服务器、虚拟机、容器环境均受影响
攻击面分析
攻击向量:本地攻击
- 需要本地用户权限(普通用户即可)
- 无法远程直接利用,但可配合远程代码执行漏洞进行提权
攻击面广度:
- 几乎所有Linux发行版都受影响
- 只要系统中存在setuid程序即可被利用
- 容器环境中若允许
pidfd_getfd()系统调用也会受影响
实际危害程度
高危害。攻击者可获取:
- /etc/shadow
- 所有用户的密码哈希,可用于离线爆破
- SSH主机私钥
- 可冒充该服务器进行中间人攻击
- 其他敏感文件
- 如Kerberos keytab、应用配置中的密码等
- 特权进程打开的任意文件
- 扩展攻击面
虽然是本地提权漏洞,但在多用户系统、共享主机环境、容器逃逸场景下危害极大。
在野利用状态
-
未确认
。截至2026年6月,尚无公开的在野利用报告
-
但由于POC已公开且利用难度低,不排除已被攻击者掌握
四、POC/EXP分析
公开状态
✅ 已公开完整POC
利用难度评级
低。普通用户权限即可利用,攻击脚本可稳定复现,成功率接近100%。
POC/EXP来源与可信度
-
发布者
:安全研究员 _SiCk(GitHub账号:0xdeadbeefnetwork)
-
发布时间
:2026年5月14日(漏洞披露后数小时内)
-
项目地址
:https://github.com/0xdeadbeefnetwork/ssh-keysign-pwn
-
可信度
:高。已被多个安全厂商和社区验证有效
利用代码关键片段分析
POC包含两种主要利用路径:
路径1:窃取SSH主机私钥
利用ssh-keysign程序读取SSH主机密钥
ssh-keysign是setuid root程序,用于主机认证
程序会打开/etc/ssh/ssh_host_*_key文件
在程序退出瞬间窃取文件描述符
路径2:读取/etc/shadow密码哈希
利用chage或passwd等setuid程序
这些程序需要读取/etc/shadow进行密码验证
同样在退出窗口窃取文件描述符
核心利用逻辑(伪代码) :
// 1. 创建子进程执行setuid程序
pid = fork();
if(pid==0){
execve(“/usr/libexec/openssh/ssh-keysign”,argv,envp);
}
// 2. 获取pidfd
intpidfd = pidfd_open(pid,0);
// 3. 等待进程进入退出状态
// 使用poll/epoll监听pidfd的POLLERR事件
// 4. 在竞态窗口内反复尝试窃取文件描述符
for(inti = 0; i<1000; i++){
intfd = pidfd_getfd(pidfd,target_fd,0);
if(fd>=0){
// 成功窃取,读取文件内容
charbuf[4096];
read(fd,buf,sizeof(buf));
break;
}
}
利用成功的前提条件
-
攻击者拥有本地普通用户账户
-
目标系统存在可被利用的setuid程序(大多数Linux系统默认存在)
-
内核版本支持
pidfd_getfd()系统调用(5.6+) -
/proc/sys/kernel/yama/ptrace_scope不为2
检测与绕过方法
检测方法:
- 监控
pidfd_getfd()系统调用的异常使用 - 检查setuid程序异常退出模式
- 监控敏感文件的异常访问模式
绕过方法:
- 攻击者可选择不同的setuid程序作为攻击目标
- 可通过调整重试次数和时机绕过简单的频率检测
五、修复与防护方案
官方修复补丁/版本
主线内核修复:
- 修复提交:Linus Torvalds 提交的 commit
31e62c2ebbfd - 提交信息:”ptrace: Don’t allow accessing an undumpable mm via the NULL mm check”
- 链接:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31e62c2ebbfdc3fe3dbdf5e02c92a9dc67087a3a
各发行版修复状态:
- Ubuntu:已发布USN安全公告,各版本内核均已更新
- Fedora:已推送更新
- AlmaLinux:2026年5月15日发布安全公告
- Debian:已发布DSA安全公告
修复原理简述
修复的核心是修改__ptrace_may_access()函数中的mm == NULL检查逻辑。修复后,内核不会仅仅因为mm为NULL就跳过所有权限检查,而是会:
- 对于确实没有mm的内核线程,保持原有逻辑
- 对于曾经有mm但已被释放的用户进程,使用进程凭证(credentials)进行权限检查
- 确保dumpable标志被正确评估,即使mm已被释放
临时缓解措施
在无法立即升级内核的情况下,可采取以下缓解措施:
-
设置ptrace_scope为限制性模式
echo2 > /proc/sys/kernel/yama/ptrace_scope
或在/etc/sysctl.conf中添加:
kernel.yama.ptrace_scope =2
说明:ptrace_scope=2表示只允许由父进程启动的跟踪,显著缩小攻击面
-
审查和移除不必要的setuid程序
查找系统中的setuid程序
find / -perm-4000-type f 2>/dev/null
移除不必要的setuid位或程序
-
容器环境防护
- 使用seccomp过滤
pidfd_getfd()系统调用 - 确保容器以非root用户运行
- 限制容器的capabilities
- 凭证轮换
- 假设SSH主机密钥可能已泄露,考虑轮换密钥
- 提醒用户修改密码,防范密码哈希泄露风险
检测方法
日志检测:
- 监控auditd日志中
pidfd_getfd系统调用的使用 - 关注setuid程序的异常频繁调用
- 关键字:
pidfd_getfd、ptrace、异常的文件描述符复制
流量/行为检测:
- 检测普通用户进程对敏感文件的异常读取
- 监控ssh-keysign等程序的异常调用模式
防护建议
-
立即升级内核
:这是最根本的解决方案
-
启用Yama ptrace限制
:将ptrace_scope设置为2
-
最小化setuid程序
:移除不必要的setuid程序
-
加强监控
:部署文件完整性监控和异常行为检测
-
凭证管理
:定期轮换SSH主机密钥和用户密码
-
容器加固
:在容器环境中使用seccomp和用户命名空间隔离
六、参考来源
- Qualys官方披露 – 漏洞发现方的官方公告
- Linux内核git提交 – 官方修复补丁
- AlmaLinux安全公告 – 发行版安全公告
- SecureBulletin分析 – 技术分析文章
- GitHub – ssh-keysign-pwn POC – 公开POC仓库
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:小兵搞安全 simeon的文章 simeon的文章《CVE-2026-46333 漏洞分析报告》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论