Let's say you don't want other sites to "frame" your site in an <iframe>
:
<iframe src="http://example.org"></iframe>
So you insert anti-framing, frame busting JavaScript into all your pages:
/* break us out of any containing iframes */
if (top != self) { top.location.replace(self.location.href); }
Excellent! Now you "bust" or break out of any containing iframe automatically. Except for one small problem.
As it turns out, your frame-busting code can be busted, as shown here:
<script type="text/javascript">
var prevent_bust = 0
window.onbeforeunload = function() { prevent_bust++ }
setInterval(function() {
if (prevent_bust > 0) {
prevent_bust -= 2
window.top.location = 'http://example.org/page-which-responds-with-204'
}
}, 1)
</script>
This code does the following:
- increments a counter every time the browser attempts to navigate away from the current page, via the
window.onbeforeunload
event handler - sets up a timer that fires every millisecond via
setInterval()
, and if it sees the counter incremented, changes the current location to a server of the attacker's control - that server serves up a page with HTTP status code 204, which does not cause the browser to navigate anywhere
My question is -- and this is more of a JavaScript puzzle than an actual problem -- how can you defeat the frame-busting buster?
I had a few thoughts, but nothing worked in my testing:
- attempting to clear the
onbeforeunload
event viaonbeforeunload = null
had no effect - adding an
alert()
stopped the process let the user know it was happening, but did not interfere with the code in any way; clicking OK lets the busting continue as normal - I can't think of any way to clear the
setInterval()
timer
I'm not much of a JavaScript programmer, so here's my challenge to you: hey buster, can you bust the frame-busting buster?
What about calling the buster repeatedly as well? This'll create a race condition, but one may hope that the buster comes out on top:
Use htaccess to avoid high-jacking frameset, iframe and any content like images.
This will show a copyright page instead of the expected.
After pondering this for a little while, I believe this will show them who's boss...
Using
_top
as the target parameter forwindow.open()
will launch it in the same window.I think you were almost there. Have you tried:
or, alternatively:
Note: I didn't actually test this.
Came up with this, and it seems to work at least in Firefox and the Opera browser.
If you look at the values returned by
setInterval()
they are usually single digits, so you can usually disable all such interrupts with a single line of code: