Last autumn I wrote a security analysis of HTML5 WebSockets for university course. In my analysis I suggested that with a cross-site scripting (XSS) vulnerability, attacker may be able to compromise WebSocket connection. So here is a proof-of-concept.
At very first, I need to say that I do not encourage anyone to any illegal acts. The following example is a proof-of-concept, meant to illustrate attack against HTML5 WebSockets – not a ready-made exploit. For any experimental testing I recommend to use only a safe and closed environment, preferably a local virtual machine or a private server.
Let’s get started
At first, we implement a simple web page that utilizes WebSockets for real-time client-server communication. I picked up an example code echo test from Websocket.org (slightly shortened version here):
Okay, and now let’s add an XSS vulnerability to the page. We save this page as PHP-file and after line 41 we add the following lines:
<?php print "Hello, ".$_GET['name']; ?>
By exploiting this vulnerability, a third-party attacker is able to eavesdrop, intercept or modify the WebSocket connections initiated from an exploited website. In practice, this is done by overriding the functions doSend(message) and/or onMessage(evt) with custom ones. If the vulnerable website is located at example.com/websocket-xss.php, the attacker constructs for instance following URL:
File websocket-xss.js is the one that includes the actual malicious code. It could be something like this:
What happens when the client (browser) receives a WebSocket message from the server, is that onMessage-function written by an attacker is invoked, instead the original one. Hence, the attacker is able to decide what happens: he can either modify the data before displaying it to user, not to display the data at all, or as in this example, send data to third-party server hosted by himself. From the user’s point of view, function onMessage() in our example acts exactly like the legitimate one. Thus, the user does not know, that the connection is being eavesdropped, unless (s)he detects the malicious act by finding the XSS vulnerability, or by monitoring the network traffic.
Finally, the attacker also needs a web service that allows cross-origin HTTP requests. This is not a problem: attacker just writes a website that returns the expected header information. In PHP, service websocket-eavesdrop.php could be something like this:
<?php header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); print "I got your message: ".file_get_contents("php://input"); ?>
Now go and try it out yourself. Example files:
- websocket-xss.php - place this to my-server1
- websocket-eavesdrop.php - place this to a “malicious” server my-server2
- websocket-xss.js - place this to my-server2(or wherever you want)
The following HTTP GET request exploits the vulnerability:
A brief analysis
The exploit works “nicely” at least on Firefox 13. It does not work in Google Chrome, since Chrome has an XSS detection tool which detects the vulnerability and prevents the injected code from being executed. However, if the attacker finds a persistent XSS vulnerability, the same attack can be targeted against Chrome users as well.
It is worth noticing that the vulnerability is NOT in the HTML5 WebSockets, or the web browser. In this example, the vulnerability is on the web page. Also, since we are demonstrating using a reflected XSS, successful attack requires that the victim accesses the web page using a certain link. For instance, attacker may spam the vulnerable link to potential victims through e-mail.
WebSockets are not that special case after all. The very same principles can be used in multiple scenarios when it comes to HTML5 and XSS. For instance, the attacker should be able to read WebStorage and use practically any features of HTML5 in the victim’s browser. There is nothing new on this actually, since XSS vulnerabilities have been widely known more than a decade. However, the main point of this article is that the nature of HTML5 and the new features of it open up many new ways to exploit an XSS.