Mixendo XHR: cross-domain Security
Contents |
The XMLHttpRequest() JavasScript object [1], [2] has been introduced to allow asynchronous requests to a server without refreshing a whole page.
In this section we will first introduce XMLHttpRequest() security issues and existing solutions, then the security model of the Mixendo Cross-Domain XHR solution. For those in a hurry that do not need all the details, you can trust that Mixendo takes your security seriously!
Common Security Concerns
We will use Douglas Crockford's words [3] to introduce the matter:
- XMLHttpRequest has a security model which is inadequate for supporting the next generation of web applications.
- (For this reason) XMLHttpRequest is constrained by the Same Origin Policy.
The Same-origin policy [4], [5] was introduced by Netscape 2.
- This constrains the interface to only connect with the server that delivered the base page. This rule deals with some common, long-standing security flaws in web architecture.
It is said that:
- If the 'Same Origin Policy' were not in place, then the user could be harmed by XSS (cross site scripting) or Cross-site request forgery (XSRF) attacks.
An example can help understand what is the potential problem with an open cross-domain XHR:
- In the following examples, we will have a page that was created by miscreants at pirate.net. That page will attempt to compromise the user's relationship with penzance.org.
- If the Same-Origin Policy were not in effect, a pirate.net page could send a request via XMLHttpRequest to penzance.org. That request would carry the penzance.org cookies. If penzance.org were using cookies for authentication, then it would be tricked into acting on the request as though it had been initiated by the user. Any request to a site will carry the cookies associated with the site. This would allow pirate.net the right to use penzance.org cookies.
- If penzance.org sits behind a firewall, and if the internal servers assume that the firewall makes explicit authorization unnecessary, then the pirate.net page could be used as a proxy, accessing the contents of penzance.org for transmission back to pirate.net. This would be possible because XMLHttpRequest can obtain XML-like data (such as HTML documents) as well as non-XML text.
- The Same Origin Policy frustrates these attacks, but it also frustrates a larger class of legitimate uses.
- It should be possible for a script in a page to access data from other servers without compromising the security of the user or his organization.
In short, in this example a malicious website could exploit cross-domain XHR reusing an authentication cookie to impersonate him and act on his behalf. Please hold with us until the end of this article to learn that cross-domain is not at all necessary to implement this kind of attack!
It is interesting to note, before we move XSS, that
- the Same Origin Policy does not apply to scripts. So some developers have begun to dynamically generate <script> tags to connect to any server. The server sends back a script which delivers some data. Unfortunately, the script runs with the same authority as a scripts from the originating page, allowing the script to steal cookies or directly access the originating server. This is unsafe. If a penzance.org page loaded a script from pirate.net, the script could damage the relationship between penzance.org and its users by stealing cookies and making requests of the penzance.org server.
Attacks
You can get a short summary on this Ajaxian page [6]
Cross-site scripting (XSS)
The definition of XSS given in Wikipedia [7] is very general:
- a type of computer security vulnerability typically found in web applications which allow code injection by malicious web users into the web pages viewed by other users. An exploited cross-site scripting vulnerability can be used by attackers to bypass access controls such as the same origin policy. Vulnerabilities of this kind have been exploited to craft powerful phishing attacks and browser exploits. As of 2007, cross-site scripting carried out on websites were roughly 80% of all documented security vulnerabilities. Often during an attack "everything looks fine" to the end-user who may be subject to unauthorized access, theft of sensitive data, and financial loss
Cross-Site Request Forgery (CSRF or XSRF)
Another type of attack is similar to XSS but goes the other way by using the trust a website has in a request coming from a known user is the XSRF [8]
- a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts. Contrary to cross-site scripting (XSS), which exploits the trust a user has for a particular site, cross-site request forgery exploits the trust that a site has for a particular user.
Basically, it is very similar by the example described before: a malicious webmaster embeds a request to another page in his page; the user by visiting that page will generate a request to that other page on another domain. This can result into
- an attack towards the server: the server might receive a heck lot of requests, potentially on a specific service, eg. the Digg attack (it might be worth noting that a far more complex, XSS+XSRF Digg exploit has been possible recently, and again without any cross domain)
- an attack towards the user: when the hidden link can toggle on a server some action on behalf of the user, in particular if the user has already logged into that service and has cookie lying around
Often XSRF is due to poorly developed servers, but not all the blame can be put there, and some better defined security properties and protocols would definitely help.
Chris Shiflett's article "Foiling Cross-Site Attacks" [9] can provide a few more examples.
The truth about XHR security
Now that we got your attention with this catchy title, we can tell you something important: web applications are not secure just because cross-domain is not enabled.
Since the Same-origin policy does not apply, say, to <script src=""> , <img src="">, and <iframe src=""> it is possible to easily implement a lot of attacks just by using one those. Riding sessions based on cookies is not too complicated and does not require Cross-domain XHR! What gets really trick, it must be admitted, is to make a 2-steps request, such as building a webpage capable of getting a single-time token from another website before trying to executing some operation on it. The DIGG exploit [10] is now much more difficult to implement, needing to get a token before digging a story.
We also invite you to read two (slightly outdated) posts, "Debunking Strong Misconceptions About Cross-Domain Ajax Security Issues" by Lucas Carlson [11] and "Cross-Domain Ajax Insecurity" by Chris Shiflett [12], and always remember to do your own thinking; don't forget to read the comments too (and REALLY remember to do your own thinking!).
As mentioned previously, some exploits can even be embedded on third web sites that do not properly escape user inputs; and a server-side proxy can be used to carry some malicious attacks.
Proper server-side development helps mitigating these attacks (accept only POST to perform actions, for instance, which is btw the correct way to be compliant with HTTP standard; require a single-use Token to perform an action; etc.).
In short: it's true that opening Ajax to Cross-Domain might make some of these attacks easier, but keeping it disable does not protect you either, and is a fake feeling of security really better?
W3C recently came out with the Access Control for Cross-Site Requests draft [13]. Basically it allows a server to accept an XHR request from another web application, by the mean of a configuration file and an HTTP exchange. This standard only satisfies a little part of the problem, since it does not increase the overall security of XHR and will have issues scaling (which webmaster will take the time to choose one-by-one the mash-up applications allowed to access his website?).
Flash has a similar security approach [14]. Basically this approach only works when collaborating people are working on two web applications and are implementing cross-site between them!
So what happens when you want to build your own mash-up applications, and possibly with inherent security guarantees? This is where the Mixendo XHR solution shines!
Mixendo XHR Security Approach
We want cross-domain, but we do not want to open it up wildly. We then decided to implement a self-declarative access control.
Let's say your web application on the domain yourmashup.com wants to access two other websites, domain1.com and domain2.com. We call those ones sources, since you are getting data out of them. When registering your developer key, you will have to declare that your application will be hosted on yourmashup.com and will connect to those two sources. Any other cross-domain connection will be denied.
This makes the mash-up application users aware of what's potentially going to happen, since he can immediately spot connections that should not happen; we can also block HTTPS protocol, or clean up cookies.
Also, we can block any developer's key if a (valid!) security complaint is filed, or block some specific sources, for instance if we are aware of some flaws that would be easily exploited via XHR.
We know this is not a perfect security model - but we do not live in a perfect world either, so waiting for better, we believe our access control solution can mitigate the risks of opening xmlhttprequest() to cross-domain.
Our recommendations
Since we do not think the Same-origin policy is safe, we do not think opening cross-domain up with our Access Control limitations is any more unsafe.
We do have, though, a very important recommendation for all internet users: always be careful when visiting unknown website.
Never, ever give authentication or sensitive information to a website (or widget!) that you do not trust or do not know. This is true both when using an application Powered by Mixendo, or any other application. And remember, any tool can be misused, and new bugs are found every day, as the number of security exploits out there can show.
A better Cross-Domain Security Model?
That's what we hope and strive for. It's not something which will be built into your web browser in a very short time though! So we came out with this solution. But please trust us, we are working hard towards a better mash-up word! And your comments are precious.