How should a web site deal with a user who doesn't run JavaScript? Abort (fallback to non-JavaScript version of the site), Retry (give the user a friendly error message that it's necessary to have JavaScript enabled to use the site), Ignore (continue blindly rendering a probably unusable page), or Fail (simply load nothing)? I've seen every one of these in practice, and there's no standard. Some users have JavaScript completely disabled, either for security reasons or because they are on a device (like a Blackberry) that doesn't support JavaScript. Some users have JavaScript temporarily disabled, using NoScript (like me) to whitelist trusted sites.
I propose that if you can put together a functional site that doesn't use JavaScript, fall back to this site when the user doesn't support JavaScript. If you can't, give the user a friendly error message, but hide the functionality.
The same thing is true for cookies. What's the right way to check that cookies are enabled and respond gracefully if they aren't? Showing an error message? Rewriting the URL with the session ID? Just not working? Since cookies are the best way to support sessions securely, I propose that if you need to support sessions, present an error message to users with cookies disabled.
If the web is really just a composition of technologies, how should it respond when some technologies are missing? Why don't browsers and application frameworks give us easy ways to check for these dependencies?
Clickjacking is a recently disclosed attack where users are fooled into unknowingly performing sensitive actions on external sites. It's been demonstrated in several
videos. Although it's similar to cross-site request forgery, it can't be prevented using a secret token - all form submissions and link clicks look valid because the user is interacting with the actual site.
Several proposed fixes are outlined nicely here. I'd like to focus on framebusting, which is the simplest solution.
Framebusting uses JavaScript to "bust" out of any top-level frame, usually:
if (top != self) top.location.href = location.href;
Attempts to load a page that has this code into a frame will result in the framed page "busting" out of the frame and taking over the full browser window. It works – but there are some problems.
- It's opt-in. No one is protected by default.
- It doesn't work for pages that need to be in frames legitimately.
- JavaScript needs to be enabled.
- It may cause a performance hit.
- It can be defeated in Internet Explorer (6 and up) using the security=restricted attribute.
This last issue is troubling – the browser with the largest market share has a non-standard "feature" that looks like a security flaw. But the security=restricted attribute was implemented for a valid security reason. According to the project manager for IE, it was meant to protect against malicious advertisements in frames which may attempt to forward the user to unintended sites through JavaScript. Whether or not the net security "profit" of the feature is positive or negative is subjective, but it certainly has pros and cons.
As a side note, some researchers have found ways to bypass the security=restricted attribute, but it requires control of the outer frame, which doesn't prevent clickjacking.
One way to deal with the problem of clickjacking when your site is placed in a security=restricted frame is to hide all content and then display it with JavaScript, along these lines:
<head>
<script type="text/javascript">
document.getElementById('all').style.display = 'block';
</script>
</head>
<body>
<div id="all" style="display:none;">
[Site content goes here]
</div>
</body>
This works because pages in frames that are set with a security=restricted attribute are placed in a zone that doesn't execute script, by default, and the controls that the attacker would need to get you to click on are hidden. Many sites use a similar approach to give a friendly error message to people who don't use JavaScript.
Not a perfect solution, but it does make it more difficult for the attacker. Until we have a complete solution, it's what I'll recommend and include in the .NET ESAPI.