Home · Live brief · Daily brief 2026-05-23
CVE-2026-46333 ssh-keysign-pwn: a 9-year ptrace race in the Linux kernel reaching root and SSH host keys
Part of run 2026-05-23-852c21c8 (intel · Claude Opus 4.7)
Background. The Linux kernel's __ptrace_may_access() permission check in kernel/ptrace.c has been a recurring source of local-privilege-escalation primitives ever since the dumpable / capability model was introduced. CVE-2019-13272 (Jann Horn, 2019) exploited a similar credential-window confusion in the same function. The introduction of pidfd_getfd() in v5.6-rc1 (January 2020) added a second axis — fd duplication across processes — that has compounded ptrace-window primitives by allowing fds harvested during a privileged credential window to be reused under the attacker's UID. Qualys's Looney Tunables (CVE-2023-4911) set the template for the credibility-with-public-exploits disclosure pattern Qualys has continued since. CVE-2026-46333 fits squarely in that lineage: a long-dormant logic error reaching first-class root primitives, with the disclosure structured around defender-actionable analysis rather than weaponisation help.
The bug. Qualys TRU disclosed CVE-2026-46333 on 2026-05-20 (the URL path encodes the disclosure date; the Qualys blog also carries a 2026-05-22 rendered "Date" field that appears to reflect a content update; the brief uses the URL-encoded disclosure date as anchor) (The Hacker News, 2026-05-21 · Canonical / Ubuntu, 2026-05-19; upstream kernel fix landed 2026-05-14) — a TOCTOU race in __ptrace_may_access() present since Linux v4.10-rc1 (November 2016). The window is the brief interval when a privileged process drops credentials — for example a setuid binary calling setuid() to lower privilege after performing a privileged action. During that window __ptrace_may_access() incorrectly permits ptrace attachment, because credential comparison is performed against the uid/gid captured at the time of the ptrace_may_access() call rather than at the point of the actual access; the dumpable flag is re-evaluated too late. An unprivileged caller racing the credential drop wins ptrace rights on the target.
The chain. A standalone ptrace win is interesting; the chain that promotes it to a four-target root primitive is the combination with pidfd_getfd(). Once attached, the attacker uses pidfd_getfd() to duplicate file descriptors from the privileged process into the attacker's own process. Those fds — opened by the privileged process for reading /etc/shadow, writing to /etc/ssh/ssh_host_*_key, executing as root, or speaking to D-Bus / systemd over a privileged socket — are now usable under the attacker's UID. Qualys developed four working exploits, detailed in the public advisory (exploit code itself was withheld during coordinated disclosure; the advisory and PoC outputs are public):
chage(setuid-root, setgid-shadow) → reads/etc/shadowand recovers the local hash database for cracking.ssh-keysign(setuid-root) → exfiltrates SSH host private keys from/etc/ssh/— the host's identity to the rest of the network, enabling SSH MITM and host impersonation on internal links.pkexec(setuid-root) → arbitrary root command execution; functionally equivalent to PwnKit (CVE-2021-4034) outcomes but reached through a different primitive.accounts-daemon(root daemon, not setuid) → arbitrary root command execution via hijacked D-Bus connection to systemd.
Exploits confirmed working on Debian 13, Ubuntu 24.04 / 26.04, Fedora 43 / 44; the underlying primitive applies to any distro carrying a v4.10-or-newer kernel and a standard setuid surface. Prerequisites: a local unprivileged shell on the target host. No network exposure required — this is a pure post-foothold escalation primitive — and no kernel hardening short of restricting ptrace defeats it on a default Linux server.
MITRE ATT&CK mapping. Primarily T1068 Exploitation for Privilege Escalation; the SSH-key exfiltration outcome maps to T1552.004 Unsecured Credentials: Private Keys; the D-Bus path through accounts-daemon is closer to T1543.002 Create or Modify System Process: Systemd Service in outcome shape.
Detection vantage. Qualys published QID 387392 for vulnerability scanning. Behavioural detection is the operationally interesting axis because the primitive is hard to defeat without a kernel update:
- Syscall pairing. EDR /
auditdhunt forpidfd_getfdsyscall paired withptracecalls originating from a non-root process targeting a setuid-root process. The combination is rare in normal workloads and is the canonical fingerprint of the exploitation pattern. - Anomalous credential-file reads.
/etc/shadowread by non-root, non-PAM-stack processes;/etc/ssh/ssh_host_*_keyread by non-sshdprocesses. - D-Bus → systemd anomalies.
accounts-daemonD-Bus connections from process trees lacking a legitimate parent (e.g. spawned from a shell rather than a login session). - Audit-rule pattern.
auditctl -w /etc/shadow -p r -k shadow_readplus-w /etc/ssh -p r -k ssh_host_key_read; pair with-a always,exit -F arch=b64 -S pidfd_getfd -k pidfd_getfd_audit.
Hardening / mitigation. The supported mitigation hierarchy:
- Patch. Upstream kernel fix landed 2026-05-14; distribution vendor packages are available from Debian, Fedora, Red Hat, SUSE, AlmaLinux, CloudLinux and Ubuntu (Canonical's ssh-keysign-pwn advisory). Roll the kernel where USNs / DSAs are available; for ELRepo / longterm trees, build against the patched stable tag.
- Interim:
sysctl kernel.yama.ptrace_scope=2. Restrictsptraceto processes carryingCAP_SYS_PTRACE. This eliminates the primitive on non-root processes but breaks debuggers and some profiling tools; deploy via configuration management with explicit allowlist of dev workstations or jump hosts where ptrace is needed. - Restrict
pidfd_getfdvia seccomp on multi-tenant or container hosts. Where workloads can be characterised, denypidfd_getfdvia seccomp profiles on container runtimes; Docker / containerd default profiles can be extended. - Container-runtime context. Multi-tenant Kubernetes nodes where lower-privilege workloads share the host kernel are the highest-risk environment because the primitive operates at kernel level —
usernsremapping does not block it. Treat patched-kernel rollout as a hard prerequisite for multi-tenant nodes.
Why this is a deep dive and not a § 2 entry. CVE-2026-46333 is a local LPE primitive — no pre-authentication network surface, no automated mass-exploitation pattern in the wild yet — so it does not clear the § 2 inclusion gates the prompt enforces. But the combination of all-major-distros affected, four working Qualys exploits detailed in the public advisory, nine-year dormancy in a kernel function under repeated scrutiny, and SSH host-key exfiltration as one of the achievable outcomes makes it the highest-signal Linux-LPE deep dive of the last fortnight. Every EU/CH public-sector environment running Linux containers, multi-tenant compute or developer workstations sits within the affected surface; the patch rollout window is the actionable defensive frame.
Action items
- Roll kernel patches for CVE-2026-46333 on every Linux estate; raise
kernel.yama.ptrace_scope=2as interim on hosts that cannot be rebooted yet. Four working Qualys exploits detailed in the public advisory (exploit code withheld during coordinated disclosure), all major distros affected, SSH host-key exfiltration in the outcome set. Multi-tenant Kubernetes nodes carry highest residual risk. Full detection / hardening package in § 5 Deep Dive below.