The WebSocket communication protocol is used for a range of purposes, including transmitting sensitive information and running actions with elevated privileges. This makes it an increasingly attractive attack vector for malicious actors.
The best defense against common WebSocket vulnerabilities is to be aware of them and implement the proper controls to reduce exposure.
In this post, we’ll look at the most common WebSocket security vulnerabilities and how to prevent them through a combination of modern security approaches and testing tools.
For each security vulnerability, I'm going to outline:
- What it is
- The impact
- And how to prevent against an attack (I'll show you best practices and some tools)
Along the way, I'll also link to in-depth posts that I think you'll find helpful.
Let's start with a fundamental one a lot of developers get wrong - broken authentication.
WebSockets don’t prescribe any particular way for servers to authenticate clients, putting the responsibility on us, the developers, to devise and implement a mechanism to confirm our user’s identity and securely manage their session.
The lack of a standard way to authenticate incoming WebSocket connections leaves room to make critical security mistakes.
The impact of a WebSocket authentication vulnerability is severe. Once an attacker has bypassed authentication, they have access to all the data and functionality that the compromised account has.
Preventing broken authentication involves authenticating the handshake before establishing the WebSocket connection, either with a cookie or token
When using cookie authentication, the browser automatically sends cookies to the server with the WebSocket handshake. Just beware of Cross-Site WebSocket Hijacking (more on that in the section below).
Token authentication is a bit more tricky.
Browsers don’t allow arbitrary headers with the WebSocket connection request, meaning you need to find another medium to send the token to the server.
It can be tempting to send the authentication token in the query string, however, this should be approached with extreme caution. Query strings form part of the URL, which is plaintext and may appear in logs and be used in an attack.
One possible solution is to use your long-lived authentication token to make a HTTP request for an ephemeral one-time token from your authentication service. Send this one-time token with the WebSocket connection in the query string then discontinue it on the server-side. This way, if the token is logged somehow or shared accidentally, it's no longer usable.
If you'd like to learn more about how to implement a token-based authentication flow, Senior Software Engineer Jimmie Potts has a concise post on the subject.
In the previous section, we looked at authentication, which confirms the client is who they say they are. Access control, on the other hand, involves granting or denying access to specific resources or actions based on the authenticated identity.
Suppose Lord Voldemort authenticates with a password. Surely he shouldn’t be authorized to subscribe to Harry Potter and the gang’s WebSocket channel.
Broken access control is the most commonly encountered and often a critical security vulnerability. It happens when a user can in fact access some resource or perform some action that they are not supposed to be able to access. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data, or performing a business function outside the user's limits.
- Unless a resource is intended to be publicly available, deny access by default.
- Explicitly declare the access that is allowed for each resource.
- Thoroughly audit and test access controls to ensure they’re working as designed.
While the design and management of access control is a complex and dynamic problem, most issues can be solved with the above best practices.
Many developers rely on obfuscation for WebSocket security, but security through obscurity is not security at all.
WebSocket URLs are normally tucked away in code and the paths themselves often contain identifiers that seem random and impossible to predict, creating a false sense of security.
Today, it's trivial for a malicious actor to use a WebSocket traffic inspectors like Burp or even Chrome’s WebSocket inspector to recognise and exploit a pattern, making it more important than ever to double-check every resource is behind an access rule.
Insecure Direct Object References (IDOR) is a subcategory of access control vulnerabilities. It's one of the most common access control weaknesses, so we wanted to call it out directly.
An IDOR vulnerability allows a malicious actor to exploit a WebSocket application by manipulating a "direct object reference" in the WebSocket request, such as a file name or query parameter.
In an IDOR attack, the request succeeds due to missing access control checks, which fail to verify whether a user should be allowed to access specific data.
To give an example - in a post entitled IDOR via WebSockets, Security Engineer Shuaib Oladigbolu describes how they managed to comment as another user simply by tampering with the authorID parameter in the WebSocket comment request - sometimes it's that easy for an attacker to cause problems.
IDOR vulnerabilities are among the most commonly-reported and are trivial to execute. They can result in unauthorized data exposure, leakage of personally identifiable information, and even create the potential for data manipulation or deletion.
- Implement access control checks for each object that users try to access.
- Use complex identifiers like GUIDs instead of predictable incremental IDs as a defense-in-depth measure (but remember that access control is crucial even with these identifiers).
For more information on IDOR, The Open Web Application Security Project (OWASP) has a handy IDOR prevention cheat sheet - they are a non-profit dedicated to application security and have many educational resources dedicated to the security subjects described on this page.
Injection is an attacker’s attempt to send data to an application, with the intention of exploiting vulnerabilities in the application's processing. It's one of the most common vulnerabilities with HTTP, and it applies to WebSockets as well, which are often used to transmit sensitive information and run actions with elevated privileges.
Common types of injection attacks include SQL injection, where attackers manipulate database queries, and cross-site scripting (XSS), where malicious scripts are injected into web pages viewed by other users.
Injections are among the oldest and most dangerous attacks aimed at web applications in general and often arise in relation to WebSockets. They can lead to unauthorized access, data loss, denial of service, or even full system compromise if not properly mitigated.
- Escape special characters in user inputs before incorporating them into queries or commands. This prevents them from being interpreted as code.
- Treat all user-supplied input as untrusted. Validate all inputs on the server, and use an allowlist of acceptable inputs.
- Examine and remove unwanted key characters, such as HTML tags that are deemed to be unsafe. Keep the safe data and remove any potentially unsafe characters.
- Most instances of SQL injection can be prevented by using parameterized queries (also known as prepared statements) instead of string concatenation within the query.
A Denial of Service (DoS) attack exploits vulnerabilities in your WebSocket implementation to crash the WebSocket server, making it inaccessible for your genuine users.
DoS attacks accomplish this by flooding the WebSocket server with traffic, or sending it information that causes a crash.
A DoS attack can be compared to a phone system being flooded with constant, non-stop calls from prank callers, jamming the lines and preventing legitimate callers from getting through, thus disrupting trade and losing the business money.
A successful DoS results in sluggish behavior or a total system crash. In both instances, the DoS attack deprives genuine users of the service they expected.
Though DoS attacks don't typically result in unauthorized access to sensitive data, they can have a devastating impact on critical services, leading to direct financial loss and reputational damage.
- Only allow authenticated users to open a WebSocket connection to prevent an attacker from flooding the WebSocket server with a large number of connection requests.
- Ensure that your authentication mechanism is efficient so that DoS attacks using an invalid token can be quickly and cheaply refused.
- Limit the number of requests that can be made to the WebSocket server from the same IP address over a specific time period.
- Limit the number of connections allowed to the WebSocket server to circumvent a resource exhaustion attack.
- Limit message size to a reasonable number to prevent message size attacks.
DoS is not a specific attack but rather, a category of attacks. It would be outside the scope of this post to list every type of DoS however, I can highly recommend this post on DoS via WebSockets by CQR. They go into more detail about the above vulnerabilities and touch on a few others as well - for example, a pesky type of DoS called a WebSocket SYN Flood DoS.
An additional type of DoS attack is the Distributed Denial of Service (DDoS) attacks.
DDoS attacks are more sophisticated and impactful than DoS attacks. They involve a coordinated effort from multiple sources - often compromised computers or devices forming a botnet. These sources simultaneously DoS the WebSocket server, making it even more challenging to defend against or mitigate.
The most immediate and obvious impact of a DDoS is that your WebSocket server becomes overwhelmed and crashes. Suppose you’re building a chat experience or realtime collaborative experience over WebSockets - if your WebSocket server is compromised, your entire website may as well be down. As your service becomes intermittent, users may lose faith in the experience and use another service altogether.
Since the attack is distributed, connections will likely come from all around the world. It will be hard to distinguish malicious and genuine connections due to the fact the botnet is composed of compromised systems that otherwise seem like genuine users. This makes a DDoS difficult to mitigate, resulting in intermittent disruptions to the service, often leading to reputational damage or straight up financial loss.
- Ensure your server is not vulnerable to DoS attacks (see section above).
- Use a hosted WebSocket infrastructure like ours at Ably - our near-limitless scale means we can mitigate huge increases in traffic and defend against DDoS attacks - so you benefit from our scale as attacks have no effect on your own servers.
- Proxy WebSocket connections through a content delivery network (CDN) that offer DDoS protection services that can detect and mitigate attacks in realtime.
- Distribute WebSocket connections across multiple servers and data centers, making it harder for attackers to overwhelm a single server.
- Have a plan in place for responding to a DDoS attack, including procedures for notifying stakeholders, isolating affected systems, and restoring services.
For more information on how DDoS attacks work in the real world (and some guidance on how to mitigate them), CloudFlare has an in-depth post on the subject. As it happens, CloudFlare is a CDN that offers DDoS protection. We use them at Ably.
Cross-site WebSocket hijacking (also known as cross-origin WebSocket hijacking) is a security vulnerability that occurs when a malicious actor makes an unauthorized WebSocket connection to a different origin (site) than the one the user is currently on.
It arises when the WebSocket handshake request relies solely on HTTP cookies for authentication and isn't relevant to you if you're using token-based authentication.
Modern browsers ordinarily prevent cross-origin resource sharing (CORS) with a same-origin policy - while this applies to HTTP, counterintuitively, this does not apply to WebSocket connections, introducing a potentially surprising attack vector - unless you happen to know better. Good job you're reading this post!
The implication of a cross-site WebSocket hijacking vulnerability depends on the scope of the attack and the hacker's ability to leverage it.
At a minimum, a successful cross-site WebSocket hijacking attack enables malicious actors to abuse the established WebSocket connection to perform actions on the user's behalf without their consent, potentially compromising their data or executing unintended actions. In many cases, the user won't know they've been exploited until it's too late, making it hard to react and defend their own data.
- On the server side, validate the origin of incoming WebSocket connections. Only allow connections from trusted domains by checking the Origin header. Reject connections from unexpected or unauthorized origins.
- Introduce a session-individual token (like a CSRF token) into the user's session, which is then included in the WebSocket connection request sent to the server. This token is not known to malicious actors, making it difficult for them to forge requests.
When transmitting sensitive information from one client to another over WebSockets, it must traverse the network. Malicious actors may exploit vulnerabilities to eavesdrop on the communication and steal personally identifiable information, such as account details, sensitive health data, private communications, and intellectual property.
Broadly speaking, this is known as a man-in-the-middle attack and is the equivalent of a mailman opening your bank statement, writing down your account details, and then resealing the envelope and delivering it to your door - you might not know you've been hacked until it's too late!
The most immediate impact of a data leak is the violation of privacy for your users whose personal information has been exposed. At a minimum, users will lose faith in your ability to secure their information, leading to reputational damage and potentially loss of business as well. Depending on the nature of the breach, you may incur legal consequences and regulatory fines also.
The severity of the impact can vary based on the nature of the data exposed, and the motivation of the attackers. By intercepting or manipulating sensitive data, a malicious actor could steal intellectual property or even use data obtained from the breach to carry out a secondary attack, possibly causing wider operational disruptions.
- Always use the WebSocket Secure (wss) protocol instead of WebSocket (ws) to ensure data exchanged between the client and server is encrypted using SSL (TLS), making it difficult for attacks to intercept or decipher.
- Ensure that the SSL certificate used for security the WebSocket connection is valid and issued by a trusted certificate authority.
- Regularly review the information sent over WebSockets to determine if a justifiable business need exists for transmitting each item present. Any items deemed unnecessary should be removed.
When building with WebSockets, it’s common to use a library like Socket.IO to help you get up and running more quickly. These libraries tend to implement features you probably need - like automatic reconnection and message acknowledgements, as well as provide patterns for grouping connections by “rooms” or “topics” (pub/sub) to make routing messages simple. They are very convenient!
However, before depending on a WebSocket library, do some research, and possibly some auditing.
Using a third-party WebSocket library can save time upfront, but it’s not without risk of introducing a vulnerability.
For example, according to Snyk, email@example.com introduces a DOS vulnerability before being patched in websockets@10.
Here's one more example of a Regular Expression Denial of Service (ReDoS) vulnerability introduced by the third-party ws package, which has since been solved.
Newer WebSocket libraries (or newer WebSocket library versions) may be more susceptible to vulnerabilities due to the fact they haven’t yet been battle-tested.
Additionally, watch out for older or unmaintained WebSocket libraries. Often, libraries with known vulnerabilities don’t get fixed due to a lack of maintainers.
A vulnerable or outdated dependency may be susceptible to any of the common WebSocket vulnerabilities described in this post.
Malicious actors can exploit these vulnerabilities to gain access to sensitive data or take control of the application entirely.
- Use a commercial WebSocket-based API like Ably, which is actively maintained by a dedicated team, frequently undergoes penetration testing, and has a respectable vulnerability disclosure policy (bug bounty).
- Carefully inspect any open source dependency you add to your WebSocket server, as it may have an outstanding vulnerability.
- Keep open source dependencies updated to ensure you have the latest security patches, reducing the risk of an exploit.
- Optionally use an integration such as Snyk to continuously perform security scanning on your open source dependencies and detect potential vulnerabilities.
To wrap up this post, let's cover some of the most commonly-asked questions about WebSocket security.
Yes, it's highly recommended to use SSL encryption with WebSockets (wss) to prevent eavesdropping and tampering by malicious actors. Using SSL also helps to maintain the integrity and confidentiality of the communication and prevents various security vulnerabilities that can arise when data is transmitted over an unencrypted connection.
WebSockets are very secure when used over an encrypted SSL connection (wss) and you follow the WebSocket security best practices described in this post. Secure authentication, authorization, and input validation are crucial for preventing unauthorized access and attacks. Regular updates to libraries and ongoing testing contribute to overall security.
Comprehensive WebSocket security testing requires a deep understanding of the WebSocket protocol and practical experience in both manual and automated security testing techniques. Open tools like STEWS can detect known WebSocket vulnerabilities while commercial security tools like Burp Suite exist to intercept and manipulate WebSocket frames with ease, however they won't catch everything. Perform manual testing and fuzzing to identify unexpected behavior or vulnerabilities that automated tools might miss.
If you lack experience in WebSocket security testing, consider consulting with security experts or penetration testers who specialize in this area, as the consequences of poor WebSockets security can be dire.