Websocket API Security
Websocket Security Model
Websocket APIs operate on a persistent, bidirectional connection that fundamentally differs from traditional HTTP APIs. Understanding this protocol's security model is crucial for identifying vulnerabilities.
The Websocket handshake begins as an HTTP request with an Upgrade header, then transitions to a persistent TCP connection. This dual-phase nature creates unique security considerations:
- Handshake authentication: Initial HTTP headers carry authentication tokens (Bearer tokens, cookies, API keys). If these aren't validated properly, attackers can establish unauthorized connections.
- Persistent state: Unlike REST APIs where each request is independent, Websocket connections maintain state. A compromised connection can persist for hours, continuously exposing data.
- Binary data handling: Websocket supports both text and binary frames. Improper validation of binary payloads can lead to deserialization attacks or buffer overflows.
- Subprotocol negotiation: The Sec-WebSocket-Protocol header allows clients and servers to agree on application-level protocols. Misconfigured subprotocol handling can enable protocol confusion attacks.
Transport security is typically implemented via WSS (Websocket Secure) over TLS, but the handshake itself occurs over HTTP, making it vulnerable to man-in-the-middle attacks if not properly secured. The persistent connection also means that certificate revocation or key rotation can be problematic—a connection established with compromised credentials remains valid until explicitly closed.
Websocket-Specific Vulnerabilities
Websocket APIs face several protocol-specific attack vectors that don't exist in traditional REST APIs:
Connection flooding: Attackers can establish hundreds of thousands of Websocket connections to exhaust server resources. Unlike HTTP where connections are short-lived, each Websocket connection consumes memory and file descriptors. A single IP can maintain thousands of connections, and with botnets, attackers can overwhelm even well-provisioned servers.
Unauthorized data access: Many Websocket implementations use connection-level authentication but fail to properly scope data access. An attacker who authenticates once can potentially access data from other users if the server doesn't validate ownership for each message. This is particularly dangerous in chat applications, collaborative tools, and real-time dashboards.
Message injection and replay: The persistent nature of Websocket connections makes them susceptible to message injection if the connection isn't properly authenticated. Additionally, since messages aren't independently authenticated like HTTP requests, replay attacks become more feasible. An attacker who captures a valid message can replay it multiple times.
Denial of Service via resource exhaustion: Websocket servers must buffer messages for slow or disconnected clients. Attackers can exploit this by establishing connections and failing to read messages, causing the server to buffer increasingly large amounts of data until memory is exhausted.
Subprotocol confusion: If a server negotiates subprotocols without proper validation, an attacker might switch to a different subprotocol mid-connection, potentially bypassing security controls designed for the expected protocol.
Real-world example: In 2021, a popular collaboration platform had a vulnerability where Websocket connections were authenticated but not properly scoped to workspaces. An attacker with a valid token could subscribe to notifications from any workspace, exposing sensitive communications across organizations.
Hardening Websocket APIs
Securing Websocket APIs requires a defense-in-depth approach that addresses the protocol's unique characteristics:
Connection-level authentication: Always revalidate authentication at connection establishment. Don't rely on HTTP session cookies alone—implement token-based authentication (JWT, API keys) that's validated during the Websocket handshake. Example:
app.get('/websocket', (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader || !validateToken(authHeader)) {
return res.status(401).send('Unauthorized');
}
// Establish connection only after successful auth
});
Per-message authorization: Never trust that a connection-level authentication grants access to all data. Validate permissions for every message, especially for data retrieval and modification operations. Implement row-level security or document-level access controls.
Connection limits and rate limiting: Implement connection limits per IP, user, and API key. Use sliding window algorithms to detect and block connection flooding. Consider exponential backoff for repeated connection attempts.
Input validation and sanitization: Validate all message formats, sizes, and content. Reject messages that exceed size limits or contain malformed data. Implement a strict schema for all message types and reject anything that doesn't conform.
Encryption and integrity: Always use WSS (Websocket Secure) over TLS. For highly sensitive applications, consider implementing message-level encryption where payloads are encrypted before transmission, even over WSS.
Monitoring and alerting: Track connection counts, message rates, and error patterns. Set up alerts for unusual activity like sudden connection spikes or repeated authentication failures. Log all security-relevant events for audit trails.
Timeouts and cleanup: Implement appropriate timeouts for idle connections and ensure proper cleanup of resources when connections close unexpectedly. Use heartbeat messages to detect dead connections and implement a maximum connection duration.
Testing with middleBrick: middleBrick's black-box scanning can identify Websocket-specific vulnerabilities including authentication bypasses, data exposure, and improper authorization. The scanner tests the unauthenticated attack surface and provides actionable findings with severity ratings and remediation guidance. For teams using middleBrick's Pro plan, continuous monitoring can alert you when new Websocket endpoints are deployed or when security scores change.