Skip to content

内核 FD Theft 与 mm-NULL Ptrace 绕过防御(Yama / Seccomp / SUID 收敛) ​

防御目标 ​

防止非特权进程利用内核 do_exit() 中 exit_mm() 与 exit_files() 之间的 mm-NULL 竞态窗口(CVE-2026-46333),通过 pidfd_open(434) + pidfd_getfd(438) 复制已退出的 SUID 进程打开的 /etc/shadow 或 SSH 主机私钥句柄。

分层防御矩阵 ​

防御层控制点实施细节效果
内核修复合入提交 31e62c2ebbfd(2026-05-14 之后稳定版内核)__ptrace_may_access() / pidfd_getfd() 在 mm == NULL 时强制失败或严格校验 PF_EXITING/dumpable从内核根因封堵 mm-NULL 窗口
Seccomp 过滤禁用 pidfd_getfd(x86_64 syscall 438)在容器运行时、systemd 服务单元(SystemCallFilter=~pidfd_getfd)和沙箱中拦截 pidfd_getfd截断跨进程 FD 复制原语
Ptrace 与 Dumpable 收敛kernel.yama.ptrace_scope >= 1、fs.suid_dumpable = 0限制进程间 ptrace 附着关系并禁止 SUID 进程生成核心转储缩小可附着与转储暴露面
SUID 暴露面最小化清理/替换 SUID 二进制(ssh-keysign、chage 等)移除非必要 SUID 位;无需 Host-Based Auth 时禁用 ssh-keysign 的 SUID 位并配置 HostbasedAuthentication no消除“以 root 打开敏感文件后降权退出”的攻击靶标
凭证隔离与密码哈希强度使用 yescrypt / Argon2id 并限制 ssh_host_*_key 访问策略即便发生历史泄露也提升离线破解门槛,并触发 SSH 主机密钥告警降低二次横向风险

防御实现与校验示例 ​

1. systemd 服务沙箱与 sysctl 加固配置 ​

ini
# /etc/sysctl.d/99-ptrace-hardening.conf
kernel.yama.ptrace_scope = 2
fs.suid_dumpable = 0
ini
# systemd unit 片段:阻断服务及子进程使用 pidfd_getfd
[Service]
SystemCallFilter=~pidfd_getfd
NoNewPrivileges=yes

2. 系统 SUID 暴露面与 sysctl 基线检查脚本(Python) ​

python
from pathlib import Path

SENSITIVE_SUID_TARGETS = {
    "/usr/lib/openssh/ssh-keysign",
    "/usr/libexec/openssh/ssh-keysign",
    "/usr/bin/chage",
}

def evaluate_fd_theft_posture(suid_paths: list[str], yama_scope: int, seccomp_blocks_pidfd_getfd: bool) -> dict:
    risky_suid = [p for p in suid_paths if p in SENSITIVE_SUID_TARGETS]
    findings = []
    if yama_scope < 1:
        findings.append("weak_yama_ptrace_scope")
    if not seccomp_blocks_pidfd_getfd:
        findings.append("pidfd_getfd_not_filtered_in_sandbox")
    if risky_suid:
        findings.append(f"suid_targets_present:{','.join(risky_suid)}")
    return {
        "hardened": len(findings) == 0,
        "findings": findings,
    }

if __name__ == "__main__":
    assert evaluate_fd_theft_posture([], 2, True)["hardened"] is True
    res = evaluate_fd_theft_posture(["/usr/bin/chage"], 0, False)
    assert not res["hardened"] and len(res["findings"]) == 3
    print("mm_null_fd_theft_defense: PASS")

防御工作流 ​

text
1. 核对内核补丁:确认运行内核已包含修复提交 31e62c2ebbfd(或发行版对应 CVE-2026-46333 安全更新)
2. 启用 Yama 与转储禁用:设置 kernel.yama.ptrace_scope >= 1(服务器推荐 2)及 fs.suid_dumpable = 0
3. 清理高危 SUID:若业务未启用 SSH HostbasedAuthentication,剥离 ssh-keysign SUID 权限(chmod u-s)
4. Seccomp 拦截:在容器与隔离服务配置中禁止 pidfd_getfd 系统调用
5. 运行时检测:对高频 fork + pidfd_open + pidfd_getfd 的异常进程行为生成告警

验证与判定标准 ​

  • 系统调用拦截:在配置了 SystemCallFilter=~pidfd_getfd 的服务或容器内调用 pidfd_getfd 返回 EPERM
  • 内核补丁校验:在已修复内核上运行 pidfd_getfd 访问正在退出的子进程句柄返回 EACCES / EPERM / ESRCH,无法读取 /etc/shadow 或 ssh_host_*_key
  • SUID 与 sysctl 合规:sysctl kernel.yama.ptrace_scope >= 1、sysctl fs.suid_dumpable == 0,且非必需 SUID 列表已清空

MCP 工具映射 ​

防御环节MCP 工具用途
同类内核逃逸路径查询kb_router检索 ptrace/namespace 相关防御卡
加固配置文件生成workspace_write_text输出 sysctl 与 systemd seccomp 加固片段
异常行为检测规则make_sigma_stub生成高频 pidfd_open/pidfd_getfd 窃取行为检测规则

Apache-2.0 · For authorized learning and defensive research only · Disclaimer