Message passing and Cross-Origin Resource Sharing (CORS)

Web’s security model revolves around the same origin policy, meaning that a site having a domain http://www.example.com can send and receive scripts and resources from http://www.example.com or from www.*.example.com that is, either from the same domain, or a sub-domain of that domain. Same origin policy says that the two scripts or resource must be with the same protocol (usually both http), port number (80 being the default for http), and host (modulo document.domain being set by both pages to the same value) This helps in keeping all the web applications sand-boxed into their own domain, where developers can rely on the security aspects and play around inside their own domain.

But, at times, there is a requirement to access the resources from another domains, in order for the web-page or the web application to have a rich set of features. At other times, attackers use cleaver techniques, like XSS (Cross-Site Scripting) where the attackers can write scripts to initiate XSS attacks, which bypass the same origin policy and trick the website to deliver malicious content along with the intended content. In order to safely achieve the Cross-Origin Resource Sharing, there are a few techniques available – postMessage, JSONP, etc.

postMessage

window.postMessage method is used to safely enable cross-origin communications. Usually, scripts on different pages are allowed to access each other if and only if conform to the same origin policy. window.postMessage provides a controlled mechanism to circumvent this restriction in a way which is secure when properly used.

The window.postMessage method causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g., remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.) The MessageEvent has the type message, a data property which is set to the value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called.

Syntax

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

In this syntax, there are 3 parameters:-

  • ​otherWindow : This is a reference to another window. For example, the contentWindow property of an iframe element, the object returned by window.open, or by named or numeric index on window.frames.
  • message: This is the data which is to be sent to the other window. The data is serialized using the structured clone algorithm.
  • targetOrigin: Specifies what the origin of otherWindow must be for the event to be dispatched, either as the literal string “*” (indicating no preference) or as a URI. If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow’s document does not match that provided in targetOrigin, the event will not be dispatched. Only if all three match, will the event be dispatched. This mechanism provides control over where messages are sent. For example, if postMessage was used to transmit a password, it would be absolutely critical that this argument be a URI whose origin is the same as the intended receiver of the message containing the password, to prevent interception of the password by a malicious third party.
  • transfer: Is a sequence of Transferable objects that are transferred with the message. The ownership of these objects is given to the destination side and they are no longer usable on the sending side.

Properties

The properties of the dispatched message are:

  • data: The object passed from the other window.
  • origin: The origin of the window that sent the message at the time postMessage was called.
  • source: A reference to the window object that sent the message; you can use this to establish two-way communication between two windows with different origins

Security restrictions

  • ​If it is not expected to receive messages from other sites, event listeners for message events should not be added. This is a completely foolproof way to avoid security problems.
  • If it is expected to receive messages from other sites, the sender’s identity must always be verified using the origin and possibly source properties.
  • An exact target origin must always be specified, not *, while using postMessage to send data to other windows. A malicious site can change the location of the window without, and therefore it can intercept the data sent using postMessage.

JSONP

JSONP takes advantage of the fact that browsers do not enforce the same origin policy on <script> tags. When a request is made to a server that is JSONP enabled, a special parameter is also passed that tells the server a little bit about the page. That way, the server is able to nicely wrap up its response in a way that the page can handle.

For example, say the server expects a parameter called “callback” to enable its JSONP capabilities. Here the request would look something like this:-

http://www.example.net/sample.aspx?callback=mycallback

Without JSONP, the server might return some basic JavaScript object, something like this:-

{ foo:’bar’}

However, with JSONP, when the server receives the “callback” parameter, it wraps up the result a little differently, returning something like this:-

mycallback({ foo: ‘bar’ });

It will now invoke the method specified. So, in the page, the callback function is defined:-

mycallback=function(data){  alert(data.foo);};

And now, when the script is loaded, it’ll be evaluated, and the function will be executed.

Security Concerns

Although JSONP is an OKish way, it comes in with some security concerns:-

  • Cross-site request forgery (CSRF): As the <script> tag does not respect the same origin policy, a malicious page can request JSON data belonging to another page, which can then be exposed to a third-party.
  • Rosetta Flash: Rosetta Flash is an exploitation technique that allows an attacker to exploit servers with a vulnerable JSONP endpoint by causing Adobe Flash Player to believe that an attacker-specified Flash applet originated on the vulnerable server. Flash Player implements same-origin policy allowing to make requests (with cookies) and receive responses from the hosting site. The applet can then send the retrieved data back to the attacker.

Other ways

Another way to allow CORS is to add ‘Access Control Allow Origin’ in the header response.

Conclusion

​The safest way to pass messages between different origins is using window.postMessage, which is supported in almost all the modern browsers.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s