最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Detect if JavaScript is Executing In a Sandboxed Iframe? - Stack Overflow

programmeradmin2浏览0评论

I have a product that's playing a video in Flash (if available), and falls back to HTML5 if Flash isn't available.

I'm not able to find a way to determine if JavaScript is executing within an Iframe with the "sandbox" attribute, which is necessary for my solution because sandboxed iframes disable all plugins. The sandboxed iframe could be as simple as this:

<iframe src="/" sandbox="allow-scripts">

To determine if Flash is enabled, I'm using swfobject's method of checking navigator.plugins["Shockwave Flash"].description, which is set even when in a sandboxed iframe. I can load the swf object, but it doesn't play.

To reproduce this issue, visit /, open your chrome inspector and click "Run". The script on the cross-domain site will pause in the context of the sandboxed iframe.

According to the W3 spec at .html#sandboxing-flag-set, there is supposed to be an "active sandboxing flag set" on the document that JavaScript can access (at least that's how I'm reading the spec). There doesn't seem to be any flag set on the iframe's document.

Does anyone have any ideas / solutions on how to detect if JavaScript is executing from within a sandboxed iframe?

I have a product that's playing a video in Flash (if available), and falls back to HTML5 if Flash isn't available.

I'm not able to find a way to determine if JavaScript is executing within an Iframe with the "sandbox" attribute, which is necessary for my solution because sandboxed iframes disable all plugins. The sandboxed iframe could be as simple as this:

<iframe src="http://www.cross-domain./" sandbox="allow-scripts">

To determine if Flash is enabled, I'm using swfobject's method of checking navigator.plugins["Shockwave Flash"].description, which is set even when in a sandboxed iframe. I can load the swf object, but it doesn't play.

To reproduce this issue, visit http://jsfiddle/max_winderbaum/9cqkjo45/, open your chrome inspector and click "Run". The script on the cross-domain site will pause in the context of the sandboxed iframe.

According to the W3 spec at http://dev.w3/html5/spec-preview/browsers.html#sandboxing-flag-set, there is supposed to be an "active sandboxing flag set" on the document that JavaScript can access (at least that's how I'm reading the spec). There doesn't seem to be any flag set on the iframe's document.

Does anyone have any ideas / solutions on how to detect if JavaScript is executing from within a sandboxed iframe?

Share Improve this question asked Apr 3, 2015 at 15:26 OmninternetOmninternet 1551 silver badge6 bronze badges 7
  • But surely that's the point of the HTML5 fallback? – user3310334 Commented Apr 3, 2015 at 15:37
  • 1 @minseong If you keep reading, the issue is that I have no idea of when I need to fall back to HTML5. Everything I can get from the browser tells me Flash is enabled, so I load Flash. If I need to load my HTML5 solution, I need to know if Flash is disabled in JavaScript. If you tell me how I can tell if Flash is disabled, it will resolve my issue. – Omninternet Commented Apr 3, 2015 at 15:54
  • What about document.plugins? That might tell you something different than navigator.plugins. The latter is the installed plugins, the former is (supposedly) the plugins in the document, which may differ due to being sandboxed. I haven't checked though. – Heretic Monkey Commented Apr 3, 2015 at 16:34
  • In both a sandboxed iframe and outside of an iframe altogether, document.plugins returns an empty array in Chrome and Firefox. Good idea, though! – Omninternet Commented Apr 3, 2015 at 16:42
  • Duplicate with stackoverflow./questions/34043278/… (although neither has an upvoted answer). – Tim B Commented Dec 3, 2015 at 17:56
 |  Show 2 more ments

2 Answers 2

Reset to default 6 +50

I will consider different kinds of iframes (choose the first case which applies):

  • Iframes with the sandboxed scripts browsing context flag

    That is, iframes with a sandbox attribute which doesn't contain the allow-scripts keyword.

    This flag blocks script execution. In particular, you can't use a script to check if the iframe is sandboxed.

  • Same-origin iframes without the sandboxed origin browsing context flag

    That is, same-origin iframes with no sandbox attribute, or same-origin iframes with a sandbox attribute which contains the allow-same-origin and allow-scripts keywords.

    In this case, you can use the frameElement global property to access the frame element (returns null when not used inside an iframe).

    Once you have a reference to the iframe, you can use hasAttribute or getAttribute to check its sandboxed attribute. There is also the sandboxed property, which should return a DOMSettableTokenList (old browsers might return a string according to an old spec).

  • Cross-origin iframes without the sandboxed origin browsing context flag

    That is, cross-origin iframes with no sandbox attribute, or cross-origin iframes with a sandbox attribute which contains the allow-same-origin and allow-scripts keywords.

    In this case, the use of frameElement is blocked:

    • According to W3C, it should throw a SecurityError exception. This is implemented by Chrome.
    • According to WHATWG, it should return null. This is implemented by Firefox.

    Then, I don't think you can distinguish whether the iframe is sandboxed or not in this case. However, since using allow-same-origin in a cross-origin iframe isn't much useful, consider assuming the iframe isn't sandboxed.

  • Iframes with the sandboxed origin browsing context flag

    That is, iframes with a sandbox attribute which doesn't contain the allow-same-origin keyword but contains the allow-scripts keyword.

    As in the previous case, the use of frameElement is blocked.

    However, you can detect this case because document.domain will be the empty string.

Note: Firefox treats data URIs as same-origin, so it's OK. However, Chrome treats them as cross-origin. Then frameElement doesn't work and document.domain is the empty string regardless of whether the iframe is sandboxed or not. You can check whether location.protocol is 'data:' string to detect data URIs.

In general, you might try something like

function isSandboxedIframe() {
  if (window.parent === window) return 'no-iframe';
  try { var f = window.frameElement; } catch(err) { f = null; }
  if(f === null) {
    if(document.domain !== '') return 'unkown'; // Probably 'non-sandboxed'
    if(location.protocol !== 'data:') return 'sandboxed';
    return 'unkown'; // Can be 'sandboxed' on Firefox
  }
  return f.hasAttribute('sandbox') ? 'sandboxed' : 'non-sandboxed';
}

A project sandblaster can help you detect if you running being sandboxed.

Sandbox check if itself is framed first and then scans through the attributes of the frame element to detect several information about itself. These includes framed, crossOrigin, sandboxed, sandboxAllowances, unsandboxable, resandboxable, sandboxable.

To detect if itself is sandboxed in our case, it checks if the frame element has an attribute sandbox.

// On below `frameEl` is the detected frame element
try {
  result.sandboxed = frameEl.hasAttribute("sandbox");
}
catch (sandboxErr) {
  result.sandboxed = null;
  if (typeof errback === "function") {
    errback(sandboxErr);
  }
}

I tried to replicate your issue and to test if this solution works, I had to paste the script into the window itself due to the security issue.

<html>
    <head>
    </head>
    <body>

    <script>
        //Paste the contents of the script(https://raw.githubusercontent./JamesMGreene/sandblaster/master/dist/sandblaster.js) here

        var result = sandblaster.detect();
        if(result.sandboxed === true) {
            //sandboxed
        }
        debugger;
    </script>
    </body>
</html>

Here is a demo: http://jsfiddle/Starx/tzmn4088/ that shows this working.

发布评论

评论列表(0)

  1. 暂无评论