Insights

Parameter Tampering in WebSockets

Author:

Paul Johnston

Parameter tampering is one of the more common high-risk vulnerabilities in modern web applications. While issues like SQL injection have become less frequent, due to frameworks promoting secure coding practices and improved detection by security tools, parameter tampering remains a business logic flaw that existing tools struggle to effectively address.  

WebSockets are a powerful technology for creating interactive, real-time applications. However, like any technology, they come with their own set of security risks. Many of these risks fall into familiar categories of vulnerabilities, such as injection flaws and access control failures. Unfortunately, typical security tools offer limited support for WebSockets, meaning security teams must invest additional effort to fill this gap.  

In this insight piece, we will examine a vulnerability that illustrates parameter tampering in a WebSocket. For confidentiality reasons, this is a lab example, but it draws inspiration from real-world experiences, and all the attack and defense techniques discussed are applicable to live environments. We will explore how to detect and exploit this vulnerability using dynamic analysis, identify the vulnerable coding patterns that lead to exposure, and present secure coding practices to adopt instead. 

Exploring the Lab Environment 

Logging into the lab application as two test users, we can see the different rooms they have access to: 

Chat Room Access - Parameter Tampering in WebSockets

To investigate how the application is functioning internally, we can configure the browsers to proxy through an intercepting proxy, such as Burp. When we attempt to join the different chats, we can see the following WebSocket messages: 

WebSocket Messages - Parameter Tampering in WebSockets

We can see “join 1” for All Employees and “join 2” for Managers. As a pen tester, this immediately makes me think: what if we tamper with this? In normal operation, only Bob will join Managers, but what if we tamper with Alice’s message and change the ID from 1 to 2? 

We can do this by right clicking a message and choosing Send to Repeater. This creates a new Repeater tab, where we can modify the message to use a different ID, and send it. 

Modify Message - Parameter Tampering in WebSockets

When we do this, we don’t see any immediate feedback, so we’ll need to test whether we’ve been able to join the chat. We can use Bob’s browser to send a message to the managers’ chat – which we would expect Alice not to be able to view – and observe that Alice’s browser does now display the message. 

Test 1 - Parameter Tampering in WebSockets

This is a serious confidentiality breach. In addition, tampering with the “send” message allows an integrity breach as well. 

Handling Disconnected Sockets 

When we first use Send to Repeater, the UI appears as in the left image below. However, if the browser window is closed or refreshed, the UI changes to the right image. 

Disconnected Sockets - Parameter Tampering in WebSockets

What’s happening internally here is that Burp is proxying the WebSocket between the browser and the back-end application.  

Messages generated by the browser are sent first to Burp and then on to the server. Server generated messages are sent first to Burp and then on to the browser. If the browser has a navigation event, the WebSocket closes, and Burp can no longer send or receive messages. However, Burp does provide a Reconnect button. This creates a WebSocket from Burp to the server, but this does not involve the browser. Burp can send messages to the server, but server-generated messages cannot reach the browser. 

For most WebSocket apps, I find the protocol is text based and simple enough to read raw within Burp. But some applications are more complicated. 

Crafting a Weaponized Exploit 

In the lab environment, manually modifying and resending the message worked fine. However, our experience with production applications is that various restrictions are in place which make this more difficult.  

For example, we had no difficulty joining a second chat on a socket that had already joined a chat – but many applications would not allow that. Also, there was no restriction on timing, but many live applications close the socket if a particular message isn’t received within a time window. 

To cope with such applications, we need a way to tamper with messages without affecting the timing. Burp has a feature we can use for this: Match and replace rules. 

This is a feature that has long existed for HTTP messages and has more recently been extended to support WebSocket messages. We can use the following configuration: 

Match and Replace Rules - Parameter Tampering in WebSockets

With this in place, when Alice joins the All Employees chat, the message is automatically modified to join the Managers chat: 

Modified Message - Parameter Tampering in WebSockets

Defending the Application 

Looking at the source code, we can see the vulnerable section of code. As with most parameter tampering vulnerabilities, the issue is that an ID parameter is taken from external input and used without validation. 

Source Code - Parameter Tampering in WebSockets

To fix this issue, we need to verify that the requesting user is a member of the chat that the chatId refers to. There is a potential difficulty here, because WebSocket messages don’t contain cookies or another authentication mechanism. To do this, we need to look at how WebSocket connections are created. There is an initial HTTP request, with a Connection: Upgrade header. We can see this request within Burp Repeater by clicking the pen icon: 

Connection Upgrade Header - Parameter Tampering in WebSockets

This initial request does include cookies. So, what we need to do is connect each WebSocket message to the initial HTTP request. The lab application is written in Ktor and the design of Ktor makes this relatively easy to do as the whole connection is handled in a coroutine. In some frameworks, the WebSocket functionality is more disjointed from the HTTP functionality, which can make this harder to implement. 

The code with authentication and validation looks like:

Authentication and Validation - Parameter Tampering in WebSockets

With this in place, both Alice and Bob can join the rooms they have access to. But when we send a tampered message, the WebSocket is immediately closed by the server, demonstrating that the protection is working effectively. 

A defense-in-depth consideration is that the attack was only possible due to the use of sequential IDs. If long, random GUIDs were used instead, this would also have prevented the attack.  

In general, we recommend validation as the primary defense, with the use of GUIDs also encouraged as a “belt and braces” precaution. 

In Conclusion 

The overall nature of attacking and defending parameter tampering in WebSocket messages is little different to parameter tampering in HTTP requests. However, tooling is less mature – both in terms of dynamic testing tools and web frameworks. This makes WebSockets a fruitful place for pen testers to explore, and an important part of an attack surface for defenders to consider. 

Concerned about parameter tampering in WebSockets, or any other aspect of your web application security? Why not get in touch and see how our web app penetration test services can help you uncover vulnerabilities and provide you with the security assurances you need.  

Looking for more than just a test provider?

Get in touch with our team and find out how our tailored services can provide you with the cybersecurity confidence you need.