Today’s web applications are put together a mesh up a new
experiences into one experience. Think Twitter widgets showing the latest
tweets about a product. Or Facebook comments discussing an article. Or even just
integrated web pages through an IFRAME element. These experiences can
increase security breaches to your site.
Don’t stress ... there’s a new kid on the block to help you
out: The HTML5 Sandbox. But before I get to that, let’s quickly review IFRAME element
issues.
A Black Box
Embedding content with an IFRAME is like announcing
a party publically on Facebook. You think you know who you invited, but really
you have no idea who passed it on and who’ll show up.
The same is true for framing content. You know what you
are referencing, but you have no clue how the site will evolve in the future. Content
or functionality (or both) can change any time. Without you knowing…and
without your approval.
Security Concerns Using iframe
Browsers handle pages that use IFRAME just like
any other web page. Forms can be used to retrieve user input, scripts can be
executed, the page can navigate within the browser window, and browser plugins
can be executed. And just like the party crashers who get out of hand, you
have no control what the hosted content will do.
There is one mechanism in place by default that prevents
some kinds of attacks: the cross-domain policy.
Re-hosting Content from Another
Domain
If hosted content is coming from another domain,
cross-domain policy comes into play and it prohibits the “foreign” content to
access the parent’s document object model.
So, the embedded page is not able to read, for instance,
cookies or the browser's local storage for the hosted domain. But there are
still risks left.
Hosted content can still re-navigate on the top level. By
displaying content the user would expect, the site could attempt to phish
confidential information from the user. Or, by using a similarly styled form,
attempt to maliciously capture user information that way.
That’s why, even with the cross-domain policy in place,
there are still big security risks.
Re-Hosting Content from the Same
Domain
The case for re-hosting content from the same domain is
even worse.
When the content comes from the same domain, there are no
default security restrictions in place. Embedded content can access the
complete loaded browser DOM and manipulate everything.
It kind of makes sense that content on the same domain should
be safe. The risk here primarily stems from user-generated content that is re-hosted
in the IFRAME.
A Sandboxed Approach
These valid security concerns hadn’t been properly addressed
by a standards body for a long time. Without a clear W3C standard, it was
essential to somehow secure the host from framed content. For example, Microsoft
provided a proprietary implementation of IFRAME security in Internet Explorer 8. Others
picked it up and discussed it as the baseline for their browsers as well. But
standards have matured greatly since IE8.
Modern browsers including Chrome, Firefox, and IE10 Platform Preview are
based on the W3C IFrame Sandbox Attribute.
Here’s what we’ll build today with Sandbox. See the demo
here.
Let’s begin by applying the sandbox. Just add it as empty
attribute to the IFRAME element:
<iframe sandbox src="http://somewebsite.com/default.html"></iframe>
That’s it!
Now, IFRAME sandboxed content is re-hosted in the
browser with the following restrictions:
- Plugins are disabled. Any kind of ActiveX, Flash,
or Silverlight plugin will not be executed.
- Forms are disabled. The hosted content is not
allowed to make forms post back to any target.
- Scripts are disabled. JavaScript is disabled and
will not execute.
- Links to other browsing contexts are disabled. An anchor tag targeting
different browser levels will not execute.
- Unique origin treatment. All content is treated under
a unique origin. The content is not able to traverse the DOM or read cookie
information.
This means that even content coming from the same domain
is treated with the cross-domain policy, as each IFRAME content will be
viewed as a unique origin.
Embedded content is only permitted to display
information. No other
actions can be done inside the IFRAME that could compromise the hosting
website or take advantage of the users’ trust.
Checking for the Sandbox
Attribute
We know that an IFRAME is an open gate. We know
that the sandbox attribute locks down security of hosted content. The
decision is clear: Use IFRAME elements just with the sandbox attribute!
You can confirm that the browser supports the IFRAME
sandbox attribute with a simple check in JavaScript:
if( "sandbox" in document.createElement( "IFRAME" ) ) {
} else {
}
If it is supported, just use the sandbox attribute. If
not, try to embed the content through other ways or encourage the user with a
message that he should upgrade to a modern browser.
Customizing the Sandbox
There are cases where you’ll need some level of
customization on the restrictions, which is absolutely possible.
Several attribute values relax the standard sandbox
policy:
allow-forms
If you want to enable forms post back within the IFRAME
element, you just specify the allow-forms value for the sandbox
attribute.
<iframe sandbox="allow-forms" src="xyz.html"></iframe>
If this value is present, the embedded page is allowed to
post back using a form submit within the frame.
allow-scripts
JavaScript is a powerful language and is often used to
have dynamic interactions on the client side without resending information to
the server. But that power also brings risks when re-hosting foreign web pages.
Therefore, you should carefully consider whether you really want to enable
JavaScript in IFRAME scenarios -- especially when the content is from an
unknown source.
Enabling JavaScript is done through the allow-scripts
value.
<iframe
sandbox="allow-scripts" src="xyz.html"></iframe>
allow-same-origin
By default, an IFRAME page from the same domain
has the possibility to access the parent’s document object model.
With the sandbox attribute in place, the page will be
treated as not being from the same origin. This page has no access to
the resources, even when coming from the same domain.
To re-enable same-origin treatment in a sandboxed
scenario, you have to specify the allow-same-origin attribute.
<iframe sandbox="allow-same-origin" src="xyz.html"></iframe>
The value itself is not very helpful, as you need some
script capabilities to make use of it.
For example, if you want to access the local storage of
the current domain like this:
function loadFromStorage( key ) {
if( localStorage ) {
return localStorage.getItem( key );
}
});
... you also need the allow-scripts value:
<iframe sandbox="allow-scripts allow-same-origin" src="xyz.html"></iframe>
Now access works!
But be warned: Allowing multiple scripts in the same sandbox can lead to
security vulnerabilities. For example, your hosted content can manipulate the attributes
of the sandbox and remove further restrictions.
allow-top-navigation
When you use the sandbox attribute, anchor targeting
other browsing contexts are ignored and not executed by default. This protects
the website hosting the IFRAME content from being replaced by the hosted
content.
For example, this link would not be executed in the
default sandbox, as the target would replace the complete web page:
<a
href="xyz.html" target="_top">Click me</a>
Relaxing this policy is only recommended if you trust the
content you host.
<iframe sandbox="allow-top-navigation" src="xyz.html"></iframe>
ms-allow-popups
Sometimes it is useful to allow embedded content opening
up new popup windows. A perfect example is a mapping service like Bing Maps.
When embedding Bing Maps, additional functionality like driving
directions or destination details can be looked up in popup windows. But since sandbox
prohibits this, there’s a setting in Internet Explorer 10 that will enable popups
without compromising the sandbox.
The following code shows how to set up ms-allow-popups.
<iframe sandbox="ms-allow-popups" src="xyz.html"></iframe>
When setting this value, embedded sites are able to
display information in a new window.
<a href="xyz.html" target="_new">Show Info</a>
Putting It All Together
You can combine several attribute values on one sandbox. For
instance, if you want to enable forms post-back, top-level navigation and
JavaScript, just specify
<iframe
sandbox="allow-forms allow-top-navigation allow-scripts"
src="xyz.html"></iframe>
It is also good to know that the sandbox behaves
correctly when used in hierarchical situations, using several nested IFRAMES
with different sandbox attribute values. The top-level sandbox always dominates
down the hierarchy.
Get hands on!
You can play around with the HTML sandbox in this
demo. And you
can download a copy
of this demo from Github. To enable the form post-back demo, just open the
project folder in WebMatrix and start the project from there.
Then, download a modern browser (like Internet Explorer 10 Platform
Preview)
and get familiar with the sandbox by reading the IE
developer guide.
This single attribute is a big step toward a more secure web ... and modern
browsers are finally ready to sandbox embedded content.