Posted on Mar 06, 2013

I recently had to do some research for a collegue who had some questions about "clickjacking", the practice of hosting a website inside a hidden or transparent iframe (the target), positioning that frame over top of another inocuous, innocent looking page (the attacker) that has a call to action.  The user clicks what they think is something simple (like a video play button) but instead they're clicking on a page element inside the transparent iframe, initiating some action on the target website.

For example, an attacking website could get a user to login to their banking website without them knowing, depending on whether the user had configured their browser to autofill in their username and password on the site.  The attacking site could go on to do lots of other things, tricking the user into transfering money or whatever.

Scary stuff.

I should probably drop a DISCLAIMER here: I am in no way a security guru and don't pretend to be, so if you're concerned about this stuff, do your research or hire an expert!

The old way

A few years ago, the standard defense against having your website hosted inside another site's iframe was to use javascript to "bust out" of the frame.  The code was very simple:

if(top != self) top.location.replace(location);

This has proven to not be sufficient enough to help your site from getting clickjacked as there are a number of work arounds, from using a little known proprietary iframe attribute supported by IE7 which stops all javascript on the target page from being executed, to more sophisticated attacks that use javascript event handlers to intercept the target page's attempt to redirect the top level page and kill it using a confirmation dialog or a 204 server response code.

Note that HTML5's new sandbox attribute gives attackers the same options as the IE7 proprietary attribute did.  In fact, it's more powerful as it can not only shutdown javascript execution (which could potentially break the target site's functionality and therefore make the attack useless) but can also shutdown redirects without shutting down javascript.  So you get a functioning site that can't break out of the iframe.

The current way

Fortunately, we have two weapons at our disposal, a new page header that most modern browsers support, and a new-ish javascript+CSS fix that overcomes the weaknesses of the old frame buster code.

X-Frame Options

This is a new header that you can add to your site's pages which tells modern browsers whether your page is allowed to be shown within an iframe, and if so, which domains are allowed to do so.  (Ironically, this new proposal came from Microsoft, added in their IE8 browser)  You can read more about it and how to configure Apache to use it over at the Moz Dev Network.

Javascript + CSS

This solution comes from a Standford University report on clickjacking from 2010 and seems to have become the current standard for clickjack defence in legacy browsers that do not support X-Frame Options.  The solution is simple: use CSS to hide all (or some) of the content on your site, and then attempt to use javascript to redirect the page if it's not the top level document.  If it is a top level document, then unhide all the site content.

<style id="antiClickjack">body{display:none !important;}</style> <script type="text/javascript"> if (self === top) { var antiClickjack = document.getElementById("antiClickjack"); antiClickjack.parentNode.removeChild(antiClickjack); } else { top.location = self.location; } </script>

The result is that the targetted page is not only invisible visually, but also "invisible" from a browser layout perspective, so the user can't actually interact with anything on the page.

Caveat Emptor

All of the Google-ing I did on this topic gave me articles and posts that were already 3-4 years old, so from what I can tell the above represents the state of the art and hackers have yet to find a way to circumvent these precautions.  That doesn't mean it hasn't been circumvented, so again, seek council from a security expert if you really want to be sure.

Further reading: