XSS and App Security through HTML5's PostMessage()

 

Previously, I wrote about the risk of XSS and going beyond the javascript alert box, and now we’ll take a technical deep dive into a new HTML5 method which has changed the way we look for and identify XSS: XSS and Application Security through HTML5's PostMessage() . The postMessage() method allows applications to speak to one another through iframes, something that before was restricted by the same-origin policy.

Let's see how this works and the security implications involved.

 

The Method

 

The postMessage() method was created to enable cross-document messaging from applications on separate domains. In other words, it effectively side steps the same-origin policy allowing applications to send and receive data to and from each other. Here is the syntax for the method:

 

otherWindow.postMessage(message, targetOrigin, [transfer]);

 

Let's take the following example:

 

Site A has a nested iframe of Site B, which is on a separate domain:

site-a-b.jpg

 

If Site A wants to read content from Site B using a script like this:

 

Site A:

<iframe src="http://site-b.net/" name="siteb"></iframe>

<script>
document.getElementsByName('siteb')[0].onload = function() {
    frames[0].getElementById("message").innerHTML = "Hello World.";
}
</script>

 

Site B:

<div id="message"></div>

 

It would receive a same-origin error saying "Error: SecurityError: Blocked a frame with origin 'http://site-a.com' from accessing a cross-origin frame."  Now, thanks to our new postMessage() method, we can avoid this error by using the following code:

 

Site A:

<iframe name="siteb" src="http://site-b.net"></iframe>
<button onclick="frames[0].postMessage('Hello World.','*')">Send Message</button>

 

Site B:

<div id="message"></div>
<script> window.addEventListener('message', writeMessage, false); function writeMessage(event) { document.getElementById("message").innerHTML = event.data; } </script>

 

Which would result in Site A sending the message "Hello World" to Site B and writing it to the DOM (Document Object Model):

site-a-b-hello.jpg

 

The Vulnerability

 

Now that the postMessage() method allows us to communicate between iframes, we essentially have created a new attack vector for exploiting XSS. In many cases developers are not sanitizing the data that is passed in between applications in this way. The mistake is assuming that an application will only send you appropriate, safe data. Let's look at the same example as before but from the perspective of an attacker.

 

Because Site B is actively listening for any site to send it a message, the attacker can load Site B as an iframe in an evil webpage that he controls, Site X.

site-x-b.jpg

 

Now he can send a malicious XSS message to Site B using the postMessage() method:

 

Site X:

<iframe name="siteb" src="http://site-b.net"></iframe>
<button onclick="frames[0].postMessage('<img src=x onerror=alert(document.cookie)','*')">Send Attack</button>

 

Site B:

<div id="message"></div>
<script> window.addEventListener('message', writeMessage, false); function writeMessage(event) { document.getElementById("message").innerHTML = event.data; } </script>

site-x-b-attack.jpg

 

This malicious message was sent from the attacker controlled webpage to Site B, then was written to the DOM and executed as javascript. This resulted in the alert box containing the session id; but as we discussed last time, we can go much further than an alert box.  

 

The attack behaves very similar to reflected XSS, where and attacker would need to social engineer his target to click/visit his malicious webpage. However, the key difference is that the postMessage() method does not send any data to the server, it communicates to the iframe directly through the browser. This makes the attack virtually undetectable on the server-side. 

 

The Solution

 

There are two recommendations for securing the postMessage() method. The first is to specifically designate the target origin when sending messages to another application. This prevents the message from being "snooped" on by other iframes on the page which may have listeners setup. In our example, the targetOrigin should be as follows:

 

frames[0].postMessage('Hello World.','http://site-b.net');

 

On the receiving side, all listeners should verify the event.origin parameter before accepting any messages. This will verify that any received messages had come from the expected application, and can be done by changing our Site B code to the following:

 

<div id="message"></div>
<script> window.addEventListener('message', writeMessage, false); function writeMessage(event) { if (event.origin == "http://site-a.com") { document.getElementById("message").innerHTML = event.data; } else { return; } } </script>

 

As always, any data input to the application should be sanitized and filtered before being returned to the user. Javascript doesn't have a built in function to make this easy, but you can either use a library such as JQuery, or write your own script to encode dangerous characters.

 

About HP Fortify On Demand

 

HP Fortify on Demand is a cloud-base Application Security solution. We perform multiple types of security testing, including advanced manual XSS detection.

 

If you have questions or comments reach out to us on Twitter @hpappsecurity or at fodsales(at)hp.com!

 

Labels: Fortify
Leave a Comment

We encourage you to share your comments on this post. Comments are moderated and will be reviewed
and posted as promptly as possible during regular business hours

To ensure your comment is published, be sure to follow the Community Guidelines.

Be sure to enter a unique name. You can't reuse a name that's already in use.
Be sure to enter a unique email address. You can't reuse an email address that's already in use.
Type the characters you see in the picture above.Type the words you hear.
Search
Showing results for 
Search instead for 
Do you mean 
About the Author
hacker, developer, script junkie [python,ruby,php]
Featured


Follow Us
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation.