Security | Fitness | Mindfulness
28 June 2015
Same Origin Policy is one of the most important security concepts implemented in all modern browsers. It is a set of mechanisms which control how a script loaded from one origin can interact with a resource from another origin. Mozilla Developer Network provides a good summary of Same Origin Policy. It permits an origin to send information to another origin, but does not permit an origin to receive information from another origin. In short, it controls the interactions between different origins based on three simple rules:
Thus, it does not prevent against the attacks related to transfer of information
from one origin to another (such as CSRF and clickjacking). The restriction on receiving
information is to prevent malicious web applications to read sensitive
information from other applications. More details on SOP can be found in part
2 of Michal Zalewski’s famous Browser Security Handbook.
Same origin policies define a set of restrictions on several important functionalities within a web browser including DOM access, XMLHttpRequest, cookie setting, etc. However, there are a few exceptions - features which are not subject to same origin checks. Some of these exception are even utilized to circumvent same origin policy (as discussed in the next section).
There are
numerous mechanisms that permit HTML web pages to include and display remote
sub-resources through HTTP GET requests without having these operations
subjected to a well-defined set of security checks. This can be achieved by
using HTML tags such as: <IMG SRC=”...”>
, <SCRIPT SRC="...">
, <LINK
REL="stylesheet" HREF="...">
, <EMBED SRC="...">
, <OBJECT CODEBASE="...">
, and
<APPLET CODEBASE="...">
. These tags are used to issue GET requests to arbitrary
sites and fetch resources. Not only this, any Content-Type
and
Content-Disposition
HTTP headers returned by the server for the sub-resource
are mostly ignored; there is no opportunity to authoritatively instruct the
browser about the intended purpose of a served document to prevent having the
data parsed as JavaScript, CSS, etc. More details can be found at life outside
same-origin
rules
section of the Browser Security Handbook.
The reason why including an
untrusted third-party script (served from a third party domain) in your
application is a bad idea because the origin of a JavaScript file is defined by
the domain of the HTML page which includes it. That is, regardless of their
source, remote scripts always execute in the security context of the document
they are attached to. Once called, JavaScript has full access to the current
DOM, and limited access to DOMs of other windows; it may also further invoke
new JavaScript by calling eval()
, configuring timers (setTimeout(...)
and
setInterval(...)
), or producing JavaScript-invoking HTML. So, for example, if
you include the Google Analytics code with a <script>
tag, it can do anything
to your website but does not have same origin permissions on the Google’s
website.
There are many different ways of circumventing same origin checks and I’ll mention four of them in this section. However, to keep this post short, I’ll only cover basics of the first two techniques, while just touching the remaining two techniques. I will also try to include references for further readings with the techniques.
JSONP is really a simple trick to overcome the XMLHttpRequest same
domain policy. As you know one cannot read an AJAX response from a different
domain. So - instead of using XMLHttpRequest, we have to use <SCRIPT>
tags in
order for JavaScript to get data from another domain. It requires the
application server to send back a JSON response to the client, wrapped around a
callback method provided by the client. So the <SCRIPT>
tag is used to make a
GET request to a source (different domain) such as:
http://www.example.net/sample.php?callback=mycallback. The basically returns
back something like: mycallback({ foo: 'bar' })
. This will invoke the function
mycallback()
which is already defined on client side and thus your script will be
able read the server response. For more information, read this discussion on SO.
There are some security implications of using JSONP in your application. First, it should never be used to read sensitive data because this would allow anyone to read this sensitive information just by including the source (with the call back) in their page. If this is required, make sure the request is protected by using CSRF headers, so that server can identify if a GET request is genuine or not. Second, the callback can be used as a potential XSS (Cross-Site Scripting) vector. As JSONP is really JavaScript, it can do everything else JavaScript can do, so you need to trust the provider of the JSONP data. More details can be found here.
These days, CORS is being used over JSONP as it allows XMLHttpRequests to other domains and does not have any security implications if deployed properly. CORS lets you opt out of SOP restrictions. Read more about CORS here. From wikipedia:
Cross-origin resource sharing (CORS) is a mechanism that allows many resources (e.g., fonts, JavaScript, etc.) on a web page to be requested from another domain outside the domain from which the resource originated. In particular, JavaScript’s AJAX calls can use the XMLHttpRequest mechanism. Such “cross-domain” requests would otherwise be forbidden by web browsers, per the same-origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request. It is more useful than only allowing same-origin requests, but it is more secure than simply allowing all such cross-origin requests.”
Again, CORS can also have serious security implications, if not implemented
properly. For example, if a server is configured to respond to all the origins
(i.e. sets Access-Control-Allow-Origin: *
in the response) and requires
credentials from the client (i.e. sets Access-Control-Allow-Credentials: True
in the
response), then you can trick someone’s browser into making a CSRF style
request. Obviously, this can be protected against such attack using a normal CSRF token.
window.postMessage
, when called, 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 string 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.
Source: Mozilla Developer Network.
Setting up a simple reverse proxy on the server, will
allow the browser to use relative paths for the Ajax requests, while the server
would be acting as a proxy to any remote location. For example, the browser
would be able to request /ajax/test.xml as a relative URL, but the server would
serve this by acting as a proxy to http://other-domain.com/ajax/test.xml. One
interesting feature of the this method is that the reverse proxy can easily
distribute requests towards multiple back-ends, thus acting as a load balancer.
Feel free to email me, if you want me to share something specific or need any advice/help. Please feel free to do the same or leave a comment below, if you have any advice for me or any comment regarding anything on this website. We are all here to learn. That’s what life is all about!