Thursday 20 February 2014

Example of DOM XSS in echo demo page (that bypasses Chrome's XSS detection)

I was looking at WebSockets today (because of its use in Firebase which is used in one of AngularJS samples), and noticed an DOM XSS example on the WebSocket echo page which is used as an example of how to use WebSockets (I found that page from this article Inspecting WebSocket Traffic with Chrome Developer Tools)

For historical record (and to reuse them in a Javascript SAST) I've copied the current (vulnerable) version of the HTML and JS provided to this gist.

Code samples (like these) should not be provided with these types of security vulnerabilities, since they should represent best practices.

Specially when we know that the normal developer workflow is to start with copy-n-pastes from these type of examples (note how that page, as of Fev 2014) has no references to security).

Let see the vulnerability in action.

1) Open the page

2) click on the Connect button to establish a connection between your browser and the server:

3) click on the Send button to send the default message (which will be shown on the Log window)

4) Enter a message with some HTML code on it (and note how the HTML is rendered after clicking on the Send button)

5) try to use a <script> xss playload (in this case the payload was correctly added to the page, but the jQuery payload was not triggered (and I had no time to figure out why))

6) use a Javascript payload that is triggered via the onmouseover evert of an HTML Anchor tag (here is the payload used in the example below: using <a href='#' onmouseover ="javascript:$('a').html('xss')">a link</a> )

7) move the mouse over the link and noticed that all links on that page now say xss

What is interesting (and dangerous) from the example above is that it seems that WebSockets bypass the current XSS protections that current exist in some browsers (like Chrome). For example as with POST or GET data, I don't think there are many valid cases where data sent to the server using a WebSocket should become code on the response.

Vulnerable code:

There are two locations where we can see vulnerable code in action

1) on the the WebSocket echo page  page there is an HTML 'sample code' example that contains the following code sequence:

a) onMessage Javascript function is set as a callback to websocket.onmessage event

b) onMessage calls writeToScreen with the payload received

c) writeToScreen will create a new p HTML element and set its innerHTML to the message value (which contains the refected-by-websockets payload)

2) For some reason the code used on the WebSocket echo page is a little bit different (although it has the same code sequence)

a) onMessage callback is set

b) which calls logToConsole

c) which will create the p HTML element with the reflected payload

d) to see this in action here is how to call the onMessage method directly (from Chrome's console)

 ... with the result showing in blue (see below)

 e) here is how to cal the logToConsole method directly

 ... with the result showing in black (see below)

To see the XSS triggered from this, use the following payload (and move the mouse to the link): logToConsole("message[<a href='#' onmouseover =\"javascript:$('a').html('xss')\">over me</a>]")

Using chrome to see WebSocket traffic

On OSX's Chrome here is where the WebSocket's traffic can be seen:

TeamMentor references (note: you will need a valid/eval account to see the links below):