Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a Same Domain iframe Secure

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.

like image 204
Benjamin Gruenbaum Avatar asked May 22 '13 00:05

Benjamin Gruenbaum


People also ask

Are iframes a security risk?

iframes are a great option to keep your users more engaged. But, when you use an iframe, you're handling content from a third-party source that you have no control over. As a result, iframes often pose security threats to the applications.

Should iframes still be used?

Iframes Cause SEO Problems. Google recommends refraining from creating iframes. At there Webmasters Help Forum, Google clearly stated that iframes may cause problems for them: IFrames are sometimes used to display content on web pages.

What new iframe html5 attributes can help prevent a website being taken over from an iframe?

It's called the sandbox attribute. Just adding the sandbox attribute is enough to severely lock down an iframe. With this attribute set, the document inside the iframe cannot do any of the following: Run any JavaScript, even if it would only affect contents of the iframe.


2 Answers

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.

like image 68
Esailija Avatar answered Oct 09 '22 04:10

Esailija


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.

like image 44
Halcyon Avatar answered Oct 09 '22 05:10

Halcyon