102b117d4e
Two famous 2017-2020-era LPEs to broaden 'THE tool for folks' coverage. Both detect-only initially; exploit ports as follow-ups. ptrace_traceme (CVE-2019-13272 — jannh @ Google P0, Jun 2019): - Famous because works on default-config systems with no user_ns required — locked-down environments were still vulnerable. - kernel_range thresholds: 4.4.182 / 4.9.182 / 4.14.131 / 4.19.58 / 5.0.20 / 5.1.17 / mainline 5.2+ - Exploit shape (deferred): fork → child PTRACE_TRACEME → parent execve setuid binary → child ptrace-injects shellcode → root. - Auditd: flag PTRACE_TRACEME (request 0) — false positives via gdb/strace; tune by exclusion. netfilter_xtcompat (CVE-2021-22555 — Andy Nguyen @ Google P0): - Bug existed since 2.6.19 (2006) — 15 years of latent vuln. Famous for that age + default-config reachability via unprivileged_userns. - kernel_range thresholds: 4.4.266 / 4.9.266 / 4.14.230 / 4.19.185 / 5.4.110 / 5.10.27 / 5.11.10 / mainline 5.12+ - detect() probes user_ns+net_ns clone; locked-down → PRECOND_FAIL. - Exploit shape (deferred): heap massage via msg_msg + sk_buff cross- cache groom → kernel R/W → cred or modprobe_path overwrite. ~400 lines port from Andy's public exploit.c. - Auditd: unshare + iptables-style setsockopt + msgsnd — combined, the canonical exploit footprint. Both wired into iamroot.c, core/registry.h, Makefile. CVES.md rows added with detailed status. Coverage by year now: 2016: dirty_cow 🟢 2019: ptrace_traceme 🔵 2021: pwnkit, overlayfs, netfilter_xtcompat 🟢/🟢/🔵 2022: dirty_pipe, cls_route4 🟢/🔵 2023: entrybleed 🟢 2024: nf_tables 🔵 2026: copy_fail family (×5) 🟢 Module count: 14. Build clean (no warnings).
128 lines
4.7 KiB
C
128 lines
4.7 KiB
C
/*
|
|
* ptrace_traceme_cve_2019_13272 — IAMROOT module
|
|
*
|
|
* PTRACE_TRACEME on a parent that subsequently execve's a setuid
|
|
* binary results in the kernel granting ptrace privileges over the
|
|
* privileged process to the unprivileged child. Discovered by Jann
|
|
* Horn (Google Project Zero, June 2019).
|
|
*
|
|
* STATUS: 🔵 DETECT-ONLY. Exploit follows jannh's public PoC: fork
|
|
* a child that does PTRACE_TRACEME pointing at the parent, parent
|
|
* execve's a chosen setuid binary (e.g., su, pkexec), child then
|
|
* ptrace-injects shellcode into the now-elevated process.
|
|
*
|
|
* Affected: kernels < 5.1.17 mainline. Stable backports varied; the
|
|
* fix landed in stable as:
|
|
* 5.1.x : K >= 5.1.17
|
|
* 5.0.x : K >= 5.0.20 (older LTS — many distros stayed on 4.x)
|
|
* 4.19.x: K >= 4.19.58
|
|
* 4.14.x: K >= 4.14.131
|
|
* 4.9.x : K >= 4.9.182
|
|
* 4.4.x : K >= 4.4.182
|
|
*
|
|
* No exotic preconditions. Doesn't need user_ns. Works on
|
|
* default-config systems — that's part of why it's famous: even
|
|
* locked-down environments without unprivileged_userns_clone were
|
|
* vulnerable.
|
|
*/
|
|
|
|
#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 ptrace_traceme_patched_branches[] = {
|
|
{4, 4, 182},
|
|
{4, 9, 182},
|
|
{4, 14, 131},
|
|
{4, 19, 58},
|
|
{5, 0, 20},
|
|
{5, 1, 17},
|
|
{5, 2, 0}, /* mainline (5.2-rc) */
|
|
};
|
|
|
|
static const struct kernel_range ptrace_traceme_range = {
|
|
.patched_from = ptrace_traceme_patched_branches,
|
|
.n_patched_from = sizeof(ptrace_traceme_patched_branches) /
|
|
sizeof(ptrace_traceme_patched_branches[0]),
|
|
};
|
|
|
|
static iamroot_result_t ptrace_traceme_detect(const struct iamroot_ctx *ctx)
|
|
{
|
|
struct kernel_version v;
|
|
if (!kernel_version_current(&v)) {
|
|
fprintf(stderr, "[!] ptrace_traceme: could not parse kernel version\n");
|
|
return IAMROOT_TEST_ERROR;
|
|
}
|
|
|
|
/* Bug existed since ptrace's inception (early 2.x); anything
|
|
* pre-LTS-backport is vulnerable. Anything < 4.4 in our range
|
|
* model defaults to vulnerable since no entry covers it. */
|
|
if (v.major < 4 || (v.major == 4 && v.minor < 4)) {
|
|
if (!ctx->json) {
|
|
fprintf(stderr, "[!] ptrace_traceme: ancient kernel %s — assume VULNERABLE\n",
|
|
v.release);
|
|
}
|
|
return IAMROOT_VULNERABLE;
|
|
}
|
|
|
|
bool patched = kernel_range_is_patched(&ptrace_traceme_range, &v);
|
|
if (patched) {
|
|
if (!ctx->json) {
|
|
fprintf(stderr, "[+] ptrace_traceme: kernel %s is patched\n", v.release);
|
|
}
|
|
return IAMROOT_OK;
|
|
}
|
|
if (!ctx->json) {
|
|
fprintf(stderr, "[!] ptrace_traceme: kernel %s in vulnerable range\n", v.release);
|
|
fprintf(stderr, "[i] ptrace_traceme: no exotic preconditions — works on default config "
|
|
"(no user_ns required)\n");
|
|
}
|
|
return IAMROOT_VULNERABLE;
|
|
}
|
|
|
|
static iamroot_result_t ptrace_traceme_exploit(const struct iamroot_ctx *ctx)
|
|
{
|
|
(void)ctx;
|
|
fprintf(stderr,
|
|
"[-] ptrace_traceme: exploit not yet implemented in IAMROOT.\n"
|
|
" Status: 🔵 DETECT-ONLY. Reference: jannh's PoC.\n"
|
|
" Exploit shape: fork() → child calls PTRACE_TRACEME → parent\n"
|
|
" execve's a setuid binary (su, pkexec, ping with cap_net_raw,\n"
|
|
" etc.) → child becomes tracer of the now-privileged process\n"
|
|
" → ptrace-inject shellcode → root.\n");
|
|
return IAMROOT_PRECOND_FAIL;
|
|
}
|
|
|
|
static const char ptrace_traceme_auditd[] =
|
|
"# PTRACE_TRACEME LPE (CVE-2019-13272) — auditd detection rules\n"
|
|
"# Flag PTRACE_TRACEME (request 0) followed by parent execve of\n"
|
|
"# a setuid binary. False positives: gdb, strace, debuggers.\n"
|
|
"-a always,exit -F arch=b64 -S ptrace -F a0=0 -k iamroot-ptrace-traceme\n"
|
|
"-a always,exit -F arch=b32 -S ptrace -F a0=0 -k iamroot-ptrace-traceme\n";
|
|
|
|
const struct iamroot_module ptrace_traceme_module = {
|
|
.name = "ptrace_traceme",
|
|
.cve = "CVE-2019-13272",
|
|
.summary = "PTRACE_TRACEME → setuid binary execve → cred-escalation via ptrace inject",
|
|
.family = "ptrace_traceme",
|
|
.kernel_range = "K < 5.1.17, backports: 5.0.20 / 4.19.58 / 4.14.131 / 4.9.182 / 4.4.182",
|
|
.detect = ptrace_traceme_detect,
|
|
.exploit = ptrace_traceme_exploit,
|
|
.mitigate = NULL, /* mitigation: upgrade kernel; OR set ptrace_scope sysctl */
|
|
.cleanup = NULL,
|
|
.detect_auditd = ptrace_traceme_auditd,
|
|
.detect_sigma = NULL,
|
|
.detect_yara = NULL,
|
|
.detect_falco = NULL,
|
|
};
|
|
|
|
void iamroot_register_ptrace_traceme(void)
|
|
{
|
|
iamroot_register(&ptrace_traceme_module);
|
|
}
|