7

tl;dr Can I execute un-trusted scripts on an iframe safely?

Back story:

I'm trying to make secure JSONP requests. A lot of older browsers do not support Web Workers which means that the current solution I came up with is not optimal.

I figured I could create an <iframe> and load a script inside it. That script would perform a JSONP request (creating a script tag), which would post a message to the main page. The main page would get the message, execute the callback and destroy the iframe. I've managed to do this sort of thing.

function jsonp(url, data, callback) {
 var iframe = document.createElement("iframe");
 iframe.style.display = "none";
 document.body.appendChild(iframe);
 var iframedoc = iframe.contentDocument || iframe.contentWindow.document;
 sc = document.createElement("script");
 sc.textContent = "(function(p){ cb = function(result){p.postMessage(result,'http://fiddle.jshell.net');};})(parent);";
 //sc.textContent += "alert(cb)";
 iframedoc.body.appendChild(sc);
 var jr = document.createElement("script");
 var getParams = ""; // serialize the GET parameters
 for (var i in data) {
 getParams += "&" + i + "=" + data[i];
 }
 jr.src = url + "?callback=cb" + getParams;
 iframedoc.body.appendChild(jr);
 window.onmessage = function (e) {
 callback(e.data);
 document.body.removeChild(iframe);
 }
}
jsonp("http://jsfiddle.net/echo/jsonp/", {
 foo: "bar"
}, function (result) {
 alert("Result: " + JSON.stringify(result));
});

The problem is that since the iframes are on the same domain, the injected script still has access to the external scope through .top or .parent and such.

Is there any way to create an iframe that can not access data on the parent scope?

I want to create an iframe where scripts added through script tags will not be able to access variables on the parent window (and the DOM). I tried stuff like top=parent=null but I'm really not sure that's enough, there might be other workarounds. I tried running a for... in loop, but my function stopped working and I was unable to find out why.

NOTE:

I know optimally WebWorkers are a better isolated environment. I know JSONP is a "bad" technique (I even had some random guy tell me he'd never use it today). I'm trying to create a secure environment for scenarios where you have to perform JSONP queries.

asked May 22, 2013 at 0:05
3
  • 1
    What if you set the document.domain of the iframe as something else? Therefore, they won't be able to talk to other without postMessage. Just an idea. I remember that you can let them talk if you set them both to the same value, so I wonder if doing the opposite would yield the opposite. I'm messing around with some stuff in the fiddle; this is an interesting question, and I like your approach :) Commented May 22, 2013 at 0:35
  • @Ian can I change document.domain myself in the iframe's code? If I do, can I guarantee that it won't be changed back by the malicious code? Commented May 22, 2013 at 0:37
  • Yeah, I'm pretty sure you can. Well, you can change the value in the parent page as well to something random/unique too, then it would be pretty hard for the iframe script to guess and match it. I think I should've thought through the whole scenario before commenting, but it may be something you could toy with. I forget the point of setting it and what it actually changes, I just remember seeing it being synced so that a window and iframe could talk (by what means, I can't remember) Commented May 22, 2013 at 0:41

2 Answers 2

1

You can't really delete the references, setting null will just silently fail and there is always a way to get the reference to the parent dom.

References like frameElement and frameElement.defaultView etc. cannot be deleted. Attempting to do so will either silently fail or throw exception depending on browser.

You could look into Caja/Cajita though.

answered May 30, 2013 at 14:46
Sign up to request clarification or add additional context in comments.

Comments

1

tl;dr no

Any untrusted script can steal cookies (like a session id!) or read information from the DOM like the value of a credit card input field.

JavaScript relies on the security model that all code is trusted code. Any attempts at access from another domain requires explicit whitelisting.

If you want to sandbox your iframe you can serve the page from another domain. This does mean that you can't share a session or do any kind of communication because it can be abused. It's just like including an unrelated website. Even then there are possibilities for abuse if you allow untrusted JavaScript. You can for instance do: window.top.location.href = 'http://my.phishing.domain/';, the user might not notice the redirect.

answered May 22, 2013 at 0:08

8 Comments

How? It works with WebWorkers , what is the core problem preventing me to delete all references to the parent window inside the iframe? I tried doing so and didn't succeed, but I'd like to be convinced it's impossible. Can you give me an example of something I can't set to null here jsfiddle.net/Xwu3S before the second script tag is executed which will compromise security? In your example, can't I do window.top = null; ?
I don't know man, you are asking 3 questions in one. What question are you referring to?
I'm asking just one thing: "Why is the answer no?", your argument is that the script might steal information, you show it by the example window.top. .... I'm saying I can set window.top to null. I'd like to see why that would not help me. I'm not saying you're wrong, I just want to understand what the inherent issue is.
I don't know about that .. there could be ways around it. For one you could use window.parent till you reach the top. You could perhaps block that as well but maybe there's a way around that too. At the very least you can do window.location.href and send the user anywhere. How are you going to block that? It becomes a cat and mouse game that you will lose because the mouse only has to score once.
Intereting points. For all I care the external JSONP service can freeze the browser, they can navigate the iframe away, they can move stuff in it. It's an invisible iframe, they can easily run while(true){} which would hang the browser since an iframe runs on the same thread. The only thing I really care about is security. I don't want to let the iframe to execute the DOM, or the JavaScript variables in my main window in any way. As long as I keep users' data safe, that's a win for me.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.