Iframe Buster Buster in a Firefox add-on
I’m the author of a Firefox add-on called Wolfram Alpha Google that shows the results from Wolfram Alpha on the Google search results page whenever you do a search on Google. It worked pretty well up until this Saturday. On Saturday afternoon I came home from the beach and was searching for something on Google when the page suddenly redirected to Wolfram Alpha.
After digging into the problem I found that Wolfram Alpha had added some code commonly referred to as a “frame buster” to their site. This totally broke the add-on so I quickly put together a new version that disabled the add-on and released it on the Firefox Add-on site. On Saturday night Wolfram Alpha had removed the new code and the extension worked as normal again.
Over the last few days I’ve been trying to come up with a proper fix for this and it turns out it’s a lot more difficult than it seems. Basically what I’m trying to achieve is to add a document from one site to another site (in an iframe) and not let the first document have access to the page that it is added to.
Some of the things that I tried were:
- An Ajax request and find and replace the code before loading it –> This works and I’ve used it in my other Add-on (SEM Tools) to load Baidu which has the same problem. But it is very easy for the website owner to break this so it’s not a great solution.
- Using defineGetters (__defineGetter__) –> This DOM method allows you to change the native code that is called when another function accesses the properties of an object. This seems like the ideal solution but I couldn’t get this to work consistently on the window object’s properties. It would work in some situation (e.g. with a local file) but then it would be overridden when the window object changed or it wouldn’t work as part of an add-on. I think there must be a way to make this work but I couldn’t figure it out.
- Replacing the properties on the iframe –> Similar to above but these are mostly read-only so this doesn’t work.
- Iframe within an iframe –> The inner page can still access the top-most page so again no good.
- Iframe within an XUL iframe –> The XUL iframe should act as a barrier to stop the internal iframe accessing the outer page but you can’t insert and XUL iframe into a HTML document because of security restrictions.
- Configurable Security Policies (CAPS) –> These are supposed to give you fine-grained control over what access different websites have, including controlling changing the location on an outer iframe. I couldn’t get this to work though. I’m not sure if this is still part of Firefox anymore.
- Using object tag instead of iframe –>Objects work the same as iframes in this situation so no good either.
- Loading both the Google page and the Wolfram Alpha page in a new XUL browser –> This would work but then the URL bar and the page title would show the wrong name etc.
- Loading the iframe outside of the page. –>This works!
- Copying the above iframe into the main document –> This worked to get the content into the main document but it lost all the styling and I couldn’t interact with the page because there was no reference to the document that it belonged to.
- Loading outside the page and then loading again inside the page –> This works! After all that this was the best solution I could come up with. Basically it won’t load the page if it detects that their is a frame buster being used. You can see the code I used here. However this doesn’t really solve the problem of the access between the documents and it can be worked around too. For example by adding a settimeout to the check for frames code.
One solution to all of this would be to use Wolfram Alpha’s API which I have been thinking about doing. However with the current framework I have, it should be fairly simple to extend it so that it would work with any other website. Using a site-specific API means it will only ever be useful for that one site.
I guess more importantly, why is it so difficult to do something like this? Is including one document in another document without letting them communicate with each other inherently wrong? I don’t think so and in many ways it is a lot more secure than the current implementation of iframes. I think that mash-ups like this are quite a different use case than just wrapping an entire site in an iframe and loading it on a different domain.
If someone has come up with a better solution than this I would love to hear about it. There are a few use cases I have for this that I would love to have a simple function like loadSafelyInIframe(iframe, targetUrl) for.
So as a result of all this, I added this code to the add-on but disabled it by default as it basically doubles the load time. The Wolfram Alpha page is already very slow compared to Google so I felt that this would make it unusable. If you want to be safe or you notice this problem again you can just check the option in the Options screen. The new version is 0.8 and you can get it here once it’s been reviewed by Firefox.