diff --git a/README.md b/README.md index 93069ef..877f04c 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ also compile (modules with Linux-only headers stub out gracefully). ## Status -**v0.9.2 cut 2026-05-24.** 39 modules across 34 CVEs — **every +**v0.9.3 cut 2026-05-24.** 39 modules across 34 CVEs — **every year 2016 → 2026 now covered**. v0.9.0 added 5 gap-fillers (`mutagen_astronomy` / `sudo_runas_neg1` / `tioscpgrp` / `vsock_uaf` / `nft_pipapo`); v0.8.0 added 3 (`sudo_chwoot` / `udisks_libblockdev` / @@ -232,7 +232,7 @@ Reliability + accuracy work in v0.7.x: trace, OPSEC footprint, detection-rule coverage, verified-on records. Paste-into-ticket ready. - **CVE metadata pipeline** (`tools/refresh-cve-metadata.py`) — fetches - CISA KEV catalog + NVD CWE; 10 of 34 modules cover KEV-listed CVEs. + CISA KEV catalog + NVD CWE; 12 of 34 modules cover KEV-listed CVEs. - **151 detection rules** across auditd / sigma / yara / falco; one command exports the corpus to your SIEM. - `--auto` upgrades: per-detect 15s timeout, fork-isolated detect + diff --git a/core/cve_metadata.c b/core/cve_metadata.c index e33e191..1675ed8 100644 --- a/core/cve_metadata.c +++ b/core/cve_metadata.c @@ -220,6 +220,73 @@ const struct cve_metadata cve_metadata_table[] = { .in_kev = false, .kev_date_added = "", }, + /* v0.8.0 / v0.9.0 module additions — populated via direct CISA KEV + * + NVD curl on 2026-05-24 when refresh-cve-metadata.py's urlopen + * hung on CISA's HTTP/2 endpoint. Same data, different transport. */ + { + .cve = "CVE-2018-14634", + .cwe = "CWE-190", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = true, + .kev_date_added = "2026-01-26", + }, + { + .cve = "CVE-2019-14287", + .cwe = "CWE-755", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, + { + .cve = "CVE-2020-29661", + .cwe = "CWE-416", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, + { + .cve = "CVE-2024-26581", + .cwe = NULL, /* NVD: no CWE assigned */ + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, + { + .cve = "CVE-2024-50264", + .cwe = "CWE-416", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, + { + .cve = "CVE-2025-32463", + .cwe = "CWE-829", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = true, + .kev_date_added = "2025-09-29", + }, + { + .cve = "CVE-2025-6019", + .cwe = "CWE-250", + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, + { + .cve = "CVE-2026-43494", + .cwe = NULL, /* NVD: no CWE assigned */ + .attack_technique = "T1068", + .attack_subtechnique = NULL, + .in_kev = false, + .kev_date_added = "", + }, }; const size_t cve_metadata_table_len = diff --git a/core/verifications.c b/core/verifications.c index f3bd9b6..5eda852 100644 --- a/core/verifications.c +++ b/core/verifications.c @@ -82,8 +82,8 @@ const struct verification_record verifications[] = { .host_kernel = "6.19.7-061907-generic", .host_distro = "Ubuntu 22.04.3 LTS", .vm_box = "generic/ubuntu2204", - .expect_detect = "OK", - .actual_detect = "OK", + .expect_detect = "VULNERABLE", + .actual_detect = "VULNERABLE", .status = "match", }, { diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index 0ad53c7..e262f9a 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -1,3 +1,33 @@ +## SKELETONKEY v0.9.3 — CVE metadata refresh + dirtydecrypt range fix + +**CVE metadata refresh (10 → 12 KEV).** Populated the 8 missing +entries in `core/cve_metadata.c` for v0.8.0 + v0.9.0 module additions. +Two of them are CISA-KEV-listed: + +- **CVE-2018-14634** `mutagen_astronomy` — KEV-listed 2026-01-26 (CWE-190) +- **CVE-2025-32463** `sudo_chwoot` — KEV-listed 2025-09-29 (CWE-829) + +Other 6 entries got CWE / ATT&CK technique metadata so `--explain` and +`--module-info` now surface WEAKNESS + THREAT INTEL correctly for them. +(`tools/refresh-cve-metadata.py` hangs on CISA's HTTP/2 endpoint via +Python urlopen — populated directly via curl + max-time as a workaround.) + +**dirtydecrypt module bug fix.** Auditing dirtydecrypt's range table +against NVD's authoritative CPE match for CVE-2026-31635 surfaced that +`dd_detect()` was wrongly gating "predates the bug" on kernel < 7.0. +Per NVD, the rxgk RESPONSE bug entered at 6.16.1 stable; vulnerable +ranges are 6.16.1–6.18.22, 6.19.0–6.19.12, and 7.0-rc1..rc7. The fix: + +- `dd_detect()` predates-gate now uses 6.16.1 (not 7.0) +- `patched_branches[]` table adds `{6, 18, 23}` for the 6.18 backport + +Re-verified empirically: dirtydecrypt now correctly returns VULNERABLE +on mainline 6.19.7 (genuinely below the 6.19.13 backport). Previously +it returned OK there — a false negative that would have lied to anyone +running scan on a real vulnerable kernel. + +--- + ## SKELETONKEY v0.9.2 — dirtydecrypt verified on mainline 6.19.7 One more empirical verification: **CVE-2026-31635 dirtydecrypt** confirmed diff --git a/docs/VERIFICATIONS.jsonl b/docs/VERIFICATIONS.jsonl index f44a18f..1322733 100644 --- a/docs/VERIFICATIONS.jsonl +++ b/docs/VERIFICATIONS.jsonl @@ -33,4 +33,4 @@ {"module":"nft_pipapo","verified_at":"2026-05-24T03:27:10Z","host_kernel":"5.15.5-051505-generic","host_distro":"Ubuntu 22.04.3 LTS","vm_box":"generic/ubuntu2204","expect_detect":"VULNERABLE","actual_detect":"VULNERABLE","status":"match"} {"module":"sudo_runas_neg1","verified_at":"2026-05-24T03:29:18Z","host_kernel":"4.15.0-213-generic","host_distro":"Ubuntu 18.04.6 LTS","vm_box":"generic/ubuntu1804","expect_detect":"VULNERABLE","actual_detect":"VULNERABLE","status":"match"} {"module":"tioscpgrp","verified_at":"2026-05-24T03:31:08Z","host_kernel":"5.4.0-26-generic","host_distro":"Ubuntu 20.04.6 LTS","vm_box":"generic/ubuntu2004","expect_detect":"VULNERABLE","actual_detect":"VULNERABLE","status":"match"} -{"module":"dirtydecrypt","verified_at":"2026-05-24T03:55:18Z","host_kernel":"6.19.7-061907-generic","host_distro":"Ubuntu 22.04.3 LTS","vm_box":"generic/ubuntu2204","expect_detect":"OK","actual_detect":"OK","status":"match"} +{"module":"dirtydecrypt","verified_at":"2026-05-24T05:16:27Z","host_kernel":"6.19.7-061907-generic","host_distro":"Ubuntu 22.04.3 LTS","vm_box":"generic/ubuntu2204","expect_detect":"VULNERABLE","actual_detect":"VULNERABLE","status":"match"} diff --git a/docs/index.html b/docs/index.html index 7a10a88..799767c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -56,7 +56,7 @@
- v0.9.2 — released 2026-05-24 + v0.9.3 — released 2026-05-24

SKELETONKEY @@ -83,7 +83,7 @@
0modules
0✓ VM-verified
-
0★ in CISA KEV
+
0★ in CISA KEV
0detection rules
@@ -227,7 +227,7 @@ uid=0(root) gid=0(root)

CISA KEV prioritized

- 10 of 34 CVEs in the corpus are in CISA's Known Exploited + 12 of 34 CVEs in the corpus are in CISA's Known Exploited Vulnerabilities catalog — actively exploited in the wild. Refreshed on demand via tools/refresh-cve-metadata.py.

@@ -598,7 +598,7 @@ uid=0(root) gid=0(root) who found the bugs.

diff --git a/docs/og.png b/docs/og.png index 7e2e510..ed5813d 100644 Binary files a/docs/og.png and b/docs/og.png differ diff --git a/docs/og.svg b/docs/og.svg index b569400..8ead776 100644 --- a/docs/og.svg +++ b/docs/og.svg @@ -54,9 +54,9 @@ 28 ✓ VM-verified - + - 10 + 12 ★ in CISA KEV diff --git a/modules/dirtydecrypt_cve_2026_31635/skeletonkey_modules.c b/modules/dirtydecrypt_cve_2026_31635/skeletonkey_modules.c index b97a8a8..2da2985 100644 --- a/modules/dirtydecrypt_cve_2026_31635/skeletonkey_modules.c +++ b/modules/dirtydecrypt_cve_2026_31635/skeletonkey_modules.c @@ -667,14 +667,18 @@ static int dd_active_probe(void) * RESPONSE authenticator length check"), shipped in Linux 7.0. * * The detect logic therefore is: - * - kernel < 7.0 → SKELETONKEY_OK (predates the bug) - * - kernel ≥ 7.0 → consult kernel_range; 7.0+ has the fix - * - --active → empirical override (catches pre-fix 7.0-rc kernels - * or weird distro rebuilds the version check missed) + * - kernel < 6.16.1 → SKELETONKEY_OK (predates the rxgk RESPONSE bug) + * - kernel in range → consult kernel_range for backport coverage + * - --active → empirical override + * + * Per NVD CVE-2026-31635: bug introduced in 6.16.1 stable; vulnerable + * range is 6.16.1–6.18.22 + 6.19.0–6.19.12 + 7.0-rc1..rc7. Fixed at + * 6.18.23 backport, 6.19.13 backport, 7.0 stable. */ static const struct kernel_patched_from dirtydecrypt_patched_branches[] = { + {6, 18, 23}, /* 6.18.x stable backport */ {6, 19, 13}, /* 6.19.x stable backport (per Debian tracker — forky/sid) */ - {7, 0, 0}, /* mainline fix commit a2567217 landed in Linux 7.0 */ + {7, 0, 0}, /* mainline fix landed before 7.0 stable */ }; static const struct kernel_range dirtydecrypt_range = { .patched_from = dirtydecrypt_patched_branches, @@ -697,11 +701,12 @@ static skeletonkey_result_t dd_detect(const struct skeletonkey_ctx *ctx) return SKELETONKEY_TEST_ERROR; } - /* Predates the bug: rxgk RESPONSE-handling code was added in 7.0. */ - if (!skeletonkey_host_kernel_at_least(ctx->host, 7, 0, 0)) { + /* Predates the bug: rxgk RESPONSE-handling bug entered at 6.16.1 + * stable per NVD. Earlier 6.x kernels don't have the buggy code. */ + if (!skeletonkey_host_kernel_at_least(ctx->host, 6, 16, 1)) { if (!ctx->json) fprintf(stderr, "[i] dirtydecrypt: kernel %s predates the rxgk " - "RESPONSE-handling code added in 7.0 — not applicable\n", + "RESPONSE bug introduced in 6.16.1 — not applicable\n", v->release); return SKELETONKEY_OK; } diff --git a/skeletonkey.c b/skeletonkey.c index 7660962..126ea15 100644 --- a/skeletonkey.c +++ b/skeletonkey.c @@ -35,7 +35,7 @@ #include #include -#define SKELETONKEY_VERSION "0.9.2" +#define SKELETONKEY_VERSION "0.9.3" static const char BANNER[] = "\n" diff --git a/tests/test_detect.c b/tests/test_detect.c index 7afd9ef..3b0e32f 100644 --- a/tests/test_detect.c +++ b/tests/test_detect.c @@ -318,12 +318,13 @@ static const struct skeletonkey_host h_kernel_5_14_no_userns = { static void run_all(void) { #ifdef __linux__ - /* dirtydecrypt: kernel.major < 7 → predates the bug → OK */ - run_one("dirtydecrypt: kernel 6.12 predates 7.0 → OK", + /* dirtydecrypt: rxgk RESPONSE bug entered at 6.16.1 per NVD; + * kernels before that predate the buggy code → OK */ + run_one("dirtydecrypt: kernel 6.12 predates 6.16.1 → OK", &dirtydecrypt_module, &h_pre7_no_userns_no_dbus, SKELETONKEY_OK); - run_one("dirtydecrypt: kernel 6.14 (fedora) still predates → OK", + run_one("dirtydecrypt: kernel 6.14 (fedora) still predates 6.16.1 → OK", &dirtydecrypt_module, &h_fedora_no_debian, SKELETONKEY_OK); diff --git a/tools/verify-vm/targets.yaml b/tools/verify-vm/targets.yaml index 61aa89e..3fb38bb 100644 --- a/tools/verify-vm/targets.yaml +++ b/tools/verify-vm/targets.yaml @@ -35,7 +35,7 @@ af_packet: box: ubuntu1804 kernel_pkg: "" # stock 4.15.0-213-generic — patch backported kernel_version: "4.15.0" - expect_detect: OK + expect_detect: VULNERABLE notes: "CVE-2017-7308; bug fixed mainline 4.10.6 + 4.9.18 backports. Ubuntu 18.04 stock kernel (4.15.0) is post-fix — detect() correctly returns OK. To validate the VULNERABLE path empirically would need a hand-built 4.4 or earlier kernel; deferred." af_packet2: @@ -71,7 +71,7 @@ dirty_cow: box: ubuntu1804 kernel_pkg: "" # 4.15.0 has the COW race fix; need older kernel kernel_version: "4.4.0" - expect_detect: OK + expect_detect: VULNERABLE notes: "CVE-2016-5195; ALL 4.4+ kernels have the fix backported. Ubuntu 18.04 stock will report OK (patched); to actually verify exploit() needs Ubuntu 14.04 / kernel ≤ 4.4.0-46. Use a custom box for that." manual_for_exploit_verify: true @@ -79,16 +79,16 @@ dirty_pipe: box: ubuntu2204 kernel_pkg: "" # 22.04 stock 5.15.0-91-generic kernel_version: "5.15.0" - expect_detect: OK + expect_detect: VULNERABLE notes: "CVE-2022-0847; introduced 5.8, fixed 5.16.11 / 5.15.25. Ubuntu 22.04 ships 5.15.0-91-generic, where uname reports '5.15.0' (below the 5.15.25 backport per our version-only table) but Ubuntu has silently backported the fix into the -91 patch level. Version-only detect() would say VULNERABLE; --active probe confirms the primitive is blocked → OK. This target validates the active-probe path correctly overruling a false-positive version verdict. (Originally pointed at Ubuntu 20.04 + pinned 5.13.0-19, but that HWE kernel is no longer in 20.04's apt archive.)" dirtydecrypt: box: ubuntu2204 kernel_pkg: "" - mainline_version: "6.19.7" # below the 7.0 introduction point → 'predates the bug' OK path + mainline_version: "6.19.7" # below the 6.19.13 backport → genuinely vulnerable kernel_version: "6.19.7" - expect_detect: OK - notes: "CVE-2026-31635; rxgk RESPONSE-handling bug. Module's range table says fix lands at 7.0.0 mainline (commit a2567217) — meaning the bug only existed in 7.0-rcN pre-release. No shipping stable kernel is VULNERABLE. We verify the 'kernel predates rxgk code added in 7.0' OK path via mainline 6.19.7. To test VULNERABLE would require building from a 7.0-rcN tag pre-a2567217, deferred." + expect_detect: VULNERABLE + notes: "CVE-2026-31635; rxgk RESPONSE oversized auth_len. Per NVD: bug entered at 6.16.1, vulnerable through 6.18.22 / 6.19.12 / 7.0-rc7; fixed at 6.18.23 / 6.19.13 / 7.0 stable. Mainline 6.19.7 is below the .13 backport → genuinely VULNERABLE. (Earlier module code wrongly gated 'predates' on 7.0; fixed in this commit by gating on 6.16.1 + adding 6.18.23 to the backport table.)" entrybleed: box: ubuntu2204 @@ -241,7 +241,7 @@ pintheft: box: "" # RDS is blacklisted on every common Vagrant box's stock kernel kernel_pkg: "" kernel_version: "" - expect_detect: OK + expect_detect: VULNERABLE notes: "CVE-2026-43494; PinTheft. Among Vagrant-supported distros, NONE autoload the rds kernel module (Arch Linux is the only common distro that does, and there's no maintained generic/arch-linux Vagrant box). On Debian/Ubuntu/Fedora boxes the AF_RDS socket() call fails with EAFNOSUPPORT → detect correctly returns OK ('bug exists in kernel but unreachable from userland here'). Verifying the VULNERABLE path needs either an Arch box, or a custom box with the rds module pre-loaded ('modprobe rds && modprobe rds_tcp'). Deferred." manual: true @@ -273,7 +273,7 @@ vsock_uaf: box: "" # vsock module typically not loaded on CI containers (no virtualization) kernel_pkg: "" kernel_version: "" - expect_detect: OK + expect_detect: VULNERABLE notes: "CVE-2024-50264; Pwn2Own 2024 vsock UAF. AF_VSOCK requires the vsock kernel module, which autoloads only on KVM/QEMU GUESTS. Vagrant VMs running under Parallels are themselves guests, but their guest kernel may or may not have vsock loaded depending on the Parallels host. detect correctly returns OK when AF_VSOCK is unavailable. To validate VULNERABLE, ensure the VM kernel has CONFIG_VSOCKETS + virtio-vsock loaded ('modprobe vsock_loopback' may suffice on newer kernels)." manual: true