This is the story from one of our recent penetration testing engagements. Still, the story is a familiar one for those who are testing newer web applications that use one of the multitudes of evolving web app platforms built on a poorly understood technology stack. In this case, we ran into a WebSocket-based application that was thought to be relatively secure; however, the use of web sockets in the application was misunderstood, resulting in a significant set of authentication and authorization flaws. This also serves as yet another testament to the fact that automated vulnerability scanners (i.e. SAST and DAST tools) are no match for a seasoned penetration tester.
What is a WebSocket?
Before we continue our story, it is important to understand a little bit about WebSockets. Unlike a typical HTTP request/response interaction in which a browser requests data from the server, a WebSocket opens a persistent bi-directional communication (i.e. full-duplex) path between the server and the browser. It is similar in behavior to a Unix-style socket but is its own protocol, described in RFC 6455 at the same time the HTML 5 specification was proposed.
As long as the socket remains open, the browser and server can push messages to each other. This is particularly useful for applications with long-term connections where efficient asynchronous updates are ideal. A typical live chat program is an example of an application that would benefit from using WebSockets.
Back to our story: we were testing an application that was meant to display confidential content to authorized users. Our primary goal was to simply determine if there was any way for an unauthenticated or unauthorized user to access the confidential content.
While mapping out the application’s functionality and looking through our proxy tool (Burp Suite Pro) we noticed that the WebSockets history tab was being populated. This is not an unusual occurrence. Many web applications make use of sockets for a variety of asynchronous communication purposes that are often innocuous. What struck us as a little odd was the fact that the WebSocket was being established before our test user was fully authorized to access the application. In this particular case, the application had been modified to require a Multi-Factor Authentication (MFA) solution. Users who did not authenticate through MFA were supposed to be blocked from the application and presented with a message informing them to use the MFA solution before proceeding.
What we discovered was that the design of the application was to return the confidential content through the WebSocket, based on the ID of the user’s first layer of authentication (i.e. before the MFA message). What this means is the user was being presented with a message informing them to use MFA before proceeding and simultaneously receiving the confidential content through the WebSocket. The content was not yet being displayed to the user, but it was being stored temporarily in the browser.
This was a gray box test so we had at least two valid user accounts to work with. We were able to verify that by supplying different user IDs, even over the same WebSocket, we would receive both users’ confidential content through the socket. This proved our theory. In this application it was possible to establish a WebSocket without authenticating and then retrieve any user’s confidential content given only the user’s ID.
There are several things to be learned from this story:
Lesson # 1: Always Check for and Analyze WebSockets
WebSockets are often a poorly understood technology, especially among security practitioners. You can use Burp Suite or ZAP or even your browser’s developer tools to examine WebSocket traffic. This is something that should be done during penetration tests with every application, especially since your SAST and DAST tools are likely to miss it. For example, in the above case we know that our client had access to SAST and DAST tools, yet this issue was unknown to them.
Lesson # 2: WebSockets Don’t Do Cookies
Though it may be possible for a cookie to be returned on the same request that initiates a WebSocket, that cookie doesn’t mean anything to the WebSocket protocol. Your browser will go through its protocol change, thus establishing the WebSocket connection. At this point the server doesn’t receive any session cookies to validate on that connection. If you find an application that is using WebSockets, it is important that you examine the socket traffic to determine if any alternate forms of authentication and authorization are taking place. If you don’t see any in the WebSocket communication, chances are there isn’t any.
Lesson #3: Same Origin Policy is not for WebSockets
The Same Origin Policy, and by corollary Cross Origin Resource Sharing (CORS) policies do not affect WebSockets. WebSockets are a different protocol from HTTP altogether. It is assumed that the server will perform any necessary validations. It is important to consider this while testing them. Many solutions make assumptions that WebSockets are obeying all the same rules as HTTP traffic, but this isn’t the case.
Lesson #4: Perform Web Application Penetration Testing
We aren’t aware of any scanners that would have detected the critical authentication and authorization flaws we found. They were relatively easy for us to find because we knew where to look and because we understood the context. Though automated SAST and DAST tools are useful for automating more regular testing, they can’t replace a penetration tester. It is important that any applications that deal with confidential data undergo gray box or white box (i.e. not black box) testing, as this helps ensure thorough testing of authentication and authorization mechanisms.
To be clear, the moral of this story isn’t that every WebSocket is a vulnerability. We have encountered many applications that use WebSockets either for non-confidential purposes or in a way that includes proper authentication and authorization controls. However, when there are WebSocket vulnerabilities, they are likely to be rated high or critical. We therefore believe organizations should be extra cautious of WebSockets and understand that they are often misunderstood and not implemented with proper security controls in place.