Let's assume we have a web page that can't use X-Frame-Options
, and the Clickjacking protection has to be JavaScript based. On this page, all sensitive actions and the display of sensitive information are JS based, so for the sake of the question we can assume JS is enabled and running.
The current standard technique involves comparing self
with top
, and to display content depending on the outcome. Example from OWASP:
<style id="antiClickjack">body{display:none !important;}</style>
And then delete that style by its ID immediately after in the script:
<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
I would call this approach "fail closed" because content remains invisible until JS considers self
equal to top
.
There's also a commonly used "fail open" technique where, if self
does not equal top
, content is hidden via CSS or by setting document.body.innerHTML=''
.
Question: can the latter protection be bypassed in ways other than using the sandbox
attribute on the parent's iframe?
I didn't think so until I read this blog comment comparing the two techniques, and it made me wonder whether "fail open" is safe enough:
"You could use various JS payloads on the parent page to make the framebusting script in the iframe fail, preventing it from hiding the content of the page. [...] The ones that instead make the content of the page appear if it is not being framed were and are still perfectly fine."