Framekiller

A framekiller (or framebuster or framebreaker) is a technique used by web applications to prevent their web pages from being displayed within a frame. A frame is a subdivision of a Web browser window and can act like a smaller window. It's usually deployed to prevent a frame from an external Web site being loaded from within a frameset without permission often as part of clickjacking attack.

Implementations

Framekillers are implemented using JavaScript that validates if the current window is the main window. The recommended approach is to block rendering of the window by default and only unblock it after confirming the current window is the main one:

<style> html{display:none;} </style>
<script>
   if(self == top) {
       document.documentElement.style.display = 'block'; 
   } else {
       top.location = self.location; 
   }
</script>

This approach was proposed in 2010 by Gustav Rydstedt, Elie Bursztein, Dan Boneh and Collin Jackson in a paper that highlighted the limitations of existing frame-busting techniques along with techniques allowing to bypass them.[1]

Although this may seem like a very credible study, it must not have actually been tested? It states that doing

    if (window.location !== window.top.location) window.top.location = window.location;

will not work in a double frame. This is not correct. Doing a simple test using 3 html pages, the first having a frame to the second, the second having a frame to the third. The third having this JS (to prevent manipulations of window):

    (function (window) {
        if (window.location !== window.top.location) window.top.location = window.location;
    })(this);

and the page got rid of both the middle and the top frame. This will be true regardless of how many layers of frames you have and should be the best approach to deal with this issue.

Alternative solutions

An alternative choice is to allow the user to determine whether to let the framekiller work.

var framekiller = true;
window.onbeforeunload = function() { 
  if(framekiller) {
    return "...";  // any message that helps user to make decision
  }
};

and the code below should be added after the frame tag:

//"my_frame" should be changed according to the real id of the frame in your page 
document.getElementById("my_frame").onload = function() { 
  framekiller = false;
};

Original framekillers

Historically, the first framekiller scripts were as simple as this:

<script type="text/javascript">
  if(top != self) top.location.replace(location);
</script>

The logic here was to display the page, but check if the top location is the same as the current page, and replace the top by current if not. This method however can be easily bypassed by blocking execution of the framebuster script from the outer frame.[1]

Framekiller limitations

Client-side JavaScript solution relies on the end-user's browser enforcing their own security. This makes it a beneficial, but unreliable, means of disallowing your page to be embedded in other pages. The following situations may render the script above useless:

Anti-Framekiller

The iframe in HTML5 has a sandbox attribute.[2] The attribute's value is a set of allowed capabilities for the iframe's content. If the value is empty or not set, the iframe's content will not execute JavaScript, and won't allow top-level navigation. By specifying allow-scripts in the space separated set of exceptions in the value, the iframe will allow JavaScript, but will still disallow top-level navigation, rendering framekillers in the iframe impotent.

See also

References

  1. 1.0 1.1 G. Rydstedt, E. Bursztein, D. Boneh, C. Jackson (2010). "Busting Frame Busting: a Study of Clickjacking Vulnerabilities on Popular sites". 3rd Web 2.0 Security and Privacy workshop. IEEE.
  2. http://www.w3.org/TR/html5/embedded-content-0.html#attr-iframe-sandbox