EvanK
EvanK

Reputation: 1072

Sandboxing content in an IFRAME, on the client side

The issue

I have some javascript content that I want to "sandbox" into an iframe:

<script type="text/javascript">
    doSomethingPotentiallyMalicious( // ideally, i want this to be able to run...
        top.document.getElementById('sensitive_information') // ...but want this to fail due to cross-domain permissions
    );
</script>

The catch is, due to the nature of our web application, I need to do this inline on the parent page that contains the iframe, and I need to do this in a cross-browser compatible way.

Data URL...almost but not quite

I was able to get the desired effect in Chrome by setting content in the iframe via a data url:

<iframe id="sandbox" src="data:text/html;charset=utf-8,%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%20%20%20%20doSomethingPotentiallyMalicious(%20%2F%2F%20ideally%2C%20i%20want%20this%20to%20be%20able%20to%20run...%0A%20%20%20%20%20%20%20%20top.document.getElementById('sensitive_information')%20%2F%2F%20...but%20want%20this%20to%20fail%20due%20to%20cross-domain%20permissions%0A%20%20%20%20)%3B%0A%3C%2Fscript%3E"></iframe>

However, data url support is spotty and this needs to work cross-browser.

Document.write gets the content there, but lacks cross-domain security

I can have the unsafe content in a javascript escaped string, and then write it as the content of an iframe:

<iframe id="sandbox" src="http://google.com/"></iframe>
<script>
    var unsafeContent = '\x3Cscript\x20type\x3D\x22text\x2Fjavascript\x22\x3E\x0A\x20\x20\x20\x20doSomethingPotentiallyMalicious\x28\x20\x2F\x2F\x20ideally,\x20i\x20want\x20this\x20to\x20be\x20able\x20to\x20run...\x0A\x20\x20\x20\x20\x20\x20\x20\x20top.document.getElementById\x28\x27sensitive_information\x27\x29\x20\x2F\x2F\x20...but\x20want\x20this\x20to\x20fail\x20due\x20to\x20cross\x2Ddomain\x20permissions\x0A\x20\x20\x20\x20\x29\x3B\x0A\x3C\x2Fscript\x3E\x0A\x0A';
    var sandbox = document.getElementById('sandbox');
    sandbox = (sandbox.contentWindow) ? sandbox.contentWindow : (sandbox.contentDocument.document) ? sandbox.contentDocument.document : sandbox.contentDocument;
    sandbox.document.open();
    sandbox.document.write(unsafeContent);
    sandbox.document.close();
</script>

The problem with this is, once I write that content to the iframe, the cross-domain security is apparently no longer there (meaning that doSomethingPotentiallyMalicious function has access to the everything in the parent window).

Document.write + Document.domain doesn't seem to get us there, either

I even tried changing the document.domain (by removing the left-most domain so "www.example.com" becomes "example.com") per this previous SO post, but this doesn't seem to enforce a cross-domain policy, either:

<iframe id="sandbox" src="http://google.com/"></iframe>
<script>
    // prepended to unsafeContent: document.domain = document.domain.replace(/^[\w-]+\./,'');
    var unsafeContent = '\x3Cscript\x20type\x3D\x22text\x2Fjavascript\x22\x3E\x0A\x20\x20\x20\x20document.domain\x20\x3D\x20document.domain.replace\x28\x2F\x5E\x5B\x5Cw\x2D\x5D\x2B\x5C.\x2F,\x27\x27\x29\x3B\x0A\x20\x20\x20\x20doSomethingPotentiallyMalicious\x28\x20\x2F\x2F\x20ideally,\x20i\x20want\x20this\x20to\x20be\x20able\x20to\x20run...\x0A\x20\x20\x20\x20\x20\x20\x20\x20top.document.getElementById\x28\x27sensitive_information\x27\x29\x20\x2F\x2F\x20...but\x20want\x20this\x20to\x20fail\x20due\x20to\x20cross\x2Ddomain\x20permissions\x0A\x20\x20\x20\x20\x29\x3B\x0A\x3C\x2Fscript\x3E\x0A\x0A';
    var sandbox = document.getElementById('sandbox');
    sandbox = (sandbox.contentWindow) ? sandbox.contentWindow : (sandbox.contentDocument.document) ? sandbox.contentDocument.document : sandbox.contentDocument;
    sandbox.document.open();
    sandbox.document.write(unsafeContent);
    sandbox.document.close();
</script>

Is what I'm trying to do even technically feasible at this point?

Upvotes: 6

Views: 2393

Answers (1)

Nathan Breit
Nathan Breit

Reputation: 1671

I wonder if window.postMessage would work. You could set up an iframe that evals the first message it receives to inject javascript into it. According to the site I linked, it works in Firefox, IE8+, Opera, Safari, and Chrome. Hopefully that's cross-browser enough for you. Mobile devices might have issues with it.

Upvotes: 2

Related Questions