The vendor stamped a fire alarm on a locked interior door — it's still a real fire, just not the one visible from the street
CVE-2026-52924 is a use-after-free (CWE-416) in the Linux kernel's SCTP stack, present since kernel 4.15 (October 2017). When a Stale Cookie ERROR is received during an SCTP association handshake, the kernel rolls back from COOKIE_ECHOED to COOKIE_WAIT and calls sctp_stream_update(), which frees the old stream table and installs a new one — but fails to invalidate the stream->out_curr pointer. That dangling pointer still references the freed sctp_stream_out entry, and when the SCTP scheduler later dereferences stream->out_curr->ext, the result is a classic use-after-free. Affected stable branches include 5.10.x (before 5.10.259), 5.15.x (before 5.15.210), 6.1.x (before 6.1.176), 6.6.x (before 6.6.143), 6.12.x (before 6.12.94), 6.18.x (before 6.18.36), and 7.0.x (before 7.0.13). The flaw has been fixed via at least 16 upstream commits backported across all maintained stable branches.
The vendor CVSS of 9.8 CRITICAL with vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H is materially overstated for the vast majority of enterprise Linux deployments. The AV:N (network) designation implies an unauthenticated remote attacker can fire a packet at any Linux box and get code execution. In reality, remote exploitation requires the target to have an active SCTP listener — a protocol used almost exclusively in telecom (SS7/Diameter/5G core) and certain clustering stacks (Corosync). Fewer than 1% of enterprise Linux servers expose SCTP ports. The demonstrated exploitation path — weaponized by NebuSec with a public PoC — is local privilege escalation: an unprivileged user creates an SCTP socket (which autoloads the sctp kernel module on most distros), triggers the stale-cookie rollback, and leverages the UAF for arbitrary kernel read/write to gain root. That path corresponds to AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = CVSS 7.8 HIGH, not 9.8. The bug is serious — it's a reliable kernel LPE with container-escape potential — but calling it a 9.8 network-reachable RCE misleads defenders about where the real risk sits.
5 steps from start to impact.
SCTP module autoload
socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP). On most RHEL, Ubuntu, and Debian systems the sctp kernel module is not loaded by default but is autoloadable — the kernel's request_module() path loads it transparently. No capabilities or root required. Once loaded, the full SCTP code path is available to any user namespace.- Local shell or container exec on a Linux host running an unpatched kernel
- SCTP kernel module available and not blacklisted (default on RHEL 8/9/10, Ubuntu, Debian)
- Hardened container runtimes (gVisor, Kata) do not share the host kernel and block this
- Some CIS-benchmarked systems blacklist SCTP via
/etc/modprobe.d/; adoption is <10%
socket() with IPPROTO_SCTP (protocol 132); Sigma rules for sctp module load events in dmesg/journalctl.Initiate SCTP association and queue user data
COOKIE-ECHO chunk. The association enters COOKIE_ECHOED state with populated stream output queues.- Step 1 succeeded — SCTP module loaded
- Ability to open outbound network connections (loopback suffices)
- Host-level firewalls or network policy blocking outbound SCTP (rare default)
Trigger Stale Cookie ERROR rollback
STALE COOKIE ERROR. The kernel rolls the association back from COOKIE_ECHOED to COOKIE_WAIT and calls sctp_stream_update(), which frees the old stream table via sctp_stream_free(). Critically, stream->out_curr is not invalidated and continues pointing to the freed sctp_stream_out entry.- Attacker controls the remote SCTP endpoint (trivial for LPE — just run both sides locally)
- None — the attacker controls both ends of the connection in the LPE scenario
Exploit dangling pointer for kernel read/write
msgsnd() or add_key() slab reclamation). When the SCTP scheduler later dereferences stream->out_curr->ext, it reads attacker-controlled memory. NebuSec's PoC chains this into arbitrary kernel read/write primitives, then overwrites task_struct credentials to gain uid=0. The entire chain runs in seconds.- Step 3 succeeded — dangling pointer exists
- Standard heap-spray primitives available (no KASLR bypass needed for some techniques)
- CONFIG_SLAB_FREELIST_HARDENED and CONFIG_SLAB_FREELIST_RANDOM raise exploitation difficulty but do not prevent it
- RHEL 9+ and recent Ubuntu kernels enable these by default, making exploitation harder but not impossible
uid transitions from unprivileged → root.Root shell / container escape
uid=0 in the kernel's task_struct, the attacker has full root. In containerized environments, because containers share the host kernel, the attacker can mount the host filesystem, manipulate host processes, or break out of the namespace boundary entirely. Tencent researchers documented this container-escape path for related SCTP UAF bugs. On a Kubernetes node, this means compromise of all pods on that node and potential lateral movement via the kubelet credential.- Step 4 succeeded — arbitrary kernel write achieved
- Sandboxed runtimes (gVisor, Kata Containers) isolate the kernel and prevent this
- SELinux in enforcing mode with strict container policies can limit post-exploitation actions but does not prevent the UAF itself
nsenter, unexpected mount of host /); Falco rules for container escape patterns./etc/modprobe.d/blacklist-sctp.conf with blacklist sctp and install sctp /bin/false. This prevents both manual and autoload of the module, eliminating the entire attack surface. SCTP is unused in >99% of enterprise workloads. Verify with modprobe sctp returning an error. Deploy within 30 days per noisgate mitigation SLA for HIGH-severity findings. For container hosts and Kubernetes nodes, prioritize within 7 days given the container-escape blast radius.CAP_NET_RAW and enforce seccompProfile blocking SCTP socket creation (socket syscall with protocol 132). This prevents containerized workloads from triggering the vulnerable code path even if the module is loaded. Deploy within 30 days per noisgate mitigation SLA.container_t confined types limits post-exploitation actions even after UAF success — the attacker gains kernel write but SELinux restricts what root can access. Not a prevention control but significantly raises the cost of exploitation. Ensure setenforce 1 and SELINUX=enforcing in /etc/selinux/config.4.18.0-553.158.1, RHEL 10 → 6.12.0-211.55.1, Debian Bookworm → 6.1.176-1, Ubuntu → check linux-image for your series. This is the definitive fix. Per noisgate remediation SLA for HIGH, complete fleet-wide patching within 180 days. Prioritize container hosts and multi-tenant infrastructure.- Network firewalls / WAFs — blocking SCTP at the network edge does not help because the demonstrated exploit is local. The attacker creates both SCTP endpoints on the same host or uses loopback. Firewall rules only matter for the rare remote-exploitation scenario.
- KASLR alone — kernel address-space layout randomization raises the bar but the NebuSec PoC uses heap-spray techniques that do not require knowing kernel base addresses. KASLR is a speed bump, not a gate.
- AppArmor default profiles — default container AppArmor profiles do not restrict SCTP socket creation or block the specific syscall sequence used in the exploit chain.
- Patching userspace SCTP libraries (lksctp-tools) — the vulnerability is in the kernel, not in userspace libraries. Updating
lksctp-toolsorlibsctphas zero effect.
The supporting signals.
| In-the-wild exploitation | Not confirmed. Not listed on CISA KEV. No GreyNoise or Shadowserver telemetry showing active scanning for SCTP-based exploitation of this CVE as of 2026-10-08. However, the weaponized PoC lowers the barrier significantly. |
|---|---|
| Proof-of-concept | Public and weaponized. NebuSec (CyberMeowfia) published a full LPE exploit at github.com/NebuSec/CyberMeowfia, verified on Ubuntu kernel 7.0.0-28. A second independent repo by Eliot-code/CVE-2026-52924 includes sctp_exploit.c and sctp_cve_2026_52924_poc.c. Video demo posted on X by NebuSec showing reliable root in seconds. |
| EPSS | 0.00526 (0.526%) — roughly 73rd percentile. Low probability of mass exploitation within 30 days, consistent with local-access requirement. |
| CISA KEV | Not listed as of 2026-10-08. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (vendor). noisgate assessment: the realistic vector is AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H = 8.8 when accounting for container escape scope change, or AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 7.8 for non-containerized hosts. |
| Affected versions | Linux kernel 4.15+ through: 5.10.258, 5.15.209, 6.1.175, 6.6.142, 6.12.93, 6.18.35, 7.0.12. Bug introduced in commit circa October 2017. |
| Fixed versions | Upstream: 5.10.259, 5.15.210, 6.1.176, 6.6.143, 6.12.94, 6.18.36, 7.0.13. RHEL 8: 4.18.0-553.158.1.el8_10 (RHSA-2026:59737). RHEL 10: 6.12.0-211.55.1.el10_2 (RHSA-2026:67471). Debian Bookworm: 6.1.176-1 / 6.1.187-1. Debian Trixie: 6.12.107-1. Debian Sid: 7.2.9-1. Debian Bullseye: 5.10.259-1. |
| Exposure / scanning | SCTP port exposure is minimal in enterprise. Shodan shows ~12,000 hosts globally with SCTP ports (primarily telecom infrastructure). No GreyNoise tags for CVE-2026-52924 scanning activity. |
| Disclosure timeline | Bug introduced: October 2017. Disclosed and patched upstream: 2026-06-24. PoC published by NebuSec: ~July 2026. RHEL advisories: July–August 2026. |
| Reporting researcher | Upstream kernel fix by SCTP maintainers. Weaponized PoC and root demonstration by NebuSec / CyberMeowfia research team. |
Sources.
Why this verdict
- AV:N is overstated — realistic vector is AV:L. The 9.8 score assumes unauthenticated network-reachable exploitation. In practice, remote exploitation requires an active SCTP listener on the target. SCTP is used almost exclusively in telecom (SS7, Diameter, 5G core) and certain HA clustering. Fewer than 1% of enterprise Linux servers expose SCTP ports. The demonstrated PoC is a *local* privilege escalation — the attacker creates both ends of the SCTP association on the same host.
- SCTP module autoload preserves local attack surface. Despite SCTP's low usage, the kernel module is autoloadable by unprivileged users on default RHEL/Ubuntu/Debian installs via
socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP). This means any local shell — including a compromised web app, a malicious container tenant, or a low-privilege service account — can trigger the vulnerable code path. This keeps the local attack vector fully live. - Weaponized PoC makes exploitation reliable. NebuSec published a complete exploit achieving root in seconds on Ubuntu 7.0.0-28 kernels. A second independent repo (Eliot-code) provides additional exploit code. The exploit uses standard heap-spray techniques (
msgsnd/add_keyreclamation) and does not require KASLR bypass in all configurations. This is not theoretical. - Role multiplier: Container hosts / Kubernetes nodes. The Linux kernel is THE canonical high-value component. On container hosts, this LPE enables container escape because containers share the host kernel — Tencent researchers documented this path for related SCTP UAFs. A compromised K8s node exposes all co-resident pods and the kubelet credential. Container/K8s nodes represent >20% of enterprise Linux deployments, making this a fleet-scale blast radius scenario. This sets the verdict floor at HIGH.
- Role multiplier: Database and application servers. On production database hosts (PostgreSQL, MySQL, MongoDB), a local shell escalated to root means full data access. On CI/CD runners, it means supply-chain compromise. These are common Linux deployment roles — the kernel bug affects them all equally.
- No in-the-wild exploitation yet, not KEV-listed. EPSS at 0.526% and zero confirmed exploitation provide downward pressure against CRITICAL. The local-access prerequisite means mass exploitation requires a different initial-access vector first.
Why not higher?
The verdict stops short of CRITICAL because the realistic attack vector is local, not network. The AV:N score would require an SCTP listener, which is present on <1% of enterprise hosts (mostly telecom). There is no confirmed in-the-wild exploitation, no CISA KEV listing, and EPSS remains below 1%. Mass remote exploitation is not feasible against the general enterprise population. The exploit is powerful post-compromise tooling, but it does not provide initial access.
Why not lower?
The verdict cannot go below HIGH because: (1) the Linux kernel is the canonical high-value component — every server, container host, and K8s node runs it; (2) the SCTP module is autoloadable by unprivileged users on default installs, so the attack surface exists even where SCTP is not intentionally used; (3) the public PoC is weaponized and reliable, achieving root in seconds; (4) container escape enables fleet-scale blast radius on any multi-tenant container host, which represents a significant fraction of the installed base. A MEDIUM rating would ignore the deployment-role blast radius.
Crowdsourced verification payload.
Run this script on each target Linux host as root (or via sudo). It checks the running kernel version against known-fixed versions for each stable branch and whether the SCTP module is loadable. Invoke: sudo bash check_cve_2026_52924.sh
#!/bin/bash
# CVE-2026-52924 Checker — Linux kernel SCTP stale COOKIE-ECHO UAF
# Run as root on the target host.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
KERNEL=$(uname -r)
VERSION=$(echo "$KERNEL" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')
if [ -z "$VERSION" ]; then
echo "UNKNOWN — could not parse kernel version from: $KERNEL"
exit 2
fi
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3)
# Check if SCTP module is available (loadable)
SCTP_AVAIL="no"
if modprobe --dry-run sctp 2>/dev/null; then
SCTP_AVAIL="yes"
elif lsmod | grep -q '^sctp '; then
SCTP_AVAIL="loaded"
fi
echo "Kernel version: $KERNEL (parsed: $MAJOR.$MINOR.$PATCH)"
echo "SCTP module available: $SCTP_AVAIL"
if [ "$SCTP_AVAIL" = "no" ]; then
echo "PATCHED (mitigated) — SCTP module is not loadable on this system."
exit 0
fi
# version_gte: returns 0 if $1.$2.$3 >= $4.$5.$6
version_gte() {
local a1=$1 a2=$2 a3=$3 b1=$4 b2=$5 b3=$6
if [ "$a1" -gt "$b1" ] 2>/dev/null; then return 0; fi
if [ "$a1" -lt "$b1" ] 2>/dev/null; then return 1; fi
if [ "$a2" -gt "$b2" ] 2>/dev/null; then return 0; fi
if [ "$a2" -lt "$b2" ] 2>/dev/null; then return 1; fi
if [ "$a3" -ge "$b3" ] 2>/dev/null; then return 0; fi
return 1
}
VULN="UNKNOWN"
case "$MAJOR.$MINOR" in
4.14|4.13|4.12|4.11|4.10|4.9|4.8|4.7|4.6|4.5|4.4)
# Kernels before 4.15 are NOT affected (bug introduced in 4.15)
VULN="PATCHED"
;;
4.15|4.16|4.17|4.18|4.19|4.20)
# 4.15+ but before 5.x — affected, check RHEL backports
# RHEL 8 uses 4.18.0-553.158.1+ as fix
if echo "$KERNEL" | grep -q 'el8'; then
RHEL_REL=$(echo "$KERNEL" | grep -oP '\d+-\K\d+\.\d+' | head -1)
if [ -n "$RHEL_REL" ]; then
RHEL_MAJOR=$(echo "$RHEL_REL" | cut -d. -f1)
if [ "$RHEL_MAJOR" -ge 553 ] 2>/dev/null; then
RHEL_MINOR=$(echo "$RHEL_REL" | cut -d. -f2)
if [ "$RHEL_MAJOR" -gt 553 ] || [ "$RHEL_MINOR" -ge 158 ] 2>/dev/null; then
VULN="PATCHED"
else
VULN="VULNERABLE"
fi
else
VULN="VULNERABLE"
fi
else
VULN="VULNERABLE"
fi
else
VULN="VULNERABLE"
fi
;;
5.10)
version_gte $MAJOR $MINOR $PATCH 5 10 259 && VULN="PATCHED" || VULN="VULNERABLE"
;;
5.15)
version_gte $MAJOR $MINOR $PATCH 5 15 210 && VULN="PATCHED" || VULN="VULNERABLE"
;;
5.4|5.5|5.6|5.7|5.8|5.9|5.11|5.12|5.13|5.14|5.16|5.17|5.18|5.19)
# 5.x branches between 4.15 and 5.10 or between stable branches — affected, EOL
VULN="VULNERABLE"
;;
6.1)
version_gte $MAJOR $MINOR $PATCH 6 1 176 && VULN="PATCHED" || VULN="VULNERABLE"
;;
6.6)
version_gte $MAJOR $MINOR $PATCH 6 6 143 && VULN="PATCHED" || VULN="VULNERABLE"
;;
6.12)
version_gte $MAJOR $MINOR $PATCH 6 12 94 && VULN="PATCHED" || VULN="VULNERABLE"
;;
6.18)
version_gte $MAJOR $MINOR $PATCH 6 18 36 && VULN="PATCHED" || VULN="VULNERABLE"
;;
7.0)
version_gte $MAJOR $MINOR $PATCH 7 0 13 && VULN="PATCHED" || VULN="VULNERABLE"
;;
7.1|7.2)
version_gte $MAJOR $MINOR $PATCH 7 2 8 && VULN="PATCHED" || VULN="VULNERABLE"
;;
*)
if [ "$MAJOR" -ge 8 ] 2>/dev/null; then
VULN="PATCHED"
elif [ "$MAJOR" -lt 4 ] 2>/dev/null; then
VULN="PATCHED"
else
VULN="UNKNOWN"
fi
;;
esac
if [ "$VULN" = "VULNERABLE" ]; then
echo "VULNERABLE — kernel $KERNEL is affected by CVE-2026-52924 and SCTP module is $SCTP_AVAIL."
exit 1
elif [ "$VULN" = "PATCHED" ]; then
echo "PATCHED — kernel $KERNEL is at or above the fixed version for this branch."
exit 0
else
echo "UNKNOWN — could not determine patch status for kernel $KERNEL. Manual review required."
exit 2
fi