Skip to content
← All posts
Tutorial

Why Your WAF Misses WebSocket Attacks (And What to Do About It)

WebSocket traffic is invisible to most WAFs and CDNs. Learn how CSWSH, injection attacks, and frame anomalies bypass traditional security, and how to detect them at the wire level.

If your platform has a chat feature, a real-time dashboard, a trading interface, a live order tracker, or a collaborative document editor, you are almost certainly running WebSocket connections in production. And if you are relying on a traditional Web Application Firewall to secure them, you have a blind spot that attackers have been quietly exploiting since 2018.

This article walks through the four classes of WebSocket attacks that bypass conventional security tooling, why they bypass it, and what detection actually looks like when it works.

WebSocket is a protocol your WAF was not designed to read

A WAF inspects HTTP requests one at a time. Each request is a self-contained event with headers, a method, a path, and a body. The WAF reads it, applies pattern rules, and lets it through or blocks it.

WebSocket breaks every assumption in that model.

A WebSocket connection begins with a single HTTP request — the upgrade handshake — and then transitions to a long-lived, bidirectional, binary-framed channel. After that handshake, your WAF sees nothing. Hundreds or thousands of messages flow in both directions over the same connection, and the WAF has no inspection point for any of them. It cannot read message bodies. It cannot see frame headers. It cannot tell you what is being sent or received.

This is not a configuration issue. It is an architectural limit of how WAFs were built. Most commercial WAFs explicitly state that WebSocket inspection beyond the handshake is not supported, or is supported only in a degraded mode that buffers entire connections and breaks real-time use cases.

The result: a significant portion of your application’s runtime traffic is invisible to your security stack.

The four attack classes that exploit this blind spot

1. Cross-Site WebSocket Hijacking (CSWSH)

CSWSH is the WebSocket equivalent of CSRF, and it is more dangerous because the attack window stays open for the entire session.

The attack works as follows. A user logs into your application and a WebSocket connection is established, authenticated via cookies. The user later visits a malicious page in another tab. That page silently opens a WebSocket connection back to your application using the JavaScript WebSocket API. Because the browser automatically sends authentication cookies on the WebSocket handshake, the new connection is authenticated as the user. The attacker now has a live, bidirectional channel into your application, executing actions as the victim.

What makes CSWSH particularly insidious is that the malicious page can keep the hijacked connection open and silently exfiltrate data, send commands, or modify state for as long as the user keeps the tab open. There is no warning to the user, no interaction required, and no log entry that distinguishes the hijacked connection from a legitimate one — unless you have specific origin validation in place.

Defending against CSWSH requires strict server-side Origin header validation on every WebSocket handshake, anti-CSRF tokens carried into the WebSocket session, and ideally per-message authentication tokens. Most production deployments enforce none of these.

2. Injection attacks inside WebSocket messages

WebSocket messages typically carry JSON payloads. Those payloads end up in the same backend code paths that handle HTTP request bodies — sometimes literally the same parsing functions. Which means every injection vulnerability that exists in your REST API also exists in your WebSocket layer, except now there is nothing inspecting the traffic.

SQL injection inside a WebSocket message looks identical to SQL injection inside an HTTP body. The attacker sends {"productId": "1' OR 1=1--"} over the open channel. Your backend parses the JSON, hands the value to a query builder, and the database executes the injected SQL. The WAF that would have blocked this at the HTTP layer never sees the message.

The same applies to NoSQL injection, command injection in shell-backed handlers, LDAP injection, XML/XPath injection, and template injection. Each of these is well-understood in HTTP. None of them is inspected in WebSocket flows by default. Penetration testers consistently report finding injection vulnerabilities in WebSocket message handlers that would have been caught immediately if the same payloads had been sent over HTTP.

3. Frame anomalies and fragmentation abuse

The WebSocket protocol (RFC 6455) allows messages to be split across multiple frames. A single logical message can be sent as a sequence of fragmented frames with continuation opcodes. This is legitimate behavior — useful for streaming large payloads — but it is also a vector for evasion and resource exhaustion.

An attacker can send a message split across thousands of one-byte fragments. Each fragment is technically valid, but the cumulative effect forces your server to maintain reassembly state for an attacker-controlled duration. Multiplied across many connections, this is a low-bandwidth denial-of-service that bypasses traditional rate limiting (each fragment is small and individually innocuous).

Other frame-level anomalies include unmasked frames from clients (forbidden by spec but accepted by some servers), reserved bits set in the frame header (used for some extension protocols, but often a fingerprint of malformed or malicious clients), and oversized control frames (control frames are limited to 125 bytes; longer ones may exploit server parser bugs).

These are protocol-layer attacks. They do not look like application traffic. They look like normal — if slightly unusual — protocol behavior. Application-layer logging will not catch them. Network-layer firewalls do not understand the WebSocket frame format. You need wire-level visibility to see them.

4. Authentication and session weaknesses

WebSocket authentication is almost always handled at the handshake. The server validates the cookie or token, accepts the upgrade, and the connection runs for the next thirty minutes — or two hours, or until the user closes the tab — with no further authentication checks.

This creates two problems.

First, if a session token is compromised mid-session — through XSS, malware on the user’s machine, or token theft from local storage — the attacker can ride the existing WebSocket connection until it disconnects. There is no per-message authentication to revoke.

Second, many WebSocket implementations accept tokens via URL query parameters during the handshake (wss://example.com/ws?token=abc123). Tokens in URLs end up in browser history, referrer headers, server access logs, and proxy logs. Anyone with access to any of those gets the token.

Best practice is to authenticate via custom headers or a post-handshake authentication frame, and to validate and rotate tokens periodically within the session. In practice, most production WebSocket deployments inherit whatever the initial handshake authenticated and trust the connection for its full lifetime.

What detection actually requires

The common thread across these four attack classes is that they happen inside WebSocket frames after the handshake — exactly where WAFs cannot see. Any detection approach that depends on HTTP-layer inspection misses all of them.

Effective detection requires three capabilities working together.

Wire-level visibility. Whatever sees the traffic must read raw WebSocket frames as they pass through the kernel, before any application-layer abstraction. At Cyron, the iris eBPF agent attaches at the Linux kernel layer and reads HTTP, WebSocket, and gRPC traffic at the wire level — including every frame on every WebSocket connection — without sitting in the request path.

Protocol-aware parsing. Reading bytes is not enough. The detection layer must understand the WebSocket framing format, fragmentation reassembly, masking rules, control versus data frames, and the JSON or binary payload structure inside each message. Cyron’s WebSocket analyzer parses 43 wire-native features per frame across opcode patterns, frame structure, payload entropy, fragmentation behavior, and message timing.

Behavioral baselining. Once you have the right features, you need a model that distinguishes normal from anomalous traffic. Static rules (“block messages containing the string SELECT”) generate false positives and miss novel attacks. Behavioral models that learn each connection’s typical message rate, payload sizes, opcode distribution, and timing patterns flag genuine anomalies — credential brute-forcing, exfiltration spikes, fragmentation abuse — without false positives on legitimate traffic shape.

A practical checklist for your team

If you are running WebSocket in production today, the following audit will surface most of the common risks:

  • Enforce strict Origin header validation on every WebSocket handshake. Reject any handshake from an origin not on your explicit allow-list.
  • Require an anti-CSRF token in the handshake or first message, separate from the session cookie.
  • Authenticate every message inside the WebSocket connection, not just the handshake. Re-validate tokens periodically within the session.
  • Never accept tokens in URL query parameters. Use custom headers or post-handshake auth frames.
  • Apply input validation and parameterized queries to WebSocket message payloads identically to HTTP bodies. The same backend code paths need the same defenses.
  • Set explicit limits on message size, fragment count per message, and connection lifetime. Disconnect connections that exceed limits.
  • Log every WebSocket connection with origin, authenticated user, message count, and bytes transferred. These logs make breach forensics possible.
  • Add a wire-level detection layer that reads frames inside the connection. Without this, every other control above is enforced only by trust in your own code.

What this looks like in production

When the iris agent runs on a host carrying WebSocket traffic, it identifies WebSocket upgrades in the kernel, follows the resulting connection, and mirrors every frame to the Cyron analysis engine in real time. The engine extracts wire-native features per frame, scores them against the learned baseline for that connection class, and emits a structured incident when behavior crosses the threshold.

The detection runs out-of-band. Your application’s WebSocket traffic continues uninterrupted at full speed because the analysis engine is reading a mirrored copy, not sitting in the live request path. When a threat is identified — CSWSH attempt, injection payload, fragmentation abuse, session anomaly — iris blocks the offending source at the kernel layer for subsequent requests, with mean detect-to-action under two milliseconds.

You can see this running on a live demo at p-360.cloud, and the full WebSocket detection walkthrough is on the Cyron YouTube channel.

Try It on Your Own APIs

Cyron’s free plan includes WebSocket threat detection across all message types. No credit card. No deployment commitment. Pull the iris container, point it at your hosts, and the analysis engine starts surfacing WebSocket anomalies inside your traffic within ten minutes.

If your APIs are running real-time traffic right now and nothing is watching them at the wire level, that is the gap this was built for. Start free at cyron.io.