同时沙盒并将JS / HTML添加到iFrame

时间:2015-06-17 19:36:19

标签: javascript html security iframe sandbox

我正在尝试创建一个内部有JS fire但不能访问父文档的iframe。目标是实现一个简单的实现,而不是包含任何特殊的库。我发现HTML5 Sandbox attribute是一个可行的解决方案;然而,证明很难同时沙盒化iframe 将JS放入其中。

我试过了:

  1. 将JS添加到iframe,然后从父文档沙箱化它。 这不起作用,因为iframe中的JS会在应用iframe沙箱之前触发
  2. 创建iframe并使用srcdoc属性设置HTML(例如<iframe sandbox="allow-scripts" srcdoc="<body><script src='sample1.js'></script><script src='sample2.js'></script></body>"></iframe>根据here
  3. ,这在IE中不起作用
  4. 创建iframe并使用src属性设置HTML(例如<iframe sandbox="allow-scripts" src="javascript:&quot;<html><body><script src='sample1.js'></script><script src='sample2.js'></script></body></html>&quot;"></iframe这在Firefox 38.0.5(Mac OS X Yosemite)中不起作用,但适用于Chrome 43&amp; Safari 8.0.4 ...&#34;无法在Firefox&#34;意味着它确实允许sample2.js将<span></span>添加到iframe DOM,但它不会设置span的innerText;因此,它不能按预期工作。
  5. 最后,我刚尝试通过JS动态创建iframe。在将iframe添加到DOM(没有sandbox属性)之后,我将HTML写入其中,其中包含我想在iframe中沙箱化的脚本。在iframe头中,我有一个沙箱自己的脚本。 不幸的是,这似乎不起作用。(下面的代码)
  6. 我创建了一个JSFiddle,但它没有提供正确的行为,因为它位于嵌套的iframe中......我设置了一个简单的页面并在我的localhost上进行测试。这是我用于测试的代码:

    <html>
    <head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    </head>
    <body>
    
    <!-- Case #2 ~ Does not work in IE -->
    <iframe srcdoc="<body><script src='sample1.js'></script><script src='sample2.js'></script></body>" sandbox="allow-scripts">
    </iframe>
    
    <!-- Case #3 ~ Does not work in Firefox -->
    <iframe src="javascript:&quot;<html><body><script src='sample1.js'></script><script src='sample2.js'></script></body></html>&quot;" sandbox="allow-scripts">
    </iframe>
    
    <!-- Case #4 ~ Sandbox maybe not applied? -->
    <script>
    var i   = document.createElement('iframe');
    i.src   = "about:blank";
    i.id    = "bryce_iframe";
    document.body.appendChild(i);
    // iframe added to page
    
    var j = document.getElementById('bryce_iframe').contentDocument;
    j.open();
    
    var js = "<html><head>" +
             "<scr"+"ipt>window.top.document.getElementById('bryce_iframe').sandbox = 'allow-scripts';</scr"+"ipt>" +
             "</head><body>" +
             "<p>Hi</p>" +
             "<scr"+"ipt>" +
             "var p = document.createElement('p');" + 
             "p.innerText = 'should throw error'; console.log(p);" +
             "window.top.document.body.appendChild(p);" +
             "</scr"+"ipt>" +
             "</body></html>";
    // "window.top.document.body.appendChild(p)" should throw an error because of sandbox
    
    j.write(js);
    
    j.close();
    </script>
    
    </body>
    </html>
    

    我的sample1.js文件如下所示:

    var s = document.createElement('span');
    s.innerText = "hi";
    window.top.document.body.appendChild(s);
    

    我的sample2.js文件如下所示:

    var txt = "this doesn't try to break out of iframe";
    var s = document.createElement('span');
    s.innerText = txt;
    document.onload=document.body.appendChild(s);
    

    我几周来一直在寻找有关这个问题的有用资源。如果有另一组眼睛和我一起看它会很棒。

    我期待与任何人伸出援手合作。提前谢谢。

3 个答案:

答案 0 :(得分:0)

只是想知道为什么要在示例#4的内部脚本中添加sandbox属性?:

"<scr"+"ipt>window.top.document.getElementById('bryce_iframe').sandbox = 'allow-scripts';</scr"+"ipt>" +

沙箱属性应添加到父代码中:

<!-- Case #4 ~ Sandbox maybe not applied? -->
<script>
var i   = document.createElement('iframe');
i.src   = "about:blank";
i.id    = "bryce_iframe";
i['sandbox'] = 'allow-scripts';
document.body.appendChild(i);

这将阻止父访问。

答案 1 :(得分:0)

我遇到了同样的问题。我也没有一个好的解决方案,但还有2个不能在Edge上工作的选项:

选项1:Blob网址

var blob = new Blob([html_string], {type: 'text/html'});
var url = URL.createObjectURL(blob);
var i   = document.createElement('iframe');
i.src = url;
i.sandbox = "allow-scripts";

选项2:数据网址

var url = "data:text/html,<html_string>";
var i = document.createElement('iframe');
i.src = url;
i.sandbox = "allow-scripts";

答案 2 :(得分:0)

如果您查看HTML specification of the sandbox attribute,它会警告:

  

这些标志仅在导航iframe元素的嵌套浏览上下文时生效。

这意味着在加载iframe后,动态添加/删除/更新iframe的沙箱属性不会产生任何效果。

执行此操作的正确方法是在加载第三方JS的单独域中托管另一个HTML文件 。您可以在iframe的src属性中引用该HTML文件,并且可以静态包含sandbox属性,而不是尝试在JavaScript中动态添加它。确保包括allow-scripts作为sandbox属性的值,以便子页面能够加载JS。

您应将另一个HTML文件托管在单独的域中的原因是因为不支持sandbox属性的浏览器。 here

中记录了浏览器支持