SIPSorcery TurnServer UDP Receive Loop Denial of Service
A single malformed UDP packet sent to a SIPSorcery TURN server permanently kills UDP relay for all connected clients, requiring a full process restart to recover.

The problem
SIPSorcery ships a TURN server component (TurnServer.cs) whose UDP receive loop is structurally unsafe. The generic catch(Exception) handler sits outside the while loop, so any unhandled exception in datagram processing unwinds the entire loop rather than dropping just the bad packet.
Start() launches ReceiveUdpAsync() fire-and-forget with no supervision or restart. Once the loop dies, _running stays true but nothing calls ReceiveUdpAsync() again, leaving TURN UDP relay dead for all clients until the process is manually restarted. This is exploitable pre-authentication, before any TURN allocation or credential check.
Proof of concept
A working proof-of-concept for this issue in SIPSorcery, with the exact payload below.
# Send one UDP datagram to the TURN port (default 3478)
# First byte 0x80 bypasses the ChannelData branch (needs 0x40) and
# hits ParseSTUNHeader, which throws ApplicationException on any byte
# where (b & 0xC0) != 0. 0x80 & 0xC0 = 0x80, so the throw fires.
echo -ne '\x80\x00\x00\x00' | nc -u -w1 <TURN_HOST> 3478HandleUdpDatagram() routes any datagram whose first byte fails the ChannelData check (first byte & 0xC0 == 0x40) into ParseSTUNMessage(). ParseSTUNMessage() calls ParseSTUNHeader(), which executes if ((Array[startIndex] & 0xC0) != 0) throw new ApplicationException(...) (STUNHeader.cs:169-172).
A first byte of 0x80 satisfies 0x80 & 0xC0 = 0x80 != 0, so the throw is guaranteed.
Because HandleUdpDatagram() at line 569 of TurnServer.cs is called inside the while body but outside the inner try block (lines 562-567), the ApplicationException propagates directly to the outer catch at line 573, which logs it and returns, terminating the loop.
The fix (commit ccb0b5a) wraps HandleUdpDatagram in a per-datagram try/catch inside the while loop so malformed packets are dropped and the loop continues, matching the drop-and-continue pattern used in the earlier UdpReceiver fix. CWE-755 (Improper Handling of Exceptional Conditions) and CWE-248 (Uncaught Exception).
The fix
Upgrade SIPSorcery to 10.0.14 or later (NuGet). The patch commit ccb0b5a845efa2fb131fd00de4f5321bae627f29 moves the exception handler inside the while loop so a bad datagram is logged and dropped without killing the receive loop.
Reported by zx (Jace).
Related research
- high · 7.5SIPSorcery SCTP SACK Chunk Out-of-Bounds Read DoS
- high · 7.5CVE-2026-54632CVE-2026-54632: SIPSorcery Remote DoS via Malformed UDP Packet on RTP/ICE Socket
- high · 7.1CVE-2026-48798CVE-2026-48798: SSH.NET ScpClient Recursive Download Path Traversal
- high · 7CVE-2026-62897CVE-2026-62897: .NET WPF Integer Overflow Remote Code Execution