— This post is part of a series of blog post about all kinds of Security topics for Developers —
Clickjacking is still one of those amazingly simple attacks that are also easy to prevent. That is, if you know what clickjacking is, because considering the amount of websites that are vulnerable, not many developers know about this.
In a clickjacking attack, an attacker attempts to ‘hijack’ clicks by making the user think he is clicking something else. The basic idea here is that the attacker loads the thing he wants you to click on in an invisible iframe and then shows you something else. For example, you may see a button ‘Click here to get a Free iPad’, but when trying to click it the button, the click-event goes to a ‘Transfer $1000,- from my creditcard’ button in the invisible iframe. Clickjacking may cause all kinds of harm to the user. E.g. the hacker may get access to your webcam, steal money, send emails on your behalf, or worse… It is possible to hijack basically any type of event in the browser (like mouse events or key strokes) if the website that executes that action is not properly secured.
Clickjacking is a special form of ‘Window UI redress’. The basic idea is always to show the original web page in which the actions are performed, but make it look different (redress) to make the victim more likely to execute the action. A hacker can ‘hijack’ user actions like mouse clicks, key presses or other events, and use them for a different purpose than the user thinks it is. Usually the user won’t even know that he loaded the website until after the harm was done.
A (simplified) code example probably gives you a better idea:
<html> <body> <iframe src="vulnerable-site.com/dangerous/function/" style="opacity: 0;"></iframe> <button>Click for free iPad</button> </body> </html>
A hacker could create this page to induce users to click a link on the vulnerable site. It first contains an invisible iframe (opacity: 0) which loads the vulnerable site. And then there’s a button that induces the user to click on it. The user will think he’s clicking the button, but since the iframe came first, the click-event is handled by the iframe and the dangerous function gets executed.
The idea behind clickjacking prevention is that you tell the browsers whether your site can be loaded in an <iframe> (or <frame>, <object>, <embed> or <applet>) or not, and if you want to allow it, which domains can embed your site. There are also client side mitigations, like plugins that warn you when clicking invisible content. However, as a developer you shouldn’t want to rely on your users installing such plugins, so we’ll focus on the server side mitigations.
There’s different options:
Never let your site load in any iframe
This is the easiest situation. Send these two HTTP headers in each and every response to the browser:
X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none'
Only let your site load on a specific domain
Usually you’ll want your site to load in an iframe on the same domain, in which case you can just use the following HTTP headers in your responses:
X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self'
If you want to allow loading on a different domain, use this syntax:
X-Frame-Options: ALLOW-FROM https://different-domain.com Content-Security-Policy: frame-ancestors different-domain.com
Note that X-Frame-Options is a lot more strict, so you need to specify the scheme as well as the full domain. With Content Security Policy it is possible to leave the scheme and even use wildcards.
Allow your site to load on multiple specific domains
In this case it easiest to just go for the Content Security Policy header, because that allows you to specify the domain in a list, or with the use of wildcards:
Content-Security-Policy: frame-ancestors example.com, *.example2.com
The drawback of Content Security Policy is that many older browsers (including Internet Explorer up until verion 11) don’t support it.
Unfortunately X-Frame-Options doesn’t support multiple domains. If you really don’t want to let IE11 users down, you can check the referrer header on the server, and if it appears in your whitelist, you can put that specific domain in the X-Frame-Options header. It is a bit nasty, but it is your best shot.
Check the support for both headers in different browsers here:
- Can I use X-Frame-Options?
- Can I use Content Security Policy?