How I achieved cross site scripting

Before I get flamed for claiming the impossible, this is how I achieved a goal that was entirely in AJAX, but I needed it to across different domains!

Some background: Some time ago I found, and implemented this awesome heatmap click tracking for the company I work for. However, since our test machines run everything from one machine (i.e. images and code), when it came to putting it live I never thought for a second it wouldn’t work…which was the result.

It was because the page was being served from one domain, while the click tracking data was being sent to our ‘static’ (non-mod_perl) servers.

I’m posting this up because I think the heatmap is a superb tool for companies, in particular the designers and the marketing people.

Heatmaps will tell both groups whether a particular element is working to focus attention, or if in fact something else is drawing attention that they never thought of.

The way I got around this was to send the data via an ‘iframe‘.

The click tracking needs the server side to record the data, and doesn’t require a response. So, although using AJAX to perform the click tracking (on mouse down from anywhere in the page), equally I can record a mouse down from my main page, but instead, I’m changing the ‘src’ attribute of an iframe which sends the co-ordinates to my static server.

So where he has used the following:

var url='guardacoordenadas.pl?x='+tempX+'&y='+tempY; guardar(url);

I am simply ditching the AJAX aspect of it and changing it to (assuming ‘iframe’ is a variable that I have already pointed to our iframe):

var url='guardacoordenadas.pl?x='+tempX+'&y='+tempY; iframe.src=url;

Here is a simple example of it working (note that Safari doesn’t throw any errors on the cross domain button).

Then I would style the iframe to sit outside of the window:

position: absolute; left: -10000px

Hopefully this is some use to someone else out there.

11 Responses to “How I achieved cross site scripting”

  1. Actually, it’s my intention to not even include the iframe in the HTML, and write a simple jQuery plugin to add the iframe to the foot of the body element.

    That way I don’t end up with an iframe on the page if JavaScript is turned off.

  2. [...] By the way, there has been a post in remysharp blog explaining how to record the clicks in a different server. Thanks. Compartenos!:Estos son iconos de sitios web sociales. Es posible sugerirles esta página para que la recuerden o la publiquen. [...]

  3. Great!.

    I’ve already edited the post to link yours. Feels great to fint there are people clickmapping :)

  4. you have made one possible mistake (depending on what you intended). You appear to be using the query string to pass your variables through to your inner iFrame. This means that the browser cannot cache the url and is making a server request each time. Have you considered using bookmark instead (e.g. http://mycrossdomain.com#tempX=4&tempY=3 ). The advantage of this is that the bookmark component is not considered a different url, so your script would be loaded from the browser cache instead of the server.

  5. @Will – thanks for dropping by. You’re right that if we wanted to cache the result, then doing it via the hash component (i.e. #xyz) would be pulled from the cache.

    However, for this particular problem, heatmap tracking, I needed it to always hit the server creating a record in the logs. It would almost justify cachebusting the URL requested. Cheers.

  6. I was looking at at your code. What you are doing is just loading an iframe. The question is can you get at any of the data within the iframe via a script?

     // Get the iframe 'if'
     var elem = document.getElementById('if);
    
     try{
      // Get the document contained in the iframe
      // An exception will probably occur here, let me know if it doesn't
      // Permission denied to get property HTMLDocument ...
      var returnedDocument = elem.contentDocument;
     } catch (e) {
     alert(e);
    }
    
  7. Jason, there’s no need to access the iframe’s content. It’s just serving as a transport to send information to another server, there’s nothing inside.

    It’s just like the old trick for statistics, but with an iframe.

  8. Hey, Remy:
    I try the bookmark instead(http://mycrossdomain.com#tempX=48)
    but it still send the request to the server, and also , I use jsp to try it ,so
    I use request.getParameter(“tempX”); but the value is null , not 48, but
    if I change “#” to “?” , it can get “48″. so can you give me some advice?\
    thanks.

    –Major

  9. Hi Remy!
    I’ve just found your blog! I’m developing an open source web analytics in
    ruby on rails, and I was trying to port the heatmap click tracking on it (and that’s how I’ve found your blog!). Strange enough, I also live in brighton :)

    I wonder if you’d like to contribute, or maybe you could also find it useful..
    I warn you, it’s in very early stage, but somehow seems to work!
    The name of the project is Ruwa and you can find it on github.

    thanks.
    r.

  10. Hi there,

    It seems like you are just injecting , but as description of cross site scripting, it is impossible to get any data from iframe. I was wondering whether we could inject resources on different domain and actually get data from it. do you know any way?

    Thanks,
    Ebe.

  11. So, this would mean that I could include these AJAX calls in my evil site and then that would generate incorrect heatmap data for you, and even from legitimate visitor IPs if I get some of your visitors.