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:
@@ -5,180 +5,183 @@
|
|||||||
[](CVES.md)
|
[](CVES.md)
|
||||||
[](#)
|
[](#)
|
||||||
|
|
||||||
> **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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user