Cross-document messaging

Gabor Paller's picture

Basic element of the web application model is the page. Our scripts run in the context of a page and the page also acts as security context. One of the most persistent kind of attack on web applications is the universal cross-site scripting (UXSS) when malicious scripts access elements of the web application e.g. feeding or capturing data from the web page.
 
Web browsers enforce same-domain policy which means that only scripts embedded into pages from the same domain (i.e. server) can interact with each other freely. This yields a very strict security model where every effort is made to prevent pages from interacting with each other. While this is crucial from the security point of view, it also disables browser-side interaction between web applications.
 
HTML5 has mechanisms to provide controlled interaction of web applications from different origin. While it is still strictly forbidden for web pages coming from different origin servers to invoke each other's functions, message passing became possible. The first such HTML5 mechanism is cross-document messaging.
 
The example application is attached at the bottom of this page. You have to be logged into Sfonge web site to access it.
 
First deploy the web application on a Glassfish server with the following command:
 
asadmin deploy --force crossdocumentsmsg.war
 
Now point your browser to the following address (I tested with Firefox 15):
 
http://127.0.0.1/crossdocumentmsg
 
A familiar page will come up: our server-sent event example application. This example application, however, is embedded into our cross-document messaging application page. This page has two buttons on it: "Get ticker1" and "Get ticker2" buttons that fetch the ticker1 and ticker2 values from the server-sent event page. Plus the cross-document messaging page embeds the server-sent event page with an iframe. In general, this setup would separate the two pages fully but we will exploit the brand new HTML5 constructs to create interaction between them.
 
Let's look at WebContent/index.html! When the "Get ticker1" button is pressed, the following JavaScript method is invoked.
 
      function gettckr1() {
          var tf = document.getElementById("tickerframe");
          tf.contentWindow.postMessage("tckr1","*" );
      }
 
The first line accesses the embedded page's Window object by identifying the iframe in the DOM tree. The second line sends a message ("tckr1") to this window. It would be possible to declare, what the target origin address of the receiver window is. In our case we just trust that the target origin address is that of the server-sent event page (because we loaded it on the page) so we specify a wildcard (*).
 
The event would be received by the embedded page which resides in WebContent/ticker.jsp. In order to receive events we have to first register a listener:
 
      window.addEventListener('message', messagereceiver, false);
 
Then we handle the event in the listener (function messagereceiver(e)). One line deserves attention here:
 
          e.source.postMessage( rsp, e.origin);
 
"e" is the event object the listener received and "rsp" is the response string we send back to the embedding window. What we are really doing here is sending a response to the Window that sent a request to us. And now back in index.html. Index.html also subscribes to 'message' events and also has a message listener. This listener extracts the ticker name and value and updates the appropriate control.
 
Used properly, cross-document scripting allows your web application to be used by other web application without compromising security. As always, extra care should be taken to make sure that you don't expose a functionality that can be exploited for malicious attackers.

Taxonomy upgrade extras: