Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Academy WebSocket Security
Advanced · 25 min

WebSocket Security

Understand WebSocket-specific attacks including missing authentication and cross-site WebSocket hijacking.

1 WebSocket Attack Vectors

WebSockets establish persistent bidirectional connections. They have unique security characteristics that differ from regular HTTP requests.

1. Missing authentication on upgrade:

// Vulnerable: no auth check on WebSocket connection
wss.on("connection", (ws, req) => {
  // req.headers contains cookies and other headers
  // But no verification that the user is authenticated!
  ws.on("message", handleMessage);
});

2. Cross-site WebSocket hijacking:

WebSocket connections send cookies automatically (like HTTP requests). If the server does not validate the Origin header, a malicious page can establish a WebSocket connection to your server using the victim's session cookie:

// Attacker's page — connects to victim's WebSocket server
const ws = new WebSocket("wss://victim-bank.com/ws");
// Browser automatically includes victim's session cookie!
ws.onmessage = (e) => exfiltrate(e.data);

3. No TLS (ws:// instead of wss://): Plain WebSocket connections can be intercepted and manipulated in transit.

2 Secure WebSocket Implementation

Secure WebSockets require authentication at connection time, Origin header validation, and TLS.

Token-based WebSocket authentication:

const wss = new WebSocketServer({ noServer: true });

// Handle upgrade manually to authenticate first
server.on("upgrade", async (req, socket, head) => {
  const url = new URL(req.url, "https://example.com");
  const token = url.searchParams.get("token");

  try {
    const user = await verifyToken(token);
    wss.handleUpgrade(req, socket, head, (ws) => {
      ws.user = user;
      wss.emit("connection", ws, req);
    });
  } catch {
    socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
    socket.destroy();
  }
});

Origin validation:

const ALLOWED_ORIGINS = ["https://myapp.com", "https://www.myapp.com"];

server.on("upgrade", (req, socket, head) => {
  const origin = req.headers.origin;
  if (!ALLOWED_ORIGINS.includes(origin)) {
    socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
    socket.destroy();
    return;
  }
  // proceed with upgrade
});

Knowledge Check

0/3 correct
Q1

How does cross-site WebSocket hijacking work?

Q2

Why should authentication tokens be passed as URL parameters during WebSocket connection rather than relying on cookies?

Q3

What is the difference between ws:// and wss:// WebSocket connections?

Code Exercise

Authenticate WebSocket Connections

The WebSocket server accepts all connections without authentication. Add token verification on the upgrade event, rejecting connections without a valid token.

javascript