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.

Adoption of X-FRAME-OPTIONS Header

Late 2008, Jeremiah Grossman and Robert Hansen publicized the clickjacking problem and got the web app security experts all trying to come up with solutions. One of the more viable solution is the X-FRAME-OPTIONS header that allow a site to control whether its content can be within a frame.  There are two settings to this header, DENY blocks the content from being in a frame and SAMEORIGIN only allows the content to be framed by pages within the same origin. While it is not the end all and be all of clickjacking solution and won’t work in some sites that extensively use frames across multiple sites, it is considered as a more reasonable approach for sites to protect their own content.

Johannes Ullrich and I got a little curious about the adoption of X-FRAME-OPTIONS header in the major sites.  We went and got the list of top sites according to Alexa and see if the top sites actually use X-FRAME-OPTIONS header.  We expected the results to be low, but when we looked at the results from visiting all these sites, we were a slight bit surprised.  Of the TOP 10,000 sites from the Alexa’s list, only 4 sites have the header specified.  That number obviously is very low.

Not having the X-FRAME-OPTIONS header does not mean these site are not protected from clickjacking, maybe they are using some type of Javascript framebusting, we haven’t looked at how many have framebusting deployed yet.  It is widely believed that the Javascript only defense is not as good as the attacker could disable Javascript in the frame by setting SECURITY=RESTRICTED on the IFrame to disable the Javascript defense.

As a side note, I am doing my personal part on promoting the X-FRAME-OPTION. In the next major update of my SANS DEV422 course (soon to be 522), there will be emphasis on various defenses against Clickjacking that a site owner can leverage.