How WebSockets Work? Vulnerabilities and Security Best Practices

WebSocket is a real-time bidirectional communication protocol designed for efficient data exchange between a client (web browser, application) and a server.

Unlike traditional HTTP requests, which require a new connection to be opened for each exchange, WebSocket establishes a persistent connection. Once activated, it enables both parties to transmit messages continuously, without interruption.

This operating mode, known as full-duplex, allows the server to send data spontaneously, without any prior request from the client.

This protocol is particularly well suited to interactive applications and functions requiring real-time updates. It is commonly used for messaging, notification and instant collaboration systems.

Frameworks such as Meteor simplify its integration and enable it to be exploited on a large scale in an application.

Comprehensive Guide to WebSockets

Understanding WebSockets in Depth

Before establishing a WebSocket connection, a handshake must be performed using the HTTP protocol:

GET /chat HTTP/1.1
Host: www.websocket.com:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://www.websocket.com
Sec-WebSocket-Key: F3K8tSSU8iTVlhenxKqtbw==
DNT: 1
Connection: keep-alive, Upgrade
Cookie: X-Authorization=8jvbphlmktyutyty4vraWBA
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

If the server accepts the connection, it responds as follows:

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: ILZpbBQBard/ixWRPPI6UOlh8hY=

A response with a status code of 101 indicates that the server has validated the connection, enabling the WebSocket to be instantiated. The data exchanged can be in various formats (HTML, JSON, text, etc.).

Like HTTP, WebSocket has no built-in security mechanism. It is therefore up to the developer to implement the necessary protection at application level.

In the previous example, the X-Authorization cookie is used as an authentication mechanism to identify the user requesting access to the WebSocket, thus making it possible to restrict the data accessible according to their permissions.

Another point in common with HTTP is the existence of a secure version. The protocol defines WS (WebSocket) and WSS (WebSocket Secure). The latter encrypts communications, preventing an attacker from intercepting data in clear text via a Man in the Middle attack, as can happen with non-secure HTTP.

In addition, mechanisms for managing unused connections can be put in place to optimise server resources and prevent denial of service attacks, where a malicious user would open a large number of simultaneous connections.

How to Test WebSockets Security?

Before going into detail about WebSockets vulnerabilities, it is essential to understand how to inspect the requests exchanged between the client and the server, and how to modify the data transmitted.

Burp Suite is the industry-standard tool for web penetration testing. In particular, it can intercept, analyse and replay requests. Although initially designed for the HTTP protocol, it also offers specific features for analysing WebSockets.

To begin with, it is essential to observe all the requests exchanged in order to identify potential entry points for an attacker, and to understand how user input is processed by the browser and server.

Once the application has been properly analysed, it becomes relevant to manipulate these inputs and replay the most interesting requests.

Like HTTP requests, WebSockets can be sent to the Repeater to be modified and replayed. However, their interface has a few differences.

In the left-hand panel, you can modify the data and choose whether to send the request to the server or the client.

The right-hand panel displays the request sent and the response returned by the server (shown here in red).

However, Burp Suite has certain limitations when it comes to analysing WebSockets. In particular, it is not possible to use the Intruder tab, which automates the sending of requests based on a data dictionary. This feature would be useful, for example, for brute force testing of weak passwords.

In addition, the automated scanner in the Professional version of Burp Suite does not support WebSockets.

Despite these limitations, Burp Suite is still a more than adequate tool if only certain application functions exploit this protocol. For more advanced security tests, it is possible to use another dedicated proxy, such as ZAP.

Wscat is a lightweight, easy-to-use tool, installed via npm. The user enters the URL of the server, which triggers the initial handshake via HTTP, before establishing a WebSocket connection.

Once connected, the user can send data directly from the console and receive data from the server. For example, an endpoint could be used to execute the ping command on an IP address supplied by the user.

Although easy to learn, Wscat remains limited for advanced testing, offering few analysis or automation features.

STEWS is a tool designed specifically to test WebSockets security. It has three modules: Discovery, Fingerprinting and Vulnerability Detection.

The Discovery module locates server endpoints using the WebSocket protocol. It works in a similar way to tools such as feroxbuster or ffuf, by trying common endpoint names (from a dictionary) and analysing server responses.

The Fingerprinting module can identify the type of WebSocket server used by the application. This information can be invaluable in targeting specific attacks based on the server identified, and checking whether any CVEs are available for it.

In this example, the tool identified the use of the Ratchet library for WebSocket communications.

The Vulnerability Detection module can be used to test for a number of known vulnerabilities, such as CSWH (Cross-Site WebSocket Hijacking), which we’ll look at later, as well as various CVEs depending on the libraries detected.

Common WebSockets Vulnerabilities and Security Best Practices

This type of vulnerability corresponds to the exploitation of a CSRF (Cross-Site Request Forgery) as part of a WebSocket communication.

The exploitation scenario is similar to that of classic CSRF. Malicious code is embedded in a page that the attacker tries to get the victim to visit.

Let’s take the example of a vulnerable password change: the attacker encourages the victim to execute the password change request. The attacker can then obtain the new password and access the victim’s account.

By analysing the requests sent in the context of the victim, we can see that the handshake has succeeded, because the victim’s cookie is automatically transmitted by the browser, and no CSRF protection is in place.

The WebSocket responsible for performing the password change will then be instantiated, and the data will be sent to the server, which will apply the change.

It is important to note that this type of exploitation is only possible if the cookie has the Same-Site flag set to None (modern browsers generally default to Lax if this flag is not specified).

To correct this problem in an application, it is essential to start by changing the Same-Site flag of the session cookie. Next, the server must check the Origin header and compare it with a white list of authorised domains.

Broken access control is common in web applications and can also occur with WebSocket connections.

Let’s take an example where the server sends notifications to the user when he is mentioned on a page. WebSockets are particularly well suited to this case.

However, a common error would be to send the notification to all the clients connected to the WebSocket server, and to let the browser display the notification only if the user is concerned.

During a security audit, this error would be easily detected, as the auditor would see, in the proxy’s history, notifications intended for all other users.

Although this approach seems obvious as a vulnerability, a developer might not grasp the risk of spreading information in this way if they do not monitor the requests sent by their application via a proxy.

We will conclude with a vulnerability that is not specific to HTTP, but which highlights the importance of controlling user data. The fact that this data is sent via WebSocket should in no way reduce vigilance. This is SQL injection.

Detecting SQL injections can be relatively straightforward in some cases, but exploitation (in particular to retrieve data from the database) remains tedious if carried out manually. This is why SQLmap is particularly useful in this type of situation.

In the context of WebSockets, some adaptation work is required to use this tool, as SQLmap was not designed for this protocol.

A Python script can be used as a proxy by opening an HTTP server that will establish the WebSocket connection. Here is an example script to help you understand this process:

When the server receives an HTTP request, a WebSocket connection is established on the endpoint we wish to test; and the HTTP response will correspond to the message sent by the server in response to the client’s message.

To gain a better understanding of the requests made, a proxy has been configured to observe communications through Burp’s Proxy History.

In this way, we can use SQLmap in the classic way:

Here, a tamper script is used, as the server expects to receive the username and password in base64 format.

This script can easily be adapted to all the endpoints you wish to test; all you need to do is change the URL, the parameter names and the format in which the data is sent and responded to.

With regard to the vulnerability exploited by SQLmap, the best security practice for avoiding this type of flaw is to use Prepared statements. This is the most effective method of preventing SQL injections, regardless of the protocol used (HTTP or WebSocket).

Conclusion

The WebSocket protocol meets a need for real-time communication. However, it is mainly used for specific features and is much less widespread than HTTP. This explains why testing tools are less developed for this protocol.

As we have seen, the vulnerabilities encountered are often similar, or even identical (as in the case of SQL injection). Only the detection and exploitation techniques may differ slightly from one protocol to another.

Author: Julien BRACON – Pentester @Vaadata