From 2873133852480ce0f2726709f14d7bd5ebbc55d6 Mon Sep 17 00:00:00 2001 From: KaraZajac Date: Sun, 17 May 2026 02:02:50 -0400 Subject: [PATCH] =?UTF-8?q?README:=20polish=20=E2=80=94=20accurate=20count?= =?UTF-8?q?s,=20audience=20table,=20corpus=20glance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- README.md | 257 +++++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 127 deletions(-) diff --git a/README.md b/README.md index d41377e..03f253f 100644 --- a/README.md +++ b/README.md @@ -5,180 +5,183 @@ [![Modules](https://img.shields.io/badge/modules-28-brightgreen.svg)](CVES.md) [![Platform: Linux](https://img.shields.io/badge/platform-linux-lightgrey.svg)](#) -> **One curated binary. Twenty-eight Linux LPE exploits from 2016 → 2026. -> Detection rules in the box. One command picks the safest one and runs it.** +> **One curated binary. 28 Linux LPE exploits, 2016 → 2026. Detection +> rules in the box. One command picks the safest one and runs it.** ```bash curl -sSL https://github.com/KaraZajac/SKELETONKEY/releases/latest/download/install.sh | sh \ && skeletonkey --auto --i-know ``` -**For red teams:** stop curating dead PoC repos. `skeletonkey --scan` -tells you what works; `--auto` picks the safest one and pops shell. +> ⚠️ **Authorized testing only.** SKELETONKEY runs real exploits. By +> 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 -still need patching — same binary, same rules, no third-party SaaS. +## Why use this -**For blue teams:** every module ships matching auditd + sigma rules. -`skeletonkey --detect-rules --format=auditd | sudo tee /etc/audit/rules.d/99-skeletonkey.rules` -gets you SIEM coverage for every CVE in the corpus. +Most Linux privesc tooling is broken in one of three ways: -> ⚠️ **Authorized testing only.** SKELETONKEY is a research and red-team -> tool. By using it you assert you have explicit authorization to test -> the target system. See [`docs/ETHICS.md`](docs/ETHICS.md). +- **`linux-exploit-suggester` / `linpeas`** — tell you what *might* + work, run nothing +- **`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 ```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 -``` -### 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) skeletonkey --scan -# Broader system hygiene (setuid binaries, world-writable, capabilities, sudo) -skeletonkey --audit +# Pick the safest LPE and run it +skeletonkey --auto --i-know -# Deploy detection rules (needs sudo to write /etc/audit/rules.d/) -skeletonkey --detect-rules --format=auditd | sudo tee /etc/audit/rules.d/99-skeletonkey.rules +# 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 -# Apply temporary mitigations (needs sudo for modprobe.d + sysctl) -sudo skeletonkey --mitigate copy_fail - -# 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 +# Fleet scan — many hosts 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 ```text $ id uid=1000(kara) gid=1000(kara) groups=1000(kara) -$ skeletonkey --scan -[+] dirty_pipe VULNERABLE (kernel 5.15.0-56-generic) -[+] cgroup_release_agent VULNERABLE (kernel 5.15 < 5.17) -[+] pwnkit VULNERABLE (polkit 0.105-31ubuntu0.1) -[-] copy_fail not vulnerable (kernel 5.15 < introduction) -[-] dirty_cow not vulnerable (kernel ≥ 4.9) +$ skeletonkey --auto --i-know +[*] auto: host=demo kernel=5.15.0-56-generic arch=x86_64 +[*] auto: scanning 28 modules for vulnerabilities... +[+] auto: dirty_pipe VULNERABLE (safety rank 90) +[+] auto: cgroup_release_agent VULNERABLE (safety rank 98) +[+] auto: pwnkit VULNERABLE (safety rank 100) -$ skeletonkey --exploit dirty_pipe --i-know -[!] dirty_pipe: kernel 5.15.0-56-generic IS vulnerable -[+] dirty_pipe: writing UID=0 into /etc/passwd page cache... -[+] dirty_pipe: spawning su root +[*] auto: 3 vulnerable modules found. Safest is 'pwnkit' (rank 100). +[*] auto: launching --exploit pwnkit... + +[+] pwnkit: writing gconv-modules cache + payload.so... +[+] pwnkit: execve(pkexec) with NULL argv + crafted envp... # id uid=0(root) gid=0(root) groups=0(root) ``` -`skeletonkey --help` lists every command. See [`CVES.md`](CVES.md) for -the curated CVE inventory and [`docs/DEFENDERS.md`](docs/DEFENDERS.md) -for the blue-team deployment guide. +The safety ranking goes: **structural escapes** (no kernel state +touched) → **page-cache writes** → **userspace cred-races** → +**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 -deep-dives. **SKELETONKEY is a living corpus**: each CVE that lands here -is empirically verified to work on the kernels it claims to target, -CI-tested across a distro matrix, and ships with the detection -signatures defenders need to spot it in their environment. +Each CVE (or tightly-related family) is a **module** under `modules/`. +Modules export a standard interface (`detect / exploit / mitigate / +cleanup`) plus metadata (kernel range, detection rule text). The +top-level binary dispatches per command: -The same binary covers offense and defense: +- `--scan` walks every module's `detect()` against the running host +- `--exploit --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=` emits the + embedded rule corpus +- `--mitigate ` / `--cleanup ` 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 - apply, and which are blocked by patches/config/LSM -- `skeletonkey --exploit ` — run the named exploit (with `--i-know` - authorization gate) -- `skeletonkey --detect-rules` — dump auditd / sigma / yara rules for - every bundled CVE so blue teams can drop them into their tooling -- `skeletonkey --mitigate` — apply temporary mitigations for CVEs the - host is vulnerable to (sysctl knobs, module blacklists, etc.) +See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the +module-loader design. + +## The verified-vs-claimed bar + +Most public PoC repos hardcode offsets for one kernel build and +silently break elsewhere. SKELETONKEY refuses to ship fabricated +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 -**Active — v0.5.0 cut 2026-05-17.** Corpus covers **28 modules** -across the 2016 → 2026 LPE timeline: +**v0.5.0 cut 2026-05-17.** 28 modules. All build clean on Debian 13 +(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 - (copy_fail family ×5, dirty_pipe, entrybleed leak, pwnkit, - 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 [`ROADMAP.md`](ROADMAP.md) for the next planned modules and +infrastructure work. -See [`CVES.md`](CVES.md) for the per-CVE inventory + patch status. -See [`ROADMAP.md`](ROADMAP.md) for the next planned modules. +## Contributing -## Why this exists - -The Linux kernel privilege-escalation space is fragmented: - -- **`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) -``` +PRs welcome for: kernel offsets (run `--dump-offsets` on a target +kernel, paste into `core/offsets.c`), new modules, detection rules, +and CVE-status corrections. See [`CONTRIBUTING.md`](CONTRIBUTING.md). ## Acknowledgments Each module credits the original CVE reporter and PoC author in its -`NOTICE.md`. SKELETONKEY is the bundling and bookkeeping layer; the -research credit belongs to the people who found the bugs. +`NOTICE.md`. SKELETONKEY is the bundling and bookkeeping layer; +the research credit belongs to the people who found the bugs. ## License