← Back to Feed CACHED · 2026-10-08 06:30:59 · CACHE_KEY CVE-2026-52924
CVE-2026-52924 · CWE-416 · Disclosed 2026-06-24

Linux Kernel SCTP Use-After-Free in Stale COOKIE-ECHO Rollback

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Kernel SCTP use-after-free is a reliable LPE, not the network RCE that CVSS 9.8 implies"
02 · The Attack Path

5 steps from start to impact.

STEP 01

SCTP module autoload

An unprivileged local user (or process inside a container) calls 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.
Conditions required:
  • 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)
Where this breaks in practice:
  • 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%
Detection/coverage: AuditD rule on socket() with IPPROTO_SCTP (protocol 132); Sigma rules for sctp module load events in dmesg/journalctl.
STEP 02

Initiate SCTP association and queue user data

The attacker opens an SCTP association to a peer (which can be a loopback address or attacker-controlled endpoint). Before the handshake completes, user data is queued and bundled with the COOKIE-ECHO chunk. The association enters COOKIE_ECHOED state with populated stream output queues.
Conditions required:
  • Step 1 succeeded — SCTP module loaded
  • Ability to open outbound network connections (loopback suffices)
Where this breaks in practice:
  • Host-level firewalls or network policy blocking outbound SCTP (rare default)
STEP 03

Trigger Stale Cookie ERROR rollback

The attacker-controlled peer (or loopback service) responds with a 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.
Conditions required:
  • Attacker controls the remote SCTP endpoint (trivial for LPE — just run both sides locally)
Where this breaks in practice:
  • None — the attacker controls both ends of the connection in the LPE scenario
STEP 04

Exploit dangling pointer for kernel read/write

The attacker reclaims the freed heap slab with controlled data (standard kernel heap-spray techniques — e.g., 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.
Conditions required:
  • Step 3 succeeded — dangling pointer exists
  • Standard heap-spray primitives available (no KASLR bypass needed for some techniques)
Where this breaks in practice:
  • 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
Detection/coverage: Kernel OOPS/panic logs if exploitation fails; EDR agents monitoring for unexpected uid transitions from unprivileged → root.
STEP 05

Root shell / container escape

With 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.
Conditions required:
  • Step 4 succeeded — arbitrary kernel write achieved
Where this breaks in practice:
  • 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
Detection/coverage: Host-based EDR detecting namespace escape artifacts (nsenter, unexpected mount of host /); Falco rules for container escape patterns.
03 · Compensating Control

1
HIGH 7.8→LOW 2.0
SEVERITY REDUCED
Blacklist the SCTP kernel module immediately — Create /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.
2
HIGH 7.8→MEDIUM 5.5
SEVERITY REDUCED
Drop CAP_NET_RAW and restrict socket creation in containers — Apply PodSecurityStandards (restricted profile) or OPA/Kyverno policies to drop 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.
3
HIGH 7.8→MEDIUM 5.0
SEVERITY REDUCED
Enable SELinux enforcing with strict container policies — SELinux in enforcing mode with 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
HIGH 7.8→IGNORE 0.0
SEVERITY REDUCED
Deploy patched kernels — Apply the vendor kernel update: RHEL 8 → 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.
What doesn't work
  • 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-tools or libsctp has zero effect.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNot 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-conceptPublic 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.
EPSS0.00526 (0.526%) — roughly 73rd percentile. Low probability of mass exploitation within 30 days, consistent with local-access requirement.
CISA KEVNot listed as of 2026-10-08.
CVSS vectorCVSS: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 versionsLinux 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 versionsUpstream: 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 / scanningSCTP 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 timelineBug introduced: October 2017. Disclosed and patched upstream: 2026-06-24. PoC published by NebuSec: ~July 2026. RHEL advisories: July–August 2026.
Reporting researcherUpstream kernel fix by SCTP maintainers. Weaponized PoC and root demonstration by NebuSec / CyberMeowfia research team.

Sources.

  1. NVD — CVE-2026-52924
  2. SecurityOnline — PoC Exploit Disclosed
  3. NebuSec PoC GitHub Repository
  4. Eliot-code CVE-2026-52924 Exploit Repo
  5. Debian Security Tracker
  6. Red Hat RHSA-2026:67471 (RHEL 10)
  7. Red Hat RHSA-2026:59737 (RHEL 8)
  8. SecurityArsenal — SCTP UAF Container Escape Guide
05 · The Call

Final Verdict
↓ DOWNGRADED to HIGH (7.8/10)

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_key reclamation) 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.

06 · Verification

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

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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