AppSec Blog

Clickjacking: Help, I Was Framed!

Security researchers discovered and disclosed the Clickjacking attack (also known as a "UI Redress Attack") back in 2008. All major browsers were affected. Flash even had an interesting vulnerability that allowed control of a user's microphone and webcam. Yet, here we are 7 years later still citing this issue on nearly every security assessment of web applications that we do. During our report delivery, development teams typically have one of the following responses: "What's Clickjacking?", "What can someone really do with this?", or "So what?".

I'd like to take a minute to explain a little bit about this exploit, give a quick example, and talk about a few ways to mitigate this issue.

The Exploit

Clickjacking involves hosting a form from the application in an iframe and tricking the user into activating the form. A common way to do this is to set the opacity of the iframe to 0 (rendering it invisible) and placing a link over a button on the application form.

clickjacking_hidden1

Don't see anything dangerous? Let's turn the opacity on the iframe to 1.

clickjacking_visible1

By clicking on the "Get My Free Trip!" link, we just purchased a few things off the attacker's dream list.

The Defense

You're probably wondering how you can protect yourself against clickjacking? It's really pretty simple. All we have to do is add the X-Frame-Options response header and set it to "DENY" framing, or only allow it to come from the "SAMEORIGIN" (aka our site). This can be done by setting the response header in your code, changing the web server configuration, or simply using the OWASP Secure Headers tools, such as SHIM for .NET or Headlines for Java. No matter which route you take, you should see this response header from your server:

HTTP/1.1 200 OK
Server: nginx
X-FRAME-OPTIONS: DENY
Date: Tue, 17 Mar 2015 20:54:56 GMT
Content-Length: 29553

One thing to note is that while this solution works for all MODERN browser versions, it does not work for older versions. Below is a list of browsers and the version support was added for the X-FRAME-OPTIONS header:

Chrome: 4.1.249.1042, Firefox: 3.6.9, IE: 8.0, Opera: 10.50, Safari: 4.0

So, what do we do for legacy browsers? It's pretty simple too. OWASP recommends a style tag that hides the body, and a piece of JavaScript that removes the tag if the page is not framed, or breaks out of the frame if it is. We add a style tag with an id of "antiClickjack" that hides the body.

<style id="antiClickjack">body{display:none !important;}</style>

We follow this with a javascript that removes the style tag if we are the "top" (aka not in an iframe) or break out of the iframe by setting our location to the top.

<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>

Adding these solutions to your project globally can help you avoid an incident without taxing the server or adding much to the development cycle.

Happy (secure) coding!

References:
[1] http://ha.ckers.org/blog/20081007/clickjacking-details/
[2] http://www.sectheory.com/clickjacking.htm
[3] https://github.com/sourceclear/headlines
[4] http://shim.codeplex.com/
[5] https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet

About the Author
Aaron Cure is a senior security consultant at Cypress Data Defense, and an instructor and contributing author for the DEV544: Secure Coding in .NET course. After ten years in the U.S. Army as a Russian Linguist and a Satellite Repair Technician, he worked as a database administrator and programmer on the Iridium project, with subsequent positions as a telecommunications consultant, senior programmer, and security consultant. Other experience includes developing security tools, secure code review, vulnerability assessment, penetration testing, risk assessment, static source code analysis, and security research. Aaron holds the GIAC GSSP-.NET, GWAPT, GMOB, and CISSP certifications and is located in Arvada, CO.

Post a Comment






Captcha


* Indicates a required field.