050731396d
Verified 2026-06-08 on Ubuntu 24.04.4 / kernel 6.8.0-117-generic under
QEMU/HVF (offline: cloud image + payload iso, no guest networking):
- modprobe cifs registers the cifs.spnego key type (cifs-utils not needed
to reach the primitive).
- Independent python3 ctypes add_key('cifs.spnego', forged
uid/creduid/upcall_target) ACCEPTED (user-key control also accepted);
module exploit() independently reported 'primitive CONFIRMED' then the
honest EXPLOIT_FAIL.
- detect() returned PRECOND_FAIL without cifs-utils and VULNERABLE under
SKELETONKEY_CIFS_ASSUME_PRESENT=1.
Still pending (so cifswitch stays 🟡 and is NOT counted as a verified
end-to-end CVE; verified count stays 28 of 37): a patched kernel
(>=6.12.90/7.0.10) to prove add_key is REJECTED there (probe discriminates
fixed-from-vulnerable), and the full namespace+NSS root-pop. Recorded in
NOTICE.md, CVES.md, RELEASE_NOTES.md, and tools/verify-vm/targets.yaml.
93 lines
4.6 KiB
Markdown
93 lines
4.6 KiB
Markdown
# NOTICE — cifswitch (CVE-2026-46243, "CIFSwitch")
|
||
|
||
## Vulnerability
|
||
|
||
**CVE-2026-46243 "CIFSwitch"** — the Linux kernel's `cifs.spnego`
|
||
request-key type (`fs/smb/client/cifs_spnego.c`) accepts key descriptions
|
||
created by **userspace** (via `add_key(2)` / `request_key(2)`) without
|
||
verifying that the request originated from the in-kernel CIFS client. The
|
||
key description carries authority-bearing fields — `pid`, `uid`,
|
||
`creduid`, `upcall_target` — that the root-privileged `cifs.upcall`
|
||
helper treats as trusted, kernel-originating inputs. An unprivileged
|
||
local user forges such a description and, combined with user + mount
|
||
namespace manipulation, coerces `cifs.upcall` into loading an
|
||
attacker-controlled NSS shared library as root → local privilege
|
||
escalation to root.
|
||
|
||
It is a **~19-year-old** logic flaw — the cifs spnego upcall predates the
|
||
key-type origin checks added to the keyrings subsystem later. NVD class:
|
||
**CWE-20** (Improper Input Validation). Not in CISA KEV (as of disclosure).
|
||
|
||
**Preconditions:** the `cifs` kernel module available, `cifs-utils`
|
||
installed (so `cifs.upcall` is present), and the `cifs.spnego`
|
||
request-key rule active. Default-vulnerable distributions reported
|
||
include Linux Mint, CentOS Stream 9, Rocky Linux 9, AlmaLinux 9, Kali
|
||
Linux, SLES 15 SP7, and Red Hat Enterprise Linux 6–10.
|
||
|
||
## Research credit
|
||
|
||
Discovered, named, and disclosed by **Asim Manizada** on **2026-05-28**,
|
||
with a working proof-of-concept published the same day.
|
||
|
||
- Red Hat advisory (RHSB-2026-005):
|
||
<https://access.redhat.com/security/vulnerabilities/RHSB-2026-005>
|
||
- BleepingComputer write-up:
|
||
<https://www.bleepingcomputer.com/news/security/new-cifswitch-linux-flaw-gives-root-on-multiple-distributions/>
|
||
- Upstream fix: commit `3da1fdf4efbc490041eb4f836bf596201203f8f2`
|
||
("smb: client: reject userspace cifs.spnego descriptions"), merged
|
||
7.1-rc5.
|
||
- Debian-tracked stable backports: 5.10.257 (bullseye) / 6.1.174
|
||
(bookworm) / 6.12.90 (trixie) / 7.0.10 (forky, sid).
|
||
|
||
All research credit for finding and analysing this bug belongs to Asim
|
||
Manizada. SKELETONKEY is the bundling and bookkeeping layer only.
|
||
|
||
## SKELETONKEY role
|
||
|
||
🟡 **Primitive / ported-from-disclosure — not yet VM-verified.**
|
||
`detect()` gates on the kernel version (the Debian backport thresholds
|
||
above) **and** the presence of the vulnerable userspace path
|
||
(`cifs.upcall` / the `cifs.spnego` request-key rule) — a vulnerable
|
||
kernel without `cifs-utils` is reported `PRECOND_FAIL`, not `VULNERABLE`.
|
||
Override the probe with `SKELETONKEY_CIFS_ASSUME_PRESENT=1` (or `0`).
|
||
|
||
`exploit()` fires only the reachable, **non-destructive** part of the
|
||
primitive: it attempts to register a forged-but-benign `cifs.spnego` key
|
||
as the unprivileged user via `add_key(2)` — which instantiates the key
|
||
directly and does **not** invoke `cifs.upcall`, so it loads nothing and
|
||
spawns no privileged helper — and revokes the key immediately. A clean
|
||
accept is the empirical witness that the missing-origin-validation flaw
|
||
is present. It then **stops**: the namespace-switch + malicious-NSS-load
|
||
chain that actually lands a root shell is target/config-specific and is
|
||
**not** bundled until it can be verified end-to-end against a real
|
||
vulnerable VM, in keeping with the project's no-fabrication rule.
|
||
`exploit()` returns `EXPLOIT_FAIL` unless it can witness euid 0.
|
||
|
||
`--mitigate` writes `/etc/modprobe.d/skeletonkey-disable-cifs.conf`
|
||
(blocklists the `cifs` module — the vendor-recommended runtime
|
||
mitigation); `--cleanup` removes it. Architecture-agnostic — keyring and
|
||
namespace logic, no shellcode.
|
||
|
||
## Verification status (partial)
|
||
|
||
Verified **2026-06-08** on **Ubuntu 24.04.4 LTS, kernel 6.8.0-117-generic**
|
||
(QEMU/HVF, x86_64):
|
||
|
||
- `modprobe cifs` registers the `cifs.spnego` key type (dmesg:
|
||
`Key type cifs.spnego registered`) — `cifs-utils` is **not** required to
|
||
reach the primitive.
|
||
- An **independent** `python3` `ctypes` probe calling
|
||
`add_key("cifs.spnego", <forged uid/creduid/upcall_target>)` was
|
||
**ACCEPTED** (a plain `user`-key control was also accepted), and the
|
||
module's own `exploit()` independently reported **primitive CONFIRMED**
|
||
then the honest `EXPLOIT_FAIL`.
|
||
- `detect()` returned `PRECOND_FAIL` with `cifs-utils` absent and
|
||
`VULNERABLE` under `SKELETONKEY_CIFS_ASSUME_PRESENT=1`.
|
||
|
||
**Still pending** (so this stays 🟡 and is *not* counted as a verified
|
||
end-to-end CVE): (a) confirming `add_key` is **rejected** on a *patched*
|
||
kernel (≥ 6.12.90 / 7.0.10) — i.e. that the probe distinguishes
|
||
fixed-from-vulnerable rather than the key type always permitting userspace
|
||
creation; and (b) the full namespace + malicious-NSS root-pop, which
|
||
remains unbundled.
|