Today, many leading industries and modern enterprises have switched from processing and acting on data stored in databases to data in flight. How? Through real-time applications. One way to enable this is WebSocket, but it comes with vulnerabilities as well.
What Is WebSocket?
Real-time applications operate within an immediate time frame; sensing, analyzing and acting on streaming data as it happens. With real-time applications, you need information from your servers as soon as it is available.
WebSocket is a network protocol built on the Transmission Control Protocol, designed to make use of a more modern connection to receive and send ongoing real-time messages as required.
More and more end-users and business leaders today call for real-time experiences to remain competitive.
Before WebSocket came along, the ‘real-time’ web existed, but it was difficult to achieve since the web is built on the HTTP protocol paradigm. HTTP is stateless: there is no link between two requests successively carried out on the same connection. A stateless protocol does not require the server to retain information or status about each user for the duration of multiple requests.
Let’s take a look at how it works, how attackers can exploit it and how to defend against those techniques.
How Does WebSocket Work?
Sockets connect two services formed by a mix of IP and a port. They act as a unique, programmatic way to receive and send data and are key to network applications everywhere.
WebSocket connections start over HTTP and are often long-lived. Messages can be sent in either direction at any time and are not transactional in nature.
To establish the connection, the browser and server perform a WebSocket handshake over HTTP. The life cycle of a WebSocket interaction between client and server includes the following steps:
- A client initiates a connection to the server by sending an HTTP(S) WebSocket handshake request
- The server replies with a handshake response that consists of an HTTP response with a status code of 101 switching protocols (and a number of specific HTTP headers) to accept the WebSocket handshake
- The server can then send messages directly to the client without a client initiation of requests
- The client can explicitly (or via timeout) close the WebSocket connection.
GET /message HTTP/1.1
Connection: keep-alive, Upgrade
Cookie: session= <sessionid>
HTTP/1.1 101 Switching Protocols
The WebSocket Handshake Headers
You should also be aware of headers. These provide context and explanations about the connection. 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. The Sec-WebSocket-Accept response header contains a hash of the value submitted in the Sec-WebSocket-Key request header.
Cross-Site WebSocket Vulnerability
One key thing to look out for is the cross-site WebSocket vulnerability (also known as cross-origin WebSocket hijacking). It involves a cross-site request forgery (CSRF) on a WebSocket handshake. The WebSocket protocol itself does not prescribe any particular way that servers can authenticate clients during the WebSocket handshake over HTTP.
For example, in the below request, the WebSocket handshake request relies solely on HTTP cookies for session handling and does not contain any tokens in request parameters. This request is probably at risk for CSRF.
GET /message HTTP/1.1
Connection: keep-alive, Upgrade
Hence, the first step to performing an attack is to review the WebSocket handshakes and determine whether they have protection against CSRF.
How to Identify a Cross-Site WebSocket Vulnerability
Step 1: Access the Live chat feature and send the first text message.
( Hi, I am vulnerable to cross-site WebSocket hijacking)
Step 2: Capture the WebSocket handshake request with the help of the HTTP proxy tool and observe the request. The only session token present is in the cookie header.
Note: The Sec-WebSocket-Key header contains a random value to prevent errors from caching proxies and is not related to authentication or session handling purposes.
Step 3: Host an HTML payload with the WebSocket handshake URL to exfiltrate the victim’s chat history using the external service interaction.
Step 4: Once the victim clicks the malicious URL via a phishing email or through a random ad on a webpage, the threat actor can retrieve the chat history of the victim and exfiltrate it via external service interaction. The request body contains the full contents of the chat message in the JSON format.
Testing Cross-Site WebSocket Hijacking via an Automated Tool
Defenders can spot cross-site WebSocket hijacking with a Python tool found on GitHub. Below are the steps to see if your application is at risk for cross-site WebSocket hijacking.
GitHub link: https://github.com/DeepakPawar95/cswsh.git
Step 1: Download the Python code via Git clone.
Step 2: Install dependencies via Pip.
<pip3 install click pyfiglet Figlet websockets requests>
Step 3: Run the Python script by providing the WebSocket URL.
How to Fix and Prevent Cross-Site WebSocket Hijacking
To prevent attackers from doing this, ensure any applications connect to the WebSocket server over a secure TLS connection. You will also need to be sure to properly configure the server to verify and validate the contents of the ‘origin’ header received from the client over HTTP in its WebSocket handshake initiation request.
Same-site attributes on the session cookie can also be useful. These will instruct the browser not to send the cookie on any cross-origin request.
Last but not least, implement CSRF tokens on every request handling WebSockets. CSRF tokens include an unpredictable value (token), which is uniquely bound to the user’s session in page. Generate CSRF tokens on the server side. You can do this once per user session or for each request. This way, you can take advantage of WebSocket while cutting off an avenue for attackers.