## https://sploitus.com/exploit?id=81D47119-80BF-5E81-B7D4-894970186697
# CVE-2026-74586 β SCTP ASCONF new_transport use-after-free trigger
A self-contained, unprivileged PoC for CVE-2026-74586, a use-after-free in
the Linux kernel's SCTP ASCONF (dynamic address reconfiguration) handling.
Credit for the bug itself goes to Qing Ming, who reported it upstream; the
fix is commit beb33f8ee1ca ("sctp: clear new_transport when removing a
peer"), merged 2026-08-12 with `Cc: stable` β Red Hat rates it important,
third-party trackers put it at CVSS 9.8.
What this repo adds on top of the advisory:
- a working raw-packet trigger, no kernel patches or special tools needed
- measured reliability on a stock distro kernel: **1,394 hits in 1,397
automated runs (99.8%)** against Kali's 7.1.5+kali-amd64
- the three injection barriers that have to be solved for any raw ASCONF
work, since the kernel silently drops the packet otherwise
- struct offsets for the 7.1.5 sctp module (from objdump, not guesswork)
and notes on how far weaponization gets before it hits a hard wall
## The bug
`sctp_process_asconf_param()` stores the transport created by an ADD-IP
parameter in `asoc->new_transport`. A DEL-IP for the same address in the
same ASCONF chunk frees that transport through `sctp_assoc_rm_peer()`,
which (before the fix) does not clear `new_transport`. When
`sctp_process_asconf()` returns, `sctp_sf_do_asconf()` acts on the stale
pointer β on a stock kernel the visible effect is a HEARTBEAT emitted
toward the address of the just-freed transport; under KASAN it's a
slab-use-after-free report.
One ASCONF chunk is enough:
```
[Address Parameter L] [ADD-IP G] [DEL-IP G]
```
## Building and running
```
gcc -O2 -Wall -o poc poc.c
./poc
```
No root. The PoC unshares a user + network namespace, sets the SCTP
sysctls in it, brings up a multi-homed association over loopback, then
injects the crafted ASCONF with a raw socket.
Expected output on a vulnerable kernel:
```
[+] Association established (no AUTH)
[+] server_vtag=0x... captured_tsn=0x...
[*] serial=0x... (= initial_tsn)
[+] Injected 60 bytes
[9222->9111 vt=...] ASCONF-ACK(0x80) len=8
[+] ASCONF-ACK -> server processed ADD-IP + DEL-IP
[9222->9111 vt=...] HB(0x04) len=60 9222 vt=...] ABORT(0x06) len=8
[+] GhostTransport UAF TRIGGERED (ASCONF-ACK received)
[+] HEARTBEAT to ghost address observed (dangling transport USED)
```
The HEARTBEAT after the ACK is the interesting part: that packet only
exists because the kernel walked the dangling `new_transport`. The client
ABORTs right after because the heartbeat came back out-of-the-blue.
## Why raw injection is annoying (the three barriers)
None of this is novel research, it's just undocumented enough to cost an
afternoon, so here it is for the next person:
1. **CRC32c.** Loopback does not hand you CHECKSUM_UNNECESSARY for raw
socket packets, so `sctp_rcv()` verifies the checksum and drops on
mismatch. Compute CRC32C (poly 0x82F63B78, reflected) over the whole
SCTP packet with the checksum field zeroed.
2. **The second auth check.** `sctp_auth_recv_cid()` runs in the input
path *before* the state machine and drops unauthenticated ASCONF even
when `addip_noauth_enable=1` β that sysctl only relaxes the check
inside `sctp_sf_do_asconf()`. The way out is to never negotiate AUTH
at the socket level in the first place (no `SCTP_AUTH_SUPPORTED`
setsockopt), so `peer.auth_capable` stays false and both checks pass.
3. **The serial.** First accepted ASCONF serial = peer's initial TSN.
Capture any DATA chunk, take its TSN, subtract one. Off-by-one here
and the chunk is silently discarded.
## Affected / fixed
The `Fixes:` tag on the upstream commit is 6af29ccc223b ("sctp: Bundle
HEARTBEAT into ASCONF_ACK"), so the code is old. Fixed in mainline and
backported to the stable series (Debian tracker: fixed from 7.1.9-1 in
sid, 6.12.107 in trixie-security). Kali rolling as of 2026-09-09 ships
7.1.5-1kali1 in every suite, which predates all of it β that's the main
practical relevance of this PoC.
## Weaponization notes (where this stops)
For anyone taking it further β measured against 7.1.5 in QEMU, offsets
from `objdump -d` of the shipped `sctp.ko`:
| field | offset |
|---|---|
| flowi | 0x30 |
| ipaddr | 0x68 |
| af_specific | 0xa8 |
| asoc | 0xb0 |
| dst | 0xe0 |
| state | 0x15c |
| rcu | 0x2b0 |
- The free is single (RCU callback `sctp_transport_destroy_rcu`), there
is no double-free on this path. If you were hoping to close a socket
and get two frees β `sctp_association_free()` only walks the transport
list, and `rm_peer()` already unlinked the ghost. Don't spend an
evening on that.
- `sctp_outq_select_transport()` reads `state` at +0x15c off
`chunk->transport` at +0xe8 of the chunk. A reclaimed object sprayed
with `state=1` (ACTIVE) changes kernel behavior after the free β the
object is being consulted.
- The gate past that is the empty-list check on +0x288: the kernel
compares `*(p+0x288)` against `p+0x288`. That is a self-pointer. You
cannot spray your way past it without knowing the slab address, i.e.
this bug needs an info leak before `af_specific` control turns into
instruction-pointer control. `af_specific` itself is an indirect call
site (`*(af_specific+0x18)` with rdi = transport), so that's the prize
once a leak exists.
- Spray primitive that works: `setsockopt(SCTP_AUTH_KEY)` with an 800-byte
key lands in the same kmalloc-1k cache. Remember the header is
`struct sctp_authkey { assoc_id; keynumber; keylength; key[] }` and
AUTH needs enabling per-socket first via `SCTP_AUTH_SUPPORTED` with an
`sctp_assoc_value` β a plain int gets EINVAL.
## Scope
This is a trigger/crash PoC. It is not a privilege escalation and this
repo does not claim one. Run it against your own kernels in a VM.
Tested on: 7.1.5+kali-amd64 (Kali rolling) and 7.0.12+kali-amd64.
## References
- Fix: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=beb33f8ee1ca83acddb2a5ae80f3d22ec550b4c3
- Debian tracker: https://security-tracker.debian.org/tracker/CVE-2026-74586
- Original report by Qing Ming (lore link in the commit message)
## License
GPL-2.0 for the kernel-derived portions of the logic; do whatever you
want with the rest. For authorized security testing and research only.