Third Twist [Malware, plugins, sandboxes]

Twist #3 — Same Origin Policy restricts the DOM access and JavaScript behavior of content loaded from multiple origins. Malware only cares about plugin and browser versions.

The web relies on browsers’s ability aggregate resources from multiple origins. This lets us enjoy everything from improved performance by offloading static resources to Content Delivery Networks, staying up to date on JavaScript libraries by linking to their repositories or hosting sites (which also improves performance because browsers can reuse the cached library for unrelated sites), to more visible examples like embedded images so we can shop and spread memes.

The Same Origin Policy prevents resources with different origins from accessing each other’s content. The browser coalesces all unrelated resources into a DOM, but only those who share an origin may read attributes or modify contents. This is intended to prevent a malicious origin from modifying another site’s content. It also provides a small degree of privacy in terms of blinding other origins to the content of a resource. (In practice, this blinding has a few exceptions and workarounds.) While an advertising network might wish to know exactly what your Facebook page looks like, there’s no reason an ad banner from a non-Facebook origin should be able to access your data — Same Origin Policy prevents such behavior for good reason.

However, malware attacks care more about the version of your plugins than the content of your pages. Most opportunistic malware uses an iframe to load a Flash or Java exploit into the browser. The Same Origin Policy doesn’t prevent a resource from being requested, it merely sandboxes read access to that resource for identical origins. Hence, a malware-laden iframe dances happily with its plugin-busting partner to compromise your browser.

Protect yourself from malware by keeping the browser up to date. A modern browser is able to update itself, but that won’t alleviate the other source of woe: plugins. You can use a site like Qualys Browsercheck or Mozilla’s Plugincheck to check your browser’s health. Be diligent about applying updates; the time between vulnerability disclosure and exploit continues to shrink.

The Same Origin Policy rarely impedes HTML injection attacks. Successful injections enjoy the benefits of executing within the page’s origin — hardly a desirable situation.

Developers have always relied on the kindness of secure coding to prevent HTML injection, leaving users with few defenses other than a plugin like NoScript or a browser’s feeble XSS Auditor to block exploits when hackers partake of coders’ mistakes.

Part of the underlying problem of preventing HTML injection from a design perspective is the lack of granularity in the Same Origin Policy. HTML5 addresses this by adding new attributes to the iframe element:

  • sandbox — places the iframe into its own origin that is restricted from executing scripts, submitting forms, or creating new browsing contexts (e.g. opening a new window). A set of “allow-…” values modify these restrictions. This attribute establishes security boundaries within the DOM, the last line of defense against insecure server-side code.
  • seamless — places the iframe into the same browsing context as its containing element. This is useful for establishing visual unity and DOM access for scripting. It does not create any new security boundaries; the iframe’s browsing context is merged with its containers, effectively “weakening” the security of DOM separation normally associated with iframes. Note that this weakening is intentional in order to accommodate site designers who want this behavior.

HTML5 makes it possible to sandbox content so that you could have an iframe that displays a message (an email, tweet, status update, etc.) with high confidence that the message would be unable to launch an XSS payload even if it contained <script> tags or bypassed server-side validation (you’re still doing that, right?). We’ve switched topics from malware to HTML injection, but the sandbox attribute protects against most malware because plugins are disabled in a sandboxed browsing context.

While there’s an allow-scripts value to enable JavaScript inside a sandbox there’s no way to re-enable a plugin. Good. Browsers are allowed — though highly discouraged — to let users bypass this restriction. One goal of HTML5 is to do away with plugins altogether in order to have a uniform, platform-agnostic browsing experience, so this is hardly a strike against the spec. Plugins have had a history of breaking Same Origin Policy, actively working outside of it, and not adhering to the browser’s security or privacy settings. More reasons to uninstall them from your browser.

Should you wish to experiment with the sandbox attribute, first create a page to act as the framed content. One simple example executes the always-popular JavaScript alert().

<!doctype html>
<html><body> 
<script>
alert(19);
</script>
</body></html>

Next, create some HTML that loads the alert page inside a sandboxed iframe. If you see the alert, then it’s likely your browser doesn’t support the sandbox attribute. (It’s also possible there’s a typo in your HTML. For example, a space was necessary in the following iframe tags to keep WordPress from misinterpreting the text.)

<!doctype html>
<html>
<body>
< iframe sandbox src="canary.html"></iframe >
</body>
</html>

A sandboxed iframe is placed into a unique origin. This prevents it from matching any other resource during a Same Origin Policy check. A sandboxed iframe with origin http://web.site:80 is distinct from any other resource whose origin is http://web.site:80. In other words, the sandbox’s origin is not the usual protocol, host, port triplet extracted from its URL, but a value that never matches another origin (for example, a Boolean isUnique flag). You can see this in action within WebKit’s source code:

void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
{
  m_sandboxFlags |= mask;
  // The SandboxOrigin is stored redundantly in the security origin.
    if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) {
      setSecurityOrigin(SecurityOrigin::createUnique());
      didUpdateSecurityOrigin();
    }
}

The sandbox attribute’s allow-same-origin value removes the iframe from this unique origin and returns it to the origin of its non-sandboxed equivalent (the familiar protocol, host, port). This enables the browser to apply the usual Same Origin restrictions between resources. The allow-same-origin value would only be necessary if resources must interact with the iframe. Not again that this “weakens” the iframe boundary. Once again, it’s available because there are legitimate design patterns for which this is useful. A “weakened” iframe falls into the usual security associated with non-framed DOM elements.

< iframe sandbox="allow-same-origin" src="canary.html"></iframe >

Finally, it’s possible to re-enable JavaScript execution inside the sandbox by using the allow-scripts value:

< iframe sandbox="allow-scripts" src="canary.html"></iframe >

Note that sandbox and seamless attributes are mutable. Their presence and their values may change during the DOM’s lifetime. This also implies that malicious scripts may try to modify values in order to break out of sandboxes or attempt to sandbox themselves to prevent inspection by surrounding content. (An iframe sandbox would stop a framed content’s JavaScript-based anti-framing code, for example.) It’s also a warning that a combination like sandbox=”allow-same-origin allow-scripts” could permit a framed resource to modify the iframe’s attribute; thereby evading the sandbox altogether.

If you followed the link to WebKit’s SecurityContext.cpp source code, you might have noticed that WebKit supports another sandbox value (originally from Internet Explorer) not yet enumerated in the HTML5 spec: allow-popups. This is another example where developers update the spec to accommodate real-world situations where functionality breaks in undesirable ways. The option, as you likely guessed, permits the iframe to open popup windows.

Sandbox and seamless already exist in some browsers. The spec isn’t finalized yet (as allow-popups shows), nor is the new code in browsers bug-free. Never the less, it’s not too early to start implementing it for your web site. At the very least the site remains status quo, the attributes will be ignored by the vast amount of browsers that are either out of date and insecure or merely out of date. At best, you improve security for visitors who have modern browsers. And along the way you’ll have a chance to improve the security architecture of your site.

The iframe sandbox disables plugins, which in turn defuses most malware. It also disarms attacks like HTML injection that rely on JavaScript execution to succeed. It’s another security boundary around untrusted content that helps reduce the ever-present problem of insecure web sites.

1 thought on “Third Twist [Malware, plugins, sandboxes]”

Comments are closed.