LavaMoat / snow

Use Snow to finally secure your web app's same origin realms!
https://lavamoat.github.io/snow/demo/
MIT License
102 stars 9 forks source link

Forbid srcdoc frames with inner CSP meta tag #104

Closed weizman closed 1 year ago

weizman commented 1 year ago

should address #94, #90 and probably some other future crap too.

CSP can prevent Snow from running in new documents, which specifically srcdoc iframes can leverage.

This PR removes the ability to create srcdoc frames with meta CSP tags by assuming that this technique has no real world usage other than malicious.

mmndaniel commented 1 year ago

Ah, I hope it's not too dangerous (i.e. significantly increases protected app breakage risk). Anyways, it needs to more work to be secure, because findMetaCSP relays on prototype chain, so: Object.defineProperty(Element.prototype, 'attributes', { value: [] }); or Object.defineProperty(Attr.prototype, 'value', { value: '' }); Makes the bypass work again.

weizman commented 1 year ago

Not really because the prototype chain is coming from the realm i used for creating natives in the beginning of execution which is the realm of an iframe that was immediately removed from dom forever, so polluting it is between extremely difficult and probably impossible. You may try to produce a poc if you believe I'm wrong.

weizman commented 1 year ago

And yes, before merging i will make sure major websites don't suffer from this, but I highly doubt it. Do you see any other issues with this approach?

mmndaniel commented 1 year ago

Check these out:

Object.defineProperty(Element.prototype, 'attributes', { value: [] });
var d = document.createElement('div');
                testdiv.appendChild(d);
                d.innerHTML = `
    <iframe
        srcdoc="
        <meta http-equiv='Content-SecuriTy-Policy' content=&quot;script-src 'nonce-pwnd' ;&quot;>
            <iframe src=&quot;javascript:haha&quot;>
            </iframe>
        <script nonce=&quot;pwnd&quot;>frames[0].alert(1);</script>">
    </iframe>`
Object.defineProperty(Attr.prototype, 'value', { value: '' });
var d = document.createElement('div');
                testdiv.appendChild(d);
                d.innerHTML = `
    <iframe
        srcdoc="
        <meta http-equiv='Content-SecuriTy-Policy' content=&quot;script-src 'nonce-pwnd' ;&quot;>
            <iframe src=&quot;javascript:haha&quot;>
            </iframe>
        <script nonce=&quot;pwnd&quot;>frames[0].alert(1);</script>">
    </iframe>`
weizman commented 1 year ago

You're so right, this is one detail I missed with safe natives handling, I used a native createElement function but called it on the main vulnerable document, meaning nodes created that way were in fact vulnerable to prototype pollution. fixed f0aed38

weizman commented 1 year ago

Checked against major websites, seems to work perfectly fine, merging