3

I am creating iframes dynamically and I want to prevent scripts that don't originate from the iframes' origin. Is this even possible (via JavaScript/jQuery)? For example, if my page loads an iframe from example.com with the contents:

<script src="http://example.com/foo.js"></script>
<script src="http://something-else.com/bar.js"></script>

I want the example.com script to run, but I want the something-else.com script to be blocked and not run.

I am using NW.js (formerly Node-Webkit), so I have full read-write access to the iframes' contents as if they were same-origin.

I've tried using plugins (like those that bring CORS in the picture, with whitelisting), but nothing I've tried is working.

An ideal solution would also allow me to whitelist specific other origins in addition to the iframe's origin.

EDIT:

Here is my browser project I am trying to implement this in: https://github.com/IdeasNeverCease/Aries

Here is the section of code the iframe loading is done in: https://github.com/IdeasNeverCease/Aries/blob/master/app.nw/resources/scripts/aries.js#L376-L687

apsillers
  • 112,806
  • 17
  • 235
  • 239
NetOperator Wibby
  • 1,354
  • 5
  • 22
  • 44
  • Is the iframe in your domain? You would need to remove it on the server level. – epascarello Feb 03 '15 at 13:33
  • @epascarello I'm using node-webkit (now NW.js). Because of this, I am able to load iframes as if they were on my domain. My browser project is here: https://github.com/IdeasNeverCease/Aries – NetOperator Wibby Feb 03 '15 at 13:39
  • I dont think that's possible, what do you mean by "as if they were on my domain" – Melbourne2991 Feb 03 '15 at 14:25
  • @Melbourne2991 I said that because I didn't mention my browser project. I'm aware that if I had an iframe on my website that pointed to another page on my site, I could modify the contents of the iframe. – NetOperator Wibby Feb 03 '15 at 17:24
  • `content-security-policy`... set the http header `X-Frame-Options` with value `sameorigin`. – sarveshseri Feb 05 '15 at 19:14
  • @SarveshKumarSingh You can't set `X-Frame-Options` on iframes: http://stackoverflow.com/a/27359031/1167646 – NetOperator Wibby Feb 05 '15 at 19:17
  • You don't set that on some iframe... You send it with your HTTP-response to the browser. Now Browser will ensure that no-iFrame on your page can load content from some other source. – sarveshseri Feb 05 '15 at 19:22
  • Sounds like you want the page in each iframe to have a `Content-Security-Policy` set to `script-src 'self';` (in order to prevent scripts from other origins from being loaded on the page). I'm not sure the best way to do this in node-webkit, but if you can inject a `` tag, you could do `` (For possibly more information, see this resolved bug report: https://github.com/nwjs/nw.js/issues/1672) – apsillers Feb 05 '15 at 19:38
  • @apsillers I've been injecting custom code into iframes and I never thought about injecting a `` tag. Good grief. I'll test this when I get home later tonight. – NetOperator Wibby Feb 05 '15 at 21:17
  • @apsillers Can you post your answer so I can accept it? – NetOperator Wibby Feb 05 '15 at 23:52
  • Could you clarify what you mean by "scripts that don't originate from the iframes' source"? Do you mean you only want to load scripts from the same origin (e.g., an iframe from `example.com` can only load scripts from `example.com`) or d oyou want to disallow all script resources and only allow inline scripts (i.e., `` is okay but ` – apsillers Feb 06 '15 at 13:41
  • @apsillers I meant the first case. I also want to whitelist sources from Twitter, Facebook, &c, to allow for usage of social share buttons. I am currently figuring that out now. – NetOperator Wibby Feb 06 '15 at 14:50
  • @NetOperatorWibby I edited these comment details back into the question; feel free to alter my edits however you see fit. By the way, you're in luck: CSP can also whitelist specific origins in addition to the current `self` origin. – apsillers Feb 06 '15 at 14:57

1 Answers1

9

I want to prevent scripts that don't originate from the iframes' source

This is exactly what a Content Security Policy (CSP) is for. A CSP can specify which origins are permitted for scripts, plugins, styles, media, etc. You need to cause each the iframe to have a CSP that prevents script loads outside of the current origin; this can be done with the simple policy script-src 'self' 'unsafe-inline'; (the unsafe-inline allows the iframe to have inline scripts and the self restricts loads to the same-origin resources only)

Traditionally, you need the server to send the Content-Security-Policy response header when serving the page. However, if you don't have control over the server-sent response headers (but do have control over the page content) you can imitate an HTTP response header with a <meta> tag like so:

<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';">

You can inject this programmatically (but read on for issues):

var m = document.createElement("meta");
m.httpEquiv = "content-security-policy";
m.content = "script-src 'self' 'unsafe-inline';";
iframeElem.contentDocument.documentElement.appendChild(m);

However, this script-based injection might not work for you, because you'll only have a DOM to work with after the DOM is parsed from the HTML source. At that time, and the scripts from any (non-async) <script> elements will already have been fetched and run. You may need to manipulate the HTML directly, but I don't know enough about NW.js to tell you the best way to do that.

If you want to disallow all external script resources (even ones from the same origin), you can use script-src 'none' 'unsafe-inline';. To disallow all scripts, including loaded scripts and inline scripts, use script-src 'none';

In order to whitelist specific origins, simply add them as unquoted items in the CSP:

Content-Security-Policy: script-src 'self' *.twitter.com https://api.facebook.com

A leading *. allows all subdomains, and a leading https:// limits the whitelist for that domain to secure https:// addresses only.

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • Is there any similar mechanism that functions as a blacklist, rather than a whitelist? Use case is a stopping a bad actor on a well-known ad network from injecting code that calls a known URL. Whitelisting is infeasible because of the broad and changing set of valid URLs, vs. this one, known, bad URL. – user359996 Jul 19 '16 at 19:45
  • 1
    @user359996 My guess is no: in general, what's to stop a bad actor from just rotating domains? Such a security measure seems to have limited usefulness. In your case, maybe there's customer-facing reasons why the bad ad company can't rotate domains, but a restriction like that for an attacker sounds like the exception rather than the rule. – apsillers Jul 19 '16 at 19:51
  • For our purposes, blocking individual domains would actually be perfectly sufficient. They're not really a bad actor so much as just a very loosely coupled third-party doing something which, while not a security issue, nor even strictly illegitimate, is counter to the interests of our clients. If we did this, it is very unlikely they would notice or react, given the particulars of our own position in the market. – user359996 Aug 08 '16 at 23:02