The WebSocket protocol is a protocol of the application layer of the OSI model, which enables to communicate in full duplex (a communication canal where the information can circulate simultaneously in both directions) between a client (a browser) and a web server. In two words, it allows to create real-time web applications, like instant messaging chat.
It overcomes latency created by half-duplex communications, where communication only takes place in one direction at a time, which is characteristic of the solutions used until now for this type of application. Indeed, with the HTTP protocol, the client initiates a request and waits for a response, this is called a transaction. Each request/response initiates a different transaction, whereas a WebSocket initiates a transaction with a long-life cycle (several requests/responses). In addition, the server can send data even if no prior request has been made.
The diagram below illustrates how WebSockets work (from connection to communication):
First of all, a WebSocket communication is initiated through HTTP communication via the WebSocket handshake.
The client tells the server that it wants to initiate a WebSocket connection:
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=8jvbphlmk3DG8iXL0F4vraWBA Pragma: no-cache Cache-Control: no-cache Upgrade: websocket
If the server accepts the connection, it answers the following way:
HTTP/1.1 101 Switching Protocols Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Accept: ILZpbBQBard/ixWRPPI6UOlh8hY=
We can note that the HTTP response indicates code 101, which can help to find a WebSocket connection in a client/server communication. The following headers are added:
- ‘Connection: upgrade’ and ‘Upgrade: websocket’ in the request to indicate that the protocol is being changed
- ‘Connection: upgrade’ and ‘Upgrade: websocket’ in the response to indicate that the change is approved
- The ‘Sec-WebSocket-Version’ to indicate the protocol version to be used.
- ‘Sec-WebSocket-Key’: value used by the server to create the ‘Sec-WebSocket-Accept’ in the response
- The ‘Sec-WebSocket-Accept’: in order to obtain this value, the server concatenates the value obtained via the ‘Sec-WebSocket-Key’ client and the character string ‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’ (default value set by RFC 6455). Then, it performs the SHA-1 hash of the result, which will finally be encoded in base64 before being returned. This value is used by the client to know that the server is ready to initiate a WebSocket communication with it. Be careful, this is in no way an authentication mechanism or a security protection.
Once this communication is initiated, the client and the server communicate asynchronously. The format of the exchanged data can be of any form (HTML, JSON, Text…). However, in practice, the most used WebSocket libraries exchange in JSON format.
Possible Attacks and Security Risks
While WebSockets are useful for creating full-duplex communication channels (in modern applications, the server may need to send data to the client without the client making a special request, for example in case of instant messaging), this technology does however not offer any particular security advantage. Thus, we find the usual vulnerabilities of the HTTP protocol with sometimes some specificities. Below is a non-exhaustive list of possible vulnerabilities and attacks against WebSockets:
The WebSocket protocol does not have a native mechanism for authentication, so during development, a clean solution must be implemented, either through cookies, JWT or HTTP (Basic/Digest) authentication. During a penetration test, it is then necessary to systematically check if there is indeed an authentication system and if it is implemented correctly (access to functionalities without authentication).
Authorisation and Authorisation Control
As with authentication, there is no system for managing authorisations (that users only have access to the data and services they should have access to) in the WebSocket protocol. This gives an attacker the ability to raise its privileges vertically or to access a user’s data with the same level of rights as the attacker has.
During a pentest, the access control will be tested in detail to try to obtain a privilege escalation.
Risks Related to User Input
The data entered by users, also via WebSockets, is the major cause of attacks – XSS, SQL injections, code injections, etc. All inputs must be sanitised with the most appropriate method according to the context before being used.
Risk of Sniffing
Data transmission via the WebSocket protocol is done in clear text just like HTTP. It is therefore possible to recover this data by man-in-the-middle attacks. To avoid information leakage, the WebSocket Secure (wss) protocol must be implemented.
Remember that just as with HTTPS, wss does not mean that the web application is secure, it is only the encrypted transport of data via TLS.
Cross-Site Websocket Hijacking (CSWH)
Cross-Site WebSocket Hijacking is an attack similar to CSRF (Cross-Site Request Forgery). Both attacks are possible when the server relies only on the session authentication data (cookies) to perform an authenticated action.
For CSRF, the attacker hides a request in a link or another element that would be visible on the screen of its (authenticated) victim. The attacker prompts the victim to click on it to cause the action requested by the hidden request. The attacker can thus cause the victim to do something harmful without its knowledge. The disadvantage was that the attacker could not see the server’s response to the request (because of the origin policy), a disadvantage that no longer exists with WebSockets, as it does not implement an origin policy. This allows the attacker to create a full-duplex connection with the victim’s credentials.
In fact, the Cross-Site WebSocket Hijacking attack is possible when the WebSocket handshake is vulnerable to CSRF. Indeed, the communication channel between the two parties (client/server) is created according to the origin of the opening request. Thus, if the protocol change request is only based on cookies, an attacker can then trap a victim to initiate a request with its session but on the attacker’s server.
Once trapped, the attacker can communicate with the server via WebSockets without the victim’s knowledge. As with a classic CSRF, the attacker can therefore perform actions in the place of a user, but also read the server messages sent via WebSockets.
In order to solve this vulnerability, it is necessary to add a unique token per session and that cannot be guessed as a parameter of the handshake request.
How to Test the Security of WebSockets?
Currently, the two main tools for testing WebSockets are Burp and ZAP from OWASP. These tools allow you to intercept and modify WebSockets frames on the fly. The number of tools available to test WebSockets implementations is still quite small.
Note also that among the Chrome development tools, there is one that allows you to see WebSockets traffic. Once the tools are available, the audit of a WebSocket is the same as for normal HTTP requests (injection tests, access rights tests, workflow tests…).
If the WebSocket protocol is vulnerable to many attacks, a good configuration already allows to drastically limit the risks, as it is the case for the HTTP protocol.