modules: add ghostlock (CVE-2026-43499, "GhostLock" rtmutex/futex requeue-PI stack UAF)
release / build (arm64) (push) Waiting to run
release / build (x86_64) (push) Waiting to run
release / build (x86_64-static / musl) (push) Waiting to run
release / build (arm64-static / musl) (push) Waiting to run
release / release (push) Blocked by required conditions
release / build (arm64) (push) Waiting to run
release / build (x86_64) (push) Waiting to run
release / build (x86_64-static / musl) (push) Waiting to run
release / build (arm64-static / musl) (push) Waiting to run
release / release (push) Blocked by required conditions
Adds the ghostlock module for CVE-2026-43499 ("GhostLock", VEGA / Nebula
Security's "IonStack part II") — a ~15-year race UAF on kernel STACK memory in
the rtmutex/futex requeue-PI path (kernel/locking/rtmutex.c). On the -EDEADLK
deadlock-rollback, remove_waiter() runs against `current` instead of the waiter
task, so a concurrent sched_setattr()-driven PI-chain priority walk on another
CPU clears pi_blocked_on on the wrong task and leaves an on-stack rt_mutex_waiter
dangling. Reachable by any unprivileged user (CVSS 7.8, PR:L) — plain
futex(2) + sched_setattr(2), no userns/CONFIG beyond CONFIG_FUTEX_PI. The
corpus's first rtmutex/futex-PI module and first kernel-stack UAF (all others
are heap/slab).
Introduced 2.6.39; fixed 3bfdc63936dd (7.1-rc1), stable backports
7.0.4 / 6.18.27 / 6.12.86 / 6.6.140 / 6.1.175; 5.15/5.10/5.4/4.19 affected with
no upstream fix. CWE-416; not in KEV.
detect() is a pure version gate over the five-branch backport table. exploit()
forks an isolated child that (A) deterministically confirms the -EDEADLK
remove_waiter() rollback path is reachable (safe — no concurrent walk means no
dangling pointer; validated on real hardware) then (B) exercises the actual race
a hard-bounded 24 iters / 2s with a sibling-CPU sched_setattr(SCHED_BATCH) storm,
and stops. Deliberately under-driven: no copy_from_user widening, no stack-frame
spray/reoccupation, and the KernelSnitch leak -> forged-waiter ->
fops/ashmem/pipe R/W -> cred-patch chain (Android/Pixel-specific, per-build
offsets) is NOT bundled. Returns EXPLOIT_FAIL. Lowest --auto safety rank (11) —
a won race corrupts the kernel stack. Unlike most races it ships a real
detection signature (futex requeue-PI returning EDEADLK + sibling sched_setattr);
auditd/sigma anchor on sched_setattr, falco/eBPF on the EDEADLK tell; no yara.
Wired: registry, Makefile, safety rank 11, version 0.9.13, 9 detect() test rows
(incl. 6.13.0 -> VULNERABLE, the multi-branch "newer than all" case), CVE
metadata (CWE-416 / T1068 / not-KEV; cve_metadata.c + KEV_CROSSREF.md regenerated
-> 13 of 40), README + CVES.md + website counts (45 modules / 40 CVEs),
RELEASE_NOTES v0.9.13, verify-vm target. Also corrects pre-existing
docs/index.html drift left by v0.9.12 (body counts stuck at 43/38 and a missing
bad_epoll corpus pill). Tests: 33 kernel_range + 101 detect, all pass.
Credit: VEGA / Nebula Security (nebusec.ai, NebuSec/CyberMeowfia, Apache-2.0);
upstream fix 3bfdc63936dd (Keenan Dong / Thomas Gleixner).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KUq4DGXSPBmPkAyJ9WnM9n
This commit is contained in:
@@ -314,6 +314,15 @@
|
||||
"in_kev": false,
|
||||
"kev_date_added": ""
|
||||
},
|
||||
{
|
||||
"cve": "CVE-2026-43499",
|
||||
"module_dir": "ghostlock_cve_2026_43499",
|
||||
"cwe": "CWE-416",
|
||||
"attack_technique": "T1068",
|
||||
"attack_subtechnique": null,
|
||||
"in_kev": false,
|
||||
"kev_date_added": ""
|
||||
},
|
||||
{
|
||||
"cve": "CVE-2026-46242",
|
||||
"module_dir": "bad_epoll_cve_2026_46242",
|
||||
|
||||
@@ -4,7 +4,7 @@ Which SKELETONKEY modules cover CVEs that CISA has observed exploited
|
||||
in the wild per the Known Exploited Vulnerabilities catalog.
|
||||
Refreshed via `tools/refresh-cve-metadata.py`.
|
||||
|
||||
**13 of 39 modules cover KEV-listed CVEs.**
|
||||
**13 of 40 modules cover KEV-listed CVEs.**
|
||||
|
||||
## In KEV (prioritize patching)
|
||||
|
||||
@@ -54,6 +54,7 @@ and are technically reachable. "Not in KEV" is not the same as
|
||||
| CVE-2026-31635 | CWE-130 | `dirtydecrypt_cve_2026_31635` |
|
||||
| CVE-2026-41651 | CWE-367 | `pack2theroot_cve_2026_41651` |
|
||||
| CVE-2026-43494 | ? | `pintheft_cve_2026_43494` |
|
||||
| CVE-2026-43499 | CWE-416 | `ghostlock_cve_2026_43499` |
|
||||
| CVE-2026-46242 | CWE-416 | `bad_epoll_cve_2026_46242` |
|
||||
| CVE-2026-46243 | CWE-20 | `cifswitch_cve_2026_46243` |
|
||||
| CVE-2026-46300 | CWE-787 | `fragnesia_cve_2026_46300` |
|
||||
|
||||
@@ -1,3 +1,57 @@
|
||||
## SKELETONKEY v0.9.13 — new LPE module: ghostlock (CVE-2026-43499)
|
||||
|
||||
Adds **`ghostlock` — CVE-2026-43499 "GhostLock"** (VEGA / Nebula Security,
|
||||
"IonStack part II"), taking the corpus to **45 modules / 40 CVEs** and opening a
|
||||
brand-new subsystem: **rtmutex / futex requeue-PI** (`kernel/locking/rtmutex.c`).
|
||||
It is also the corpus's first kernel-**stack** use-after-free — every other UAF
|
||||
in the set is heap/slab. On the `-EDEADLK` deadlock-rollback path,
|
||||
`remove_waiter()` operates on `current` instead of the actual waiter task while
|
||||
unwinding a proxy lock in `rt_mutex_start_proxy_lock()` (reached from
|
||||
`futex_requeue()`); if a concurrent PI-chain priority walk — driven from another
|
||||
CPU via `sched_setattr()` — runs at that instant, `pi_blocked_on` is cleared on
|
||||
the wrong task and an on-stack `rt_mutex_waiter` is left dangling, becoming a
|
||||
controlled kernel write when the rbtree is later rotated over the reused frame.
|
||||
Reachable by **any unprivileged user** (CVSS 7.8, PR:L) — plain `futex(2)` +
|
||||
`sched_setattr(2)`, no user namespace, no capability, only `CONFIG_FUTEX_PI`
|
||||
(universal). It has existed since PI-futex requeue landed in **2.6.39** — ~15
|
||||
years across every distribution. The public exploit weaponises it (Android/Pixel)
|
||||
via a "KernelSnitch" futex-bucket page leak → forged waiter → `struct file`
|
||||
`f_op` → configfs/ashmem R/W → pipe physical R/W → cred patch; ~97% stable on
|
||||
kernelCTF, $92,337. Introduced 2.6.39; fixed `3bfdc63936dd` (merged 7.1-rc1),
|
||||
stable backports 7.0.4 / 6.18.27 / 6.12.86 / 6.6.140 / 6.1.175 — the
|
||||
5.15/5.10/5.4/4.19 LTS branches are affected with no upstream fix. CWE-416 (race
|
||||
root cause CWE-362); not in CISA KEV.
|
||||
|
||||
🟡 **Trigger (reconstructed) — reachability-only, deliberately under-driven, not
|
||||
VM-verified.** `detect()` is a pure kernel-version gate over a five-branch
|
||||
backport table (7.0.4 / 6.18.27 / 6.12.86 / 6.6.140 / 6.1.175, 7.1+ inherits
|
||||
mainline; 5.15/5.10/5.4/4.19 affected with no fix; < 2.6.39 not affected) — no
|
||||
userns/CONFIG probe (`CONFIG_FUTEX_PI` assumed). `exploit()` forks an isolated
|
||||
child that **(A)** deterministically confirms the `-EDEADLK` `remove_waiter()`
|
||||
rollback path is reachable — a **safe** witness, since without a concurrent
|
||||
priority walk the unwind creates no dangling pointer (validated on real hardware:
|
||||
the requeue-PI cycle returns `-EDEADLK` reliably) — then **(B)** exercises the
|
||||
actual race a hard-bounded 24 iterations / 2 s with a sibling-CPU
|
||||
`sched_setattr(SCHED_BATCH)` storm, and stops. It does **not** widen the
|
||||
`copy_from_user` window (no memfd/`PUNCH_HOLE`), does **not** spray or reoccupy
|
||||
the freed stack frame, and does **not** bundle the KernelSnitch leak →
|
||||
forged-waiter → fops/configfs/ashmem/pipe R/W → cred-patch chain (Android/Pixel-
|
||||
specific, per-build offsets). Returns `EXPLOIT_FAIL`. It carries the corpus's
|
||||
**lowest `--auto` safety rank (11)** — a won race corrupts the kernel stack and
|
||||
drives a near-arbitrary pointer write (near-certain panic), so `--auto` only
|
||||
reaches for it after every safer vulnerable module. Unlike most kernel races
|
||||
GhostLock has a **real detection signature**: a futex requeue-PI op returning
|
||||
`-EDEADLK` (glibc never provokes this) plus tight-loop
|
||||
`sched_setattr(SCHED_BATCH)` on a sibling thread — the shipped auditd/sigma rules
|
||||
anchor on `sched_setattr` + the post-exploitation euid-0 transition, the
|
||||
falco/eBPF rule on the requeue-PI-EDEADLK tell; no yara. Wired: registry,
|
||||
Makefile, safety rank (11), 9 `detect()` test rows (incl. the multi-branch
|
||||
"newer than all" case 6.13.0 → VULNERABLE), CVE metadata (CWE-416 / T1068 /
|
||||
not-KEV), README + CVES.md + website counts (45/40), RELEASE_NOTES v0.9.13, and a
|
||||
verify-vm target (sweep pending). Also corrects pre-existing website drift left
|
||||
by v0.9.12 (index.html body counts + the missing `bad_epoll` corpus pill).
|
||||
Credits VEGA / Nebula Security + the upstream fix `3bfdc63936dd`.
|
||||
|
||||
## SKELETONKEY v0.9.12 — new LPE module: bad_epoll (CVE-2026-46242)
|
||||
|
||||
Adds **`bad_epoll` — CVE-2026-46242 "Bad Epoll"** (Jaeyoung Chung /
|
||||
|
||||
+13
-11
@@ -4,9 +4,9 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>SKELETONKEY — Linux LPE corpus, VM-verified, SOC-ready detection</title>
|
||||
<meta name="description" content="One binary. 44 Linux privilege-escalation modules from 2016 to 2026. 28 of 39 CVEs empirically verified in real Linux VMs. 13 KEV-listed. 151 detection rules across auditd/sigma/yara/falco. MITRE ATT&CK and CWE annotated. --explain gives operator briefings.">
|
||||
<meta name="description" content="One binary. 45 Linux privilege-escalation modules from 2016 to 2026. 28 of 40 CVEs empirically verified in real Linux VMs. 13 KEV-listed. 151 detection rules across auditd/sigma/yara/falco. MITRE ATT&CK and CWE annotated. --explain gives operator briefings.">
|
||||
<meta property="og:title" content="SKELETONKEY — Linux LPE corpus, VM-verified">
|
||||
<meta property="og:description" content="44 Linux LPE modules; 28 of 39 CVEs empirically verified in real VMs. 151 detection rules. ATT&CK + CWE + KEV annotated.">
|
||||
<meta property="og:description" content="45 Linux LPE modules; 28 of 40 CVEs empirically verified in real VMs. 151 detection rules. ATT&CK + CWE + KEV annotated.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://karazajac.github.io/SKELETONKEY/">
|
||||
<meta property="og:image" content="https://karazajac.github.io/SKELETONKEY/og.png">
|
||||
@@ -62,8 +62,8 @@
|
||||
<span class="display-wordmark">SKELETONKEY</span>
|
||||
</h1>
|
||||
<p class="hero-tag">
|
||||
One binary. <strong>43 Linux LPE modules</strong> covering 38 CVEs —
|
||||
<strong>every year 2016 → 2026</strong>. 28 of 38 confirmed against
|
||||
One binary. <strong>45 Linux LPE modules</strong> covering 40 CVEs —
|
||||
<strong>every year 2016 → 2026</strong>. 28 of 40 confirmed against
|
||||
real Linux kernels in VMs. SOC-ready detection rules in four SIEM
|
||||
formats. MITRE ATT&CK + CWE + CISA KEV annotated.
|
||||
<span class="hero-tag-pop">--explain gives a one-page operator briefing per CVE.</span>
|
||||
@@ -81,7 +81,7 @@
|
||||
</div>
|
||||
|
||||
<div class="stats-row" id="stats-row">
|
||||
<div class="stat-chip"><span class="num" data-target="43">0</span><span>modules</span></div>
|
||||
<div class="stat-chip"><span class="num" data-target="45">0</span><span>modules</span></div>
|
||||
<div class="stat-chip stat-vfy"><span class="num" data-target="28">0</span><span>✓ VM-verified</span></div>
|
||||
<div class="stat-chip stat-kev"><span class="num" data-target="13">0</span><span>★ in CISA KEV</span></div>
|
||||
<div class="stat-chip"><span class="num" data-target="151">0</span><span>detection rules</span></div>
|
||||
@@ -227,7 +227,7 @@ uid=0(root) gid=0(root)</pre>
|
||||
<div class="bento-icon">★</div>
|
||||
<h3>CISA KEV prioritized</h3>
|
||||
<p>
|
||||
13 of 38 CVEs in the corpus are in CISA's Known Exploited
|
||||
13 of 40 CVEs in the corpus are in CISA's Known Exploited
|
||||
Vulnerabilities catalog — actively exploited in the wild.
|
||||
Refreshed on demand via <code>tools/refresh-cve-metadata.py</code>.
|
||||
</p>
|
||||
@@ -289,12 +289,12 @@ uid=0(root) gid=0(root)</pre>
|
||||
|
||||
<article class="bento-card bento-vfy">
|
||||
<div class="bento-icon">✓</div>
|
||||
<h3>22 modules empirically verified</h3>
|
||||
<h3>28 modules empirically verified</h3>
|
||||
<p>
|
||||
<code>tools/verify-vm/</code> spins up known-vulnerable
|
||||
kernels (stock distro + mainline from kernel.ubuntu.com), runs
|
||||
<code>--explain --active</code> per module, and records the
|
||||
verdict. <strong>28 of 38 CVEs</strong> confirmed against
|
||||
verdict. <strong>28 of 40 CVEs</strong> confirmed against
|
||||
real Linux across Ubuntu 18.04 / 20.04 / 22.04 + Debian 11 / 12
|
||||
+ mainline 5.4.0-26 / 5.15.5 / 6.1.10 / 6.19.7. Records baked into the binary;
|
||||
<code>--list</code> shows ✓ per module.
|
||||
@@ -309,7 +309,7 @@ uid=0(root) gid=0(root)</pre>
|
||||
<div class="container">
|
||||
<div class="section-head">
|
||||
<span class="section-tag">corpus</span>
|
||||
<h2>38 CVEs across 10 years. ★ = actively exploited (CISA KEV).</h2>
|
||||
<h2>40 CVEs across 10 years. ★ = actively exploited (CISA KEV).</h2>
|
||||
</div>
|
||||
|
||||
<h3 class="corpus-h" data-color="green">
|
||||
@@ -358,6 +358,8 @@ uid=0(root) gid=0(root)</pre>
|
||||
<span class="pill yellow">ptrace_pidfd</span>
|
||||
<span class="pill yellow">cifswitch</span>
|
||||
<span class="pill yellow">nft_catchall</span>
|
||||
<span class="pill yellow">bad_epoll</span>
|
||||
<span class="pill yellow">ghostlock</span>
|
||||
</div>
|
||||
|
||||
<p class="corpus-foot">
|
||||
@@ -418,7 +420,7 @@ uid=0(root) gid=0(root)</pre>
|
||||
<div class="audience-icon">🎓</div>
|
||||
<h3>Researchers / CTF</h3>
|
||||
<p>
|
||||
38 CVEs, 10-year span, each with the original PoC author
|
||||
40 CVEs, 10-year span, each with the original PoC author
|
||||
credited and the kernel-range citation auditable.
|
||||
<code>--explain</code> shows the reasoning chain; detection
|
||||
rules let you practice both sides. Source is the documentation.
|
||||
@@ -515,7 +517,7 @@ uid=0(root) gid=0(root)</pre>
|
||||
<div class="tl-col tl-shipped">
|
||||
<div class="tl-tag">shipped</div>
|
||||
<ul>
|
||||
<li><strong>28 of 38 CVEs empirically verified</strong> in real Linux VMs</li>
|
||||
<li><strong>28 of 40 CVEs empirically verified</strong> in real Linux VMs</li>
|
||||
<li><strong>kernel.ubuntu.com/mainline/</strong> kernel fetch path — unblocks pin-not-in-apt targets</li>
|
||||
<li>Per-module <code>verified_on[]</code> table baked into the binary</li>
|
||||
<li><strong>--explain mode</strong> — one-page operator briefing per CVE</li>
|
||||
|
||||
Reference in New Issue
Block a user