Web page encapsulation has long been a concern during web application vulnerability assessments. Early attacks consisted of malicious websites that encapsulated legitimate websites within a frame and used JavaScript “keyloggers” to steal login credentials. This issue became known as Cross Frame Scripting. To mitigate this risk, login pages of secure sites embedded “frame busting” JavaScript to prevent the page from being encapsulated within another site. This JavaScript would detect if the page was in a frame, and set itself as the “top” frame if it was
<script type="text/javascript"> if(top != self) top.location.replace(location); </script>
Reputational risk was also seen in simply having a reputable website embedded within a frameset of an attacker’s site. Having a high profile website embedded within a malicious website is not desirable for any organization. The framekiller code above became popular for many high profile websites. Unfortunately, many techniques were shown to disable the framekiller code. This quickly became a war of framekiller killers and so on. As time went on, another risk was identified with framing; A page could be framed, but completely overlaid with the malicious parent frame. While the malicious parent frame could control the entire visual shown to the user, it could also trick users into clicking parts of the hidden child frame. A classic example would be a JavaScript game of shooting targets by clicking a mouse, however the user would actually be clicking items on the web application encapsulated frame. This became known as Clickjacking, or a “UI Redress Attack”. As an ethical hacking service provider, convincing clients they needed to insert this JavaScript on every page of a web application was not an easy task. Surely there was a better solution. In 2009 Microsoft proposed the ‘X-Frame-Options’ (“XFO”) HTTP header and bundled support with Internet Explorer 8. This header was quickly supported by Firefox, Chrome, Opera, and Safari. The X-Frame-Options gave three options:
X-Frame-Options: DENY X-Frame-Options: SAMEORIGIN X-Frame-Options: ALLOW-FROM www.example.com
This header was the first clear instruction for web browser to disallow framing and is much more effective than the prior JavaScript protections. Unfortunately XFO does have some potentially misleading characteristics. The most common value specified is SAMEORIGIN, which does not check all ancestors of the current page. This allows content which is framed on the page, to frame another instance of the parent page. A malicious ad on your site can quite easily frame a new request of the top page. Most people would assume they were protected by SAMEORIGIN, but only DENY can prevent a clickjacking attack in this situation. Below shows a proof of concept of this attack:
Recently there has been some effort to add a Content Security Policy (CSP) directive to CSP 1.1 specifying a ‘frame-options’ directive which would supersede the XFO header, however this is not yet built into the specification. For now (July 2013), we should continue to use X-Frame-Options to restrict malicious framing. It is strongly recommended the ‘DENY’ directive be set as not all browsers fully support XFO options such as ‘ALLOW-FROM’.