Protect Your Assets
Showing results for 
Search instead for 
Do you mean 

XSS and App Security through HTML5's PostMessage()

DannyChrastil ‎06-23-2014 11:08 AM - edited ‎07-22-2015 01:24 PM


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:


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


Site A:

<iframe src="" name="siteb"></iframe>

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


Site B:

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


It would receive a same-origin error saying "Error: SecurityError: Blocked a frame with origin '' 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=""></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 =; } </script>


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


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.


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


Site X:

<iframe name="siteb" src=""></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 =; } </script>


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.','');


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 == "") { document.getElementById("message").innerHTML =; } 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)!


About the Author


hacker, developer, script junkie [python,ruby,php]

27 Feb - 2 March 2017
Barcelona | Fira Gran Via
Mobile World Congress 2017
Hewlett Packard Enterprise at Mobile World Congress 2017, Barcelona | Fira Gran Via Location: Hall 3, Booth 3E11
Read more
Each Month in 2017
Software Expert Days - 2017
Join us online to talk directly with our Software experts during online Expert Days. Find information here about past, current, and upcoming Expert Da...
Read more
View all