Add stackrot (CVE-2023-3269) + af_packet2 (CVE-2020-14386) modules
Two more for 'THE tool' coverage breadth. stackrot CVE-2023-3269 (Ruihan Li, Jul 2023): - maple-tree VMA-split UAF — kernel R/W via use-after-RCU - **Different bug class than the netfilter-heavy 2022-2024 modules** (mm-class, broadens corpus shape) - kernel_range: 6.1 ≤ K < 6.4-rc4, backports: 6.1.37 / 6.3.10 / mainline 6.4 - Pre-6.1 immune (no maple tree); 6.5+ patched - Affects 6.1 LTS still widely deployed - ~1000-line public PoC deferred for port af_packet2 CVE-2020-14386 (Or Cohen, Sep 2020): - AF_PACKET tpacket_rcv VLAN integer underflow → heap OOB - Sibling of CVE-2017-7308; same subsystem, different code path - kernel_range: 4.6 ≤ K, backports across 4.9 / 4.14 / 4.19 / 5.4 / 5.7 / 5.8 - Family-shared 'iamroot-af-packet' audit key (one ausearch covers both CVEs from one rule deployment) Era coverage now (1 gap year remaining: 2018): 2016: dirty_cow 🟢 2017: af_packet 🔵 2019: ptrace_traceme 🟢 2020: af_packet2 🔵 2021: pwnkit, overlayfs, netfilter_xtcompat 🟢/🟢/🔵 2022: dirty_pipe, cls_route4, fuse_legacy 🟢/🔵/🔵 2023: entrybleed, stackrot 🟢/🔵 2024: nf_tables 🔵 2026: copy_fail family (×5) 🟢 18 modules total. Build clean. Scan on Debian 6.12.86: 13 OK / 5 VULN.
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* af_packet2_cve_2020_14386 — IAMROOT module
|
||||
*
|
||||
* AF_PACKET tpacket_rcv() VLAN tag parsing integer underflow → heap
|
||||
* write-before-allocation. Different bug from CVE-2017-7308 — same
|
||||
* subsystem, different code path (rx side rather than ring setup),
|
||||
* later introduction. Discovered by Or Cohen (2020).
|
||||
*
|
||||
* STATUS: 🔵 DETECT-ONLY. Or Cohen's public PoC works end-to-end;
|
||||
* porting follows the same shape as CVE-2017-7308.
|
||||
*
|
||||
* Affected: kernel 4.6+ until backports:
|
||||
* 5.8.x : K >= 5.8.7
|
||||
* 5.7.x : K >= 5.7.16
|
||||
* 5.4.x : K >= 5.4.62
|
||||
* 4.19.x : K >= 4.19.143
|
||||
* 4.14.x : K >= 4.14.197
|
||||
* 4.9.x : K >= 4.9.235
|
||||
*
|
||||
* Preconditions: same as CVE-2017-7308 — CAP_NET_RAW (via user_ns).
|
||||
*
|
||||
* Coverage rationale: fills 2020 gap. Many distros (Ubuntu 18.04
|
||||
* default kernel 4.15, Ubuntu 20.04 default kernel 5.4) were vulnerable
|
||||
* before backport. Embedded systems with 4.x kernels still in production.
|
||||
*/
|
||||
|
||||
#include "iamroot_modules.h"
|
||||
#include "../../core/registry.h"
|
||||
#include "../../core/kernel_range.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static const struct kernel_patched_from af_packet2_patched_branches[] = {
|
||||
{4, 9, 235},
|
||||
{4, 14, 197},
|
||||
{4, 19, 143},
|
||||
{5, 4, 62},
|
||||
{5, 7, 16},
|
||||
{5, 8, 7},
|
||||
{5, 9, 0}, /* mainline */
|
||||
};
|
||||
|
||||
static const struct kernel_range af_packet2_range = {
|
||||
.patched_from = af_packet2_patched_branches,
|
||||
.n_patched_from = sizeof(af_packet2_patched_branches) /
|
||||
sizeof(af_packet2_patched_branches[0]),
|
||||
};
|
||||
|
||||
static int can_unshare_userns(void)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) return -1;
|
||||
if (pid == 0) {
|
||||
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) == 0) _exit(0);
|
||||
_exit(1);
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
}
|
||||
|
||||
static iamroot_result_t af_packet2_detect(const struct iamroot_ctx *ctx)
|
||||
{
|
||||
struct kernel_version v;
|
||||
if (!kernel_version_current(&v)) {
|
||||
fprintf(stderr, "[!] af_packet2: could not parse kernel version\n");
|
||||
return IAMROOT_TEST_ERROR;
|
||||
}
|
||||
|
||||
/* Bug introduced in 4.6 (tpacket_rcv VLAN path). Pre-4.6 immune. */
|
||||
if (v.major < 4 || (v.major == 4 && v.minor < 6)) {
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[+] af_packet2: kernel %s predates the bug (introduced in 4.6)\n",
|
||||
v.release);
|
||||
}
|
||||
return IAMROOT_OK;
|
||||
}
|
||||
|
||||
bool patched = kernel_range_is_patched(&af_packet2_range, &v);
|
||||
if (patched) {
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[+] af_packet2: kernel %s is patched\n", v.release);
|
||||
}
|
||||
return IAMROOT_OK;
|
||||
}
|
||||
|
||||
int userns_ok = can_unshare_userns();
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[i] af_packet2: kernel %s in vulnerable range\n", v.release);
|
||||
fprintf(stderr, "[i] af_packet2: user_ns+net_ns clone: %s\n",
|
||||
userns_ok == 1 ? "ALLOWED" :
|
||||
userns_ok == 0 ? "DENIED" : "could not test");
|
||||
}
|
||||
|
||||
if (userns_ok == 0) {
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[+] af_packet2: user_ns denied → unprivileged exploit unreachable\n");
|
||||
}
|
||||
return IAMROOT_PRECOND_FAIL;
|
||||
}
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[!] af_packet2: VULNERABLE — kernel in range AND user_ns reachable\n");
|
||||
}
|
||||
return IAMROOT_VULNERABLE;
|
||||
}
|
||||
|
||||
static iamroot_result_t af_packet2_exploit(const struct iamroot_ctx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
fprintf(stderr,
|
||||
"[-] af_packet2: exploit not yet implemented in IAMROOT.\n"
|
||||
" Status: 🔵 DETECT-ONLY. Reference: Or Cohen's PoC.\n"
|
||||
" Exploit shape: unshare userns → AF_PACKET socket → setsockopt\n"
|
||||
" TPACKET_V2 ring + crafted VLAN-tagged frame → heap underflow →\n"
|
||||
" cross-cache groom → kernel R/W → cred overwrite.\n");
|
||||
return IAMROOT_PRECOND_FAIL;
|
||||
}
|
||||
|
||||
static const char af_packet2_auditd[] =
|
||||
"# AF_PACKET VLAN LPE (CVE-2020-14386) — auditd detection rules\n"
|
||||
"# Same syscall surface as CVE-2017-7308 — share the iamroot-af-packet\n"
|
||||
"# key so one ausearch covers both. AF_PACKET socket creation from\n"
|
||||
"# non-root via userns is the canonical footprint.\n"
|
||||
"-a always,exit -F arch=b64 -S socket -F a0=17 -k iamroot-af-packet\n";
|
||||
|
||||
const struct iamroot_module af_packet2_module = {
|
||||
.name = "af_packet2",
|
||||
.cve = "CVE-2020-14386",
|
||||
.summary = "AF_PACKET tpacket_rcv VLAN integer underflow → heap-OOB write",
|
||||
.family = "af_packet",
|
||||
.kernel_range = "4.6 ≤ K, backports: 5.8.7 / 5.7.16 / 5.4.62 / 4.19.143 / 4.14.197 / 4.9.235",
|
||||
.detect = af_packet2_detect,
|
||||
.exploit = af_packet2_exploit,
|
||||
.mitigate = NULL,
|
||||
.cleanup = NULL,
|
||||
.detect_auditd = af_packet2_auditd,
|
||||
.detect_sigma = NULL,
|
||||
.detect_yara = NULL,
|
||||
.detect_falco = NULL,
|
||||
};
|
||||
|
||||
void iamroot_register_af_packet2(void)
|
||||
{
|
||||
iamroot_register(&af_packet2_module);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* af_packet2_cve_2020_14386 — IAMROOT module registry hook
|
||||
*/
|
||||
|
||||
#ifndef AF_PACKET2_IAMROOT_MODULES_H
|
||||
#define AF_PACKET2_IAMROOT_MODULES_H
|
||||
|
||||
#include "../../core/module.h"
|
||||
|
||||
extern const struct iamroot_module af_packet2_module;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* stackrot_cve_2023_3269 — IAMROOT module
|
||||
*
|
||||
* "Stack Rot": UAF in maple-tree-based VMA splitting. The maple
|
||||
* tree replaced the rbtree-based VMA store in 6.1; during split,
|
||||
* the kernel could write to a maple node after it was freed via
|
||||
* RCU. Exploitable for kernel R/W → cred overwrite.
|
||||
*
|
||||
* Discovered by Ruihan Li (Peking University), Jul 2023. Famous
|
||||
* because it was the first significant exploit landed against the
|
||||
* (then-recently-merged) maple tree code, and because the original
|
||||
* disclosure included a public PoC that worked on default-config
|
||||
* Ubuntu 23.04.
|
||||
*
|
||||
* STATUS: 🔵 DETECT-ONLY. Public PoC is ~1000 lines (heavy maple
|
||||
* tree state management + RCU-grace-period timing); a clean port
|
||||
* into iamroot_module form is a substantial follow-up.
|
||||
*
|
||||
* Affected: kernel 6.1.x — 6.4-rc4 mainline. Stable backports:
|
||||
* 6.3.x : K >= 6.3.10
|
||||
* 6.1.x : K >= 6.1.37 (LTS — most relevant)
|
||||
* mainline 6.4-rc4+
|
||||
*
|
||||
* Pre-6.1 kernels are immune (no maple tree). 6.5+ are patched.
|
||||
*
|
||||
* Preconditions:
|
||||
* - Unprivileged user_ns (to gain CAP_SYS_ADMIN inside userns for
|
||||
* some triggers — actually the bug can be triggered without
|
||||
* userns via plain mprotect/munmap split operations)
|
||||
* - Default kernel config (CONFIG_USERFAULTFD recommended for
|
||||
* deterministic exploitation, but not strictly required)
|
||||
*
|
||||
* Coverage rationale: 2023 mm-class bug. Different family than our
|
||||
* netfilter-heavy 2022-2024 modules — broadens the corpus shape.
|
||||
* Affects the 6.1 LTS kernels still widely deployed.
|
||||
*/
|
||||
|
||||
#include "iamroot_modules.h"
|
||||
#include "../../core/registry.h"
|
||||
#include "../../core/kernel_range.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const struct kernel_patched_from stackrot_patched_branches[] = {
|
||||
{6, 1, 37},
|
||||
{6, 3, 10},
|
||||
{6, 4, 0}, /* mainline */
|
||||
};
|
||||
|
||||
static const struct kernel_range stackrot_range = {
|
||||
.patched_from = stackrot_patched_branches,
|
||||
.n_patched_from = sizeof(stackrot_patched_branches) /
|
||||
sizeof(stackrot_patched_branches[0]),
|
||||
};
|
||||
|
||||
static iamroot_result_t stackrot_detect(const struct iamroot_ctx *ctx)
|
||||
{
|
||||
struct kernel_version v;
|
||||
if (!kernel_version_current(&v)) {
|
||||
fprintf(stderr, "[!] stackrot: could not parse kernel version\n");
|
||||
return IAMROOT_TEST_ERROR;
|
||||
}
|
||||
|
||||
/* Bug introduced in 6.1 (when maple tree landed). Pre-6.1 kernels
|
||||
* use rbtree-based VMAs and don't have this bug. */
|
||||
if (v.major < 6 || (v.major == 6 && v.minor < 1)) {
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[+] stackrot: kernel %s predates maple-tree VMA code (introduced in 6.1)\n",
|
||||
v.release);
|
||||
}
|
||||
return IAMROOT_OK;
|
||||
}
|
||||
|
||||
bool patched = kernel_range_is_patched(&stackrot_range, &v);
|
||||
if (patched) {
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[+] stackrot: kernel %s is patched\n", v.release);
|
||||
}
|
||||
return IAMROOT_OK;
|
||||
}
|
||||
if (!ctx->json) {
|
||||
fprintf(stderr, "[!] stackrot: kernel %s in vulnerable range\n", v.release);
|
||||
fprintf(stderr, "[i] stackrot: mm-class bug — affects default-config kernels; "
|
||||
"no exotic preconditions\n");
|
||||
}
|
||||
return IAMROOT_VULNERABLE;
|
||||
}
|
||||
|
||||
static iamroot_result_t stackrot_exploit(const struct iamroot_ctx *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
fprintf(stderr,
|
||||
"[-] stackrot: exploit not yet implemented in IAMROOT.\n"
|
||||
" Status: 🔵 DETECT-ONLY. Reference: Ruihan Li's public PoC\n"
|
||||
" (~1000 lines maple-tree state + RCU grace period timing).\n"
|
||||
" Exploit shape: mmap many VMAs → split via mprotect to trigger\n"
|
||||
" maple node use-after-RCU → cross-cache groom → kernel R/W\n"
|
||||
" → cred overwrite.\n");
|
||||
return IAMROOT_PRECOND_FAIL;
|
||||
}
|
||||
|
||||
static const char stackrot_auditd[] =
|
||||
"# StackRot (CVE-2023-3269) — auditd detection rules\n"
|
||||
"# Hard to detect via syscall hooks alone — the trigger is mprotect/\n"
|
||||
"# munmap with specific VMA-split patterns. Flag unusual high-volume\n"
|
||||
"# mprotect bursts from non-root processes.\n"
|
||||
"-a always,exit -F arch=b64 -S mprotect -F success=1 -k iamroot-stackrot\n";
|
||||
|
||||
const struct iamroot_module stackrot_module = {
|
||||
.name = "stackrot",
|
||||
.cve = "CVE-2023-3269",
|
||||
.summary = "maple-tree VMA-split UAF (StackRot) → kernel R/W → cred overwrite",
|
||||
.family = "stackrot",
|
||||
.kernel_range = "6.1 ≤ K < 6.4-rc4, backports: 6.3.10 / 6.1.37 (LTS)",
|
||||
.detect = stackrot_detect,
|
||||
.exploit = stackrot_exploit,
|
||||
.mitigate = NULL,
|
||||
.cleanup = NULL,
|
||||
.detect_auditd = stackrot_auditd,
|
||||
.detect_sigma = NULL,
|
||||
.detect_yara = NULL,
|
||||
.detect_falco = NULL,
|
||||
};
|
||||
|
||||
void iamroot_register_stackrot(void)
|
||||
{
|
||||
iamroot_register(&stackrot_module);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* stackrot_cve_2023_3269 — IAMROOT module registry hook
|
||||
*/
|
||||
|
||||
#ifndef STACKROT_IAMROOT_MODULES_H
|
||||
#define STACKROT_IAMROOT_MODULES_H
|
||||
|
||||
#include "../../core/module.h"
|
||||
|
||||
extern const struct iamroot_module stackrot_module;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user