Friday, April 5, 2013

HTML5 Sandbox - a bad idea

About sandbox.

I don't like both idea and implementations of the Sandbox feature (part of so-called HTML5). Most of the articles about it are lame copy-pastes of the spec. Straight question WHY WE NEED IT AT ALL remains not answered. Furthermore, nobody writes that implementation is a little bit crazy — by fixing small vulnerabilities it introduces huge ones.


When we embed frames with external content we are still open for navigational and/or phishing attacks (obviously cookies/inner HTML cannot be stolen because of the same origin policy). The iframe code can change top.location or open a phishing popup window prompt('your password?'). ... that's it. That's all we needed to fix.

Besides allow-popup and allow-top-navigation options W3C introduced allow-scripts, allow-forms and allow-same-origin. They wanted best you know the rest.

Javascript... malicious shit.

OMG, sandbox can load any page with javascript turned off.

People are still fixing CSS for IE6. Meanwhile W3C destroys all Javascript-based framebreakers, not asking anyone's advice (only one anti-clickjacking solution left - X-Frame-Options). Nobody gave a shit about compatibility, I guess.

W3C needed a really good reason to introduce such a crazy feature: "Javascript from a frame can do malicious actions, now you can turn it off".
Malicious what? Tomorrow they will call Javascript a Remote Code Execution Vulnerability and ask us to remove the browser? Javascript cannot be malicious on it's own!

allow-forms + disallow scripts = clickjacking working like a charm for javascript-based framebreakers. Surely, not everyone uses X-Frame-Options yet, e.g. UPDHere is a talk from BlackHat 11 last 2 years it is WontFix :O

Untrusted code on the same origin.

Another announced killer-feature of Sandbox - running untrusted code on your origin (remark: USE A SUBDOMAIN DONT BE STUPID). People tend to believe it: "Cool, I will set up a javascript playground on my website!". This?

<iframe src="SITE/playground?code=alert(1)" sandbox="allow-scripts"> 

Now think again, what stops an attacker to simply use 'SITE/playground?code=alert(1)' as an XSS hole?

Following may sound like a genius idea to prevent it - putting Sandbox into Content-Security-Policy header and let server-side to set sandbox directive. So far only Chrome supports such header (I use this technology in Pagebox - XSS protection through privilegies).

You cannot rely on it out-of-box, thus you need a way more comprehensive solution — you have to make sure that current page is loaded under sandbox (request is authentic), not in a new window

Server-side on th owner page: cookie[:nonce]=SecureRandom.hex(16).

HTML code: <iframe src="SITE/playground?code=alert(1)&nonce=123qwe123" sandbox="allow-scripts"> 

Playground server side: if params[:nonce] and cookie[:nonce] == params[:nonce] ..response..

Now you are secure from arbitrary code reflection. Anyway, don't use it. 

Sandbox was intended only to prevent top navigation (related frame navigation madness) and "phishing" popups. Severity of fixed = very low.

Eventually Sandbox simply broke the Web by creating a new clickjacking bypass. Severity of introduced = high.

Misleading posts make people think that Sandbox is a secure way to embed arbitrary content, but there are strings attached.

I don't mean Sandbox is all bad, I only state that current Sandbox is a poorly designed feature.


  1. You should use a different domain as there are tricks to leverage arbitrary js on a subdomain.

    Sandboxing is to help protect the client from arbitrary crap. It was never intended to protect the server.

    1. And as for UI Redressing (aka ClickJacking) browsers that support the sandbox attribute must support X-Frame-Options.

    2. > It was never intended to protect the server

      did I say something about server protection? I am just telling sandbox does A LITTLE BIT of good and A LOT OF bad.

      >And as for UI Redressing (aka ClickJacking) browsers that support the sandbox attribute must support X-Frame-Options.

      of course they do, but "compatibility" - you will not be surprised that most of websites don't use XFO? Some of them used framebreakers and they don't employ security experts. Now they are vulnerable again. No good

  2. With all respect deserved, since you clearly have a refined opinion on this subject, could I suggest a re-edit of the text it's self?

    Attempting to read through this, with the various bold sections whipping my attention from point to point to point, and the slivers of paragraphs, made this a terribly difficult post to read, format wise, though well thought out, and well informed it may be.

    As I said, this is with all due respect, and with thanks for the thoughtful post.

    1. Related, and to show that I do truly appreciate your contribution here. I've done a little research to try to make things easier. Here's a Stackoverflow post which could help.

    2. yeah i think i overplayed with bolds.. removed some.

  3. piffle. Permitting an iframe to reach outside of itself was a bad hack in the first place - switching to x-frame-options and allowing an iframe to be properly safe is no more than a long-overdue remedy to a really lazy mistake. Many years from now, when promising young students demand to know why sandboxing is not default, we will be embarrassed by the answer.

    1. > why sandboxing is not default

      postMessage everywhere FTW

    2. postMessage is a hack on top of a hack. There's no mechanism for letting our container emit and receive events, but we can get pointers to other windows for some reason, so let's just tie both ends together and call it good. It's not good. It doesn't take us far enough toward iframe's unfulfilled promise of modularity, and it doesn't work well with any system that would.

    3. I don't understand you. postMessage can emit, onmessage can receive.. what's wrong there?

  4. I completely disagree. It doesn't break framebreaking scripts at all (try Facebook's), only the ones that were useless/insecure in the first place.

    1. > that were useless/insecure in the first place

      they were not insecure until sandbox. how could you bypass them before ?

    2. if new feature makes something insecure then THIS feature is guilty, not websites

    3. Actually, they totally were insecure in the first place. Specifically, any framebusting script that would make the page disappear if it detected framing was insecure.

      You could use various JS payloads on the parent page to make the framebusting script in the iframe fail, preventing it from hiding the content of the page. And this was pretty much impossible to reliably prevent (also because of browser bugs). See OWASP's page (sorry but you asked for it):

      The ones that instead make the content of the page appear if it is not being framed were and are still perfectly fine.

      All in all, html5 sandbox didn't change anything except it just made it more obvious that a bad protection was bad, and this is always a good thing.

    4. there are kinds of framebreakers they were still working w/o sandbox. these are broken now

    5. Alright, which ones ???

    6. To be clear, the original article is so vague (while sounding so confident) that I'm pretty sure you didn't really look into the subject too much and were just convinced that you understood all of it. Well, you didn't.

      The other thing that's really funny is the example you give for "Untrusted code on the same origin". It has an obvious XSS hole in the parent page. Yes, the parent page, not the content of the iframe, where using html5 sandbox would be meaningful. Let me insist: breaking out of the iframe tag's src attribute is an XSS in the parent page and has absolutely nothing to do with what you're talking about; your example is absolutely 100% irrelevant.
      However, you use it to explain why html5 sandbox is supposedly "a bad idea".

      TLDR: bad, uninformed article is bad.

    7. all vectors with document.write('') were not vulnerable until sandbox.

      1. sandbox is not part of CSP, this makes sameorigin option useless (and obvious-XSS shows it). misdesign
      2. sandbox allows switching JS off but NOBODY asked for it. We never needed it, we don't have use of it. misdesign + breaking some JS framebreakers
      3. while u stay anonymous i cant feel involved into discussion with you. original article is indeed vague, I wanted to keep it short. read last sentence:
      "I don't mean Sandbox is all bad, I only state that current Sandbox is a poorly designed feature."

      i emphasise sandbox is 60% of useless and dangerous shit, while it could be much simpler, CSP based and so on.

  5. Hey Egor,

    What are your thoughts about running a sandboxed iframe *without* allow-scripts?

    If you wanted your web app to show user-generated HTML email, like this:

    <iframe seamless sandbox="allow-same-origin allow-popups" srcdoc="<html><head><base target='_blank'><style>body{margin:0;}</style></head><body>{{escaped_email_body_html}}</body></html>"></iframe>
    (only done in browsers that support sandbox)

    See any issues?