Tuesday, November 29th, 2005

How to make XMLHttpRequest calls to another server in your domain

Category: Articles

<p>Abe Fettig, of JotLive and Twisted fame, has written up his experiences trying to get XMLHttpRequest calls working across domains.

He discusses three approaches that he took to make this happen:

  1. The naive approach

    Abe verified that he couldn’t access one domain from another.

  2. Using an iframe and document.domain

    iframes aren’t limited to pulling pages from same web server as their containing page – they can load any URL. To prevent cross-site security problems, browsers enforce the same origin policy in the javascript object model: scripts running in one frame can’t access any objects inside another iframe, unless both pages came from the same server.

    There’s an exception to this rule, however. If both pages come from the same parent domain, and both of them set the property document.domain to the same parent domain, scripts running in either frame will be allowed to talk to each other. For example, say the page http://www.example.com/ loads the page http://ajax.example.com/ in an iframe. Since both pages are in the domain example.com, if both set document.domain to “example.com” they will be be given the ability to programatically access each other’s data.

    So, can you use an iframe with document.domain to make XmlHttpRequest connections? Yes, with two restrictions:

    • The iframe must be served from the server to which you’ll be making XmlHttpRequest calls.
    • You have to open the XmlHttpRequest connection before you set document.domain.
  3. Repeated XmlHttpRequests

    Although the iframe approach is working for a single XMLHttpRequest, what about if you want to do multiple requests to different domains? Abe tried a technique that changes document.domain for different XHR hits. This worked in IE and Safari, but not Mozilla or Opera.

  4. Making it work in Mozilla
  5. To get multiple XHRs working in Mozilla, Abe uses a bridge iframe:

    parent window
      bridge iframe
        child iframe
    

    And he programatically creates iframes that he needs:

    <html>
      <head>
      <script type="text/javascript" src="xmlhttp.js"></script>
      <script type="text/javascript">
        function gotTime(result) {
          window.parent.gotTime(result); // pass result up to the parent
        }
        window.onload = function(){
          var subframe = document.createElement('iframe');
          document.body.appendChild(subframe);
          subframe.src = "test4-iframe.html";
          subframe.contentWindow.bridgeGotTime = gotTime;
          document.domain = "fettig.net";
        }
      </script>
      </head>
      <body></body>
    </html>
    

Update: Abe found that Firefox 1.5 fixed things, so he didn’t need the bridge.

Related Content:

12 Comments »

Comments feed

I find it interesting that people are continually trying to get around the cross-domain limitation of XHR but only useful to the extent that it helps inform the browser builders of where they should close loopholes.

News just broke that Yahoo mail now includes an RSS reader. Imagine that the script-stripping ability isn’t quite perfect and that someone can execute a script from an RSS item in the reader. With any sort of cross-domain ability (or even an extended image url), XHR can now be used to harvest all that person’s emails and send them off to any given domain.

The vulnerability with supporting cross-domain requests is not of course the owner of the domain but with the possibility of XSS. What I would really like to see as a solution to all these problems is some way of firewalling content within a page.

Imagine that instead of having to strip all script tags, content could just be enveloped in a -firewall- (or whatever) tag that prevented all script execution within it. What an easier place the world would be.

There is a half-cocked solution tot this at the moment which is putting content in an iframe from a different domain. As you make clear in the article above though, the problem with this is that you cannot then modify the content of that iframe from the parent.

What we could really do with is some sort of asymmetric script access. I’m glad I’m not the one that’s got to figure out how to implement it though!

Comment by Peter Nixey — November 30, 2005

Peter,

I don’t believe the technique described here opens any new security holes. It doesn’t enable XHR between any two random sites. Both sites have to be in the same domain, and they have to be explicitly cooperating with each other by serving up complementary code.

Comment by Abe — November 30, 2005

I just posted an updated version of this code that works in Firefox 1.5 without any hacks at all.

Comment by Abe — November 30, 2005

Abe,

You’re right of course and to be honest I didn’t catch the fact that they both needed to be specifically communication which does rather change things.

Although it wasn’t meant to be an attack on your technique, I still stand by my original point though which is that cross domain requests carry great dangers. Techniques like arbitrary redirection on the server leave a web application far more vulnerable to attack.

Nonetheless I am very much in favour of having some sort of trusted domains. Web services are great but when they all have to use one domain as a proxy they can become somewhat arduous.

Peter

Comment by Peter Nixey — December 1, 2005

I sort of wish there was something akin to Flash’s crossdomain.xml for JavaScript. There really are times when I want to make cross-site requests—ie. between vendors’ servers where a site’s hosted on our servers and one vendor offers JS-powered metric events and another offers another service

Comment by l.m.orchard — December 2, 2005

Setting document.domain after doing the xmlhttprequest is impossible in my case. This is a clear example of misconfigured and paranoid browser security.

Comment by Dave D — July 20, 2006

_l.m.orchard_

It may be a bit paranoid, but imagine having a site like myspace, with an exploit used to push a javascript snippet (as has been done), but now, instead of spreading though just myspace, every pageview on myspace will now hammer *your* web server… effectively a ddos attack.

It’s a good thing to have security in mind in the web space.. in IE, you can add the site to your “Trusted” sites, and set security for that context to LOW… would be nice for similar settings for Firefox, etc.. allowing you to override for your apps.. but for the general web.. it’s a good thing.

Comment by tracker1 — August 29, 2006

Hi Abe, it mite seem funny rite now but i still have problems making request using the xmlhttprequest approach from my firefox mozilla browser i really need assistance.Each time i make a request to my server it throws an uncaught exception that i do not have authorised permission to make an xmlhttprequest.open request. meanwhile am working with svg and javascript. my servlet is what am trying to calls. this is supposed to load an svg page from the servlet.
Can i get any help its really getting frustrating for me.

Comment by Hilda — November 29, 2006

whenewer u discuss abt any technique pls describe it in the detail….

Comment by suraj — September 6, 2007

I saw this code before, a goo day of crossing domain

Comment by ohr — October 28, 2007

might i get the full code example?

Comment by tpaulengineer — March 10, 2010

I figured it out myself. thanks

Comment by tpaulengineer — March 16, 2010

Leave a comment

You must be logged in to post a comment.