10

I have a parent page that has a Content Security Policy on it. The main purpose of CSP is not to prevent XSS, but to prevent network access. This page has to run some user generated/submitted HTML/CSS/JS. I am running this user content in an iframe by using document.write to write the user content into this iframe.

NOTE: The user content that I have is not uploaded or present on a server but is available dynamically - say using some form.

I also want the user content to inherit the CSP of the parent page and any iframes created by the child iframe as well.

The policy applied on iframes according to the spec:

The policy of the embedding resource controls what may be embedded. The embedded resource, however, is controlled by the policy delivered with the resource, or the policy of the embedding resource if the embedded resource is a globally unique identifier (or a srcdoc frame).

So, the standard says that the policy will not be inherited, because the parent page is not a globally unique identifier. I don't want to use srcdoc iframe because of the following reasons

  1. The html can be very large
  2. The html needs to be escaped to use srcdoc which seems unreliable and unclean.
  3. Browser Support (Edge - under consideration)

But there is a twist:

When I went on to test this inheritance thing on browsers, the csp was actually being inherited on Chrome, Safari, Firefox but not Edge. This to me seems quite logical and correct.

Here is the sample test I performed:

<html>
<head>
    <!-- CSP just for demo purposes - not the actual csp -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'"/> 
</head>
<body>
    <h1>Parent Content</h1>
    <p style="font-weight: bold; font-family: arial, sans-serif;">
        The image here will be blocked due to CSP (default-src directive). 
        However the iframe's image will not be blocked on Edge since the CSP is not inherited.
    </p>
    <img src="http://www.w3schools.com/html/pic_mountain.jpg"/>
    <script>
        window.addEventListener("DOMContentLoaded", function() {
            // creating the child iframe

            // Some user controlled HTML content.
            var html = "<html><body><h1>Child Content</h1><img src='http://www.w3schools.com/html/pic_mountain.jpg'/></body></html>"; 

            var iframe = document.createElement("iframe");
            iframe.setAttribute("height", "400px");
            iframe.setAttribute("width", "400px");
            document.body.appendChild(iframe); //need to append first to be able to write into the iframe.

            var iframeDoc = iframe.contentWindow.document;
            iframeDoc.open();
            iframeDoc.write(html);
            iframeDoc.close();
        });
    </script>
</body>
</html>

So, finally my questions are:

  1. Can I depend on this inheritance of CSP to child iframe on Chrome, Firefox, and Safari? - I can't find this documented anywhere.
  2. Is there a clean and reliable way to be able to use srcdoc with escaping and everything? What are the performance impacts of using srcdoc?
  3. Is there any other method to do this?

More thought:

The spec's (and Edge) handling of CSP applying to the iframe further adds to the risk of allowing 'unsafe-inline' for scripts to prevent XSS. Because then the attacker can even use document.write like this to trigger creation of iframe to his own malicious site even. Even child-src/frame-src 'none', doesn't stop creation of iframe using document.write. Isn't this very bad for security?

  • Did you consider a data URI? – Arminius Nov 11 '16 at 10:57
  • @Arminius: Yeah, but data uri has other restrictions like XHR is not allowed at all. On Edge, data uris have some data:// URLs which makes it cross origin with the parent, which I don't want. In fact, data uris are unique opaque origins (except on firefox) so this doesn't work for me. – tapananand Nov 11 '16 at 11:00
  • Sorry, my suggestion of course made no sense for your cross origin requirements. – Arminius Nov 11 '16 at 11:06
  • @Arminius: My main concern is the inheritance of CSP to child iframes. – tapananand Nov 11 '16 at 11:08
  • Curious. If I'm able to set a XSS persistant on page B, which doesn't work because of the CSP, does it mean that if I embed page B in A and A doesn't have a CSP protecting against XSS, the XSS will trigger on Edge ? – Xavier59 Nov 13 '16 at 22:54
1

For 3, it seems there might be, and one that should allow you to set a tighter CSP on your other pages/content.

According to https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/, you can provide specific rights to your iframe (or remove them).

It seems that iframe sandbox is supporter by all your targetted browsers: http://caniuse.com/#feat=iframe-sandbox

So I might create the iframe with the appropriate sandboxing, rather than rely purely on the parent page's CSP policy.

The one unknown (to me) is what happens if/when someone manages to modify the iframe's sandbox

  • Sandboxed iframes can't do what CSP can – tapananand Mar 7 '17 at 15:34
-2

3: You over-complicate the problem, CSP is simply a 'header', just like a Cookie or a mime-type; if you serve the iframe, then you can set the CSP header as a statement in the code before you create the html.

  • 1
    Please read the question carefully – tapananand Feb 19 '17 at 6:26
  • Follow the spec and rethink. – bbaassssiiee Feb 19 '17 at 6:30
  • 1
    The question is about inheriting of csp to iframes created using document.write and not served from any server – tapananand Feb 19 '17 at 6:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.