Break Out of Frames
This tutorial explains some ways to use JavaScript to prevent your pages from being framed. Also known as “frame busting” or “breaking out of frames”.
Disclaimer
Although the techniques provided in this article can be highly effective at breaking out of frames, it is possible for a determined framer to override the JavaScript and prevent it from working. 99% of the time, you’re not gonna have to worry about framing wars, where something like the following can happen:
- Framer frames your page
- You add a frame-busting script to break out of frames
- Framer responds by adding a frame-busting buster to stop your script from breaking out of their frames
- You retaliate with a frame-busting-busting buster, to stop the frame-busting buster from working
- ..ad nauseam until someone gives up or goes insane
There is plenty of literature describing the back-and-forth battle between content publishers and content framers, for example this thread sums up the struggle that people can get into. But again, in my years of experience, I’ve never had any problem with someone breaking my frame-busting script. That doesn’t mean it won’t happen, just that it’s not something that should stop you from trying the following techniques, which work great at busting your pages out of frames.
That said, let’s get on with it!
Your basic “break-out” script
To stop framers, copy & paste this basic script to your document <head>
:
<script type="text/javascript">
if (top !== self) top.location.href = self.location.href;
</script>
There are a million different variations of the noframes/anti-frames JavaScript. Here is another one of my favorites:
<script type="text/javascript">
if (parent.frames.length > 0) {
top.location.replace(document.location);
}
</script>
This is one of the oldest tricks in the book, but remains an effective solution. This script basically says, “if the topmost frame is not the same URL as the current page, redirect to the current page.” Easy and effective (in most cases).
Break out with pop-up alert
A nice way to make the previous method more user-friendly (or less, depending on your perspective) is to include an informative popup alert notifying the visitor that you are saving them from utter scandal:
<script type="text/javascript">
if (top !== self) {
alert('You are being redirected to the original source of this content at '+ self.location.href);
top.location.href = self.location.href;
}
</script>
..or alternately we can do:
if (top != self) {
top.location.replace(document.location)
alert('You are being redirected to the original source of this content at '+ self.location.href)
}
When placed in your <head>
, either of these methods will display a nice little popup that says something like this:
“You are being redirected to the original source of this content at example.com”
Of course, the URL specified will match that of your original page. After the popup is displayed, the visitor will be taken to the page indicated in the message. Clean, effective, and fun.
Stop a specific site from framing
While the previous methods work great for breaking out of any frame, there may be situations where you need to stop only a specific site from hijacking your scene. To do this, we customize the following PHP code and place into the top of our web pages:
<?php
$blocked_site = 'example.com';
$referrer = $_SERVER['HTTP_REFERER'];
$referrer_data = parse_url($referrer);
if ($referrer_data['host'] === $blocked_site) {
echo '<script>if (top !== self) top.location.href = self.location.href;</script>';
} ?>
Edit the $blocked_site
variable to match the domain name of the site for which you would like to stop from framing your site. So for example if I want to stop dirty-framers.net
from framing my pages, I would edit the code thus:
$blocked_site = 'dirty-framers.net';
That way you can allow legit sites like feed reader services, apps and whatnot to display your content in frames, while specifically targeting any abusive domains.
Allow framing only for whitelisted sites
Blocking specific sites is fine, but what if we want to reverse the strategy and allow framing for a specific set of whitelisted sites? Rob Larsen delivers the goods:
<script type="text/javascript">
if (top != self ) {
var whitelist =[
document.location.hostname // your own site
];
var i;
var test = whitelist.length;
var safe = false;
for (i=0; i < test ; i++) {
if (document.referrer.indexOf(whitelist[i]) != -1 ) {
safe = true;
}
}
if (safe === false) {
top.location.replace(document.location);
}
}
</script>
And here is the author’s original commented version to help people understand what’s going on in the code:
<script type="text/javascript">
/*
If the topmost frame is not the document calling the code
we do some stuff to make sure we're not being hijacked
*/
if (top != self ) {
/*
Add a whitelist array. Add any site you WANT to be able to frame your site.
The default allows for your own site to frame the page. It just seemed like the way to go.
Are there any other typical sites that need to be whitelisted?
*/
var whitelist =[ document.location.hostname ];
var i;
var test = whitelist.length;
var safe = false;
/*
Then we simply test for the presence of the frame's location in the whitelist array
*/
for (i = 0; i < test; i++) {
if (document.referrer.indexOf(whitelist[i]) != -1 ) {
/*
if it is, it's safe
*/
safe = true;
}
}
/*
If it's not, bust a move and kill that (hijacking) noise
*/
if (safe === false) {
top.location.replace(document.location);
}
}
</script>
This is something that I have been wanting to use at Perishable Press to break out of illicit frames while still enabling Google Reader and other cool services to frame my stuff.
To use this script, place into the <head>
section of your web page(s) and add any “allowed” sites to the whitelist. Here is an example showing the current default plus a couple of external domains:
var whitelist =[
document.location.hostname // indicates your own site
google.com // for Google Reader et al
example.com // whatever else
];
Emulate these entries to allow as many (or as few) domains as necessary. Once uploaded, this script will break your site out of any frame that is not owned by the whitelisted domains.
One for the road..
Here is an advanced technique originally shared in a post titled, “anti anti Frame Busting” by coderrr (original article now offline):
<script>
function bust() {
if (top != self)
setInterval("top.location.replace('http://cached-bust-out-page.com/with/redirect')", 1);
}
</script>
<!-- cache it! -->
<iframe onload="bust()" src="http://cached-bust-out-page.com/with/redirect"></iframe>
After including that script, you must set the proper Expires headers for the cached page, for example:
Expires: Sun, 19 Aug 2050 14:10:44 GMT <-- far enough in the future
Last-modified: Wed, 16 Sep 2015 13:25:30 GMT <-- now
According to the author of the original tutorial, this is the “holy grail” of anti-frame-busting busting scripts. Test carefully and let ’em know who’s boss!