w3c / webappsec-csp

WebAppSec Content Security Policy
https://w3c.github.io/webappsec-csp/
Other
208 stars 78 forks source link

Add a new directive governing the use of http-equiv in <meta> tags #112

Open aidantwoods opened 8 years ago

aidantwoods commented 8 years ago

Some <meta> tags are informational (let's call these passive) <meta name="description" content="..."> And some affect the page in some way (let's call these active) <meta http-equiv="Set-Cookie" content="SESSID=1">

In CSP there is no way to revoke the power of these active ones.

<meta http-equiv="... is a tag on the page that may emulate a subset of functions normally reserved for page headers. Equally, some of these functions appear in JavaScript (which is obviously already heavily governed by CSP). Dangerous functions that can be performed by <meta http-equiv="... include

Of course you can also set the content-type, or cache-control etc... but as far as I'm aware the user-agent conventionally prefers to honour the value in a header if that's specified (though if they can easily be covered in the same directive, these could be addressed in CSP too).

So focusing on functions that cannot currently be disabled, consider the example With a CSP Content-Security-Policy: default-src 'self';

While the above policy would prevent <script>document.cookie='SESSID=1'</script> from executing, if injected by an adversary; CSP is currently unable to prevent <meta http-equiv="Set-Cookie" content="SESSID=1"> from executing – which performs the same function (even on noscript browsers). Allowing this type of <meta> tag allows any XSS injection vector to be coupled with Session Fixation even if a good CSP is specified.

Refresh, of course doesn't open up scripting in the page context. What it does do however, is load a new page context – meaning CSP specified now won't matter. An entire page can be specified within a 'data:' URL, e.g. containing a form that could post to "http://phisher.example.com/collect.php" – even if the page that had triggered the redirect had a CSP restricting form POSTs to go to 'self'.

I mention both of these, because they can both be addressed by the same directive: http-equiv e.g. Content-Security-Policy: default-src 'self';, or Content-Security-Policy: http-equiv 'self'; would disallow http-equiv in <meta>, 'self' would infer the equivalent headers should be used. 'none' keyword would have equivalent meaning here.

Hashes could be used to selectively enable based on the content="...". Similarly nonces could be specified inline.

Optionally, the values for http-equiv could be selectively specified to enable them Content-Security-Policy: http-equiv 'set-cookie' 'refresh';, or Content-Security-Policy: http-equiv set-cookie refresh;

Content-Security-Policy: http-equiv 'unsafe-inline'; could be used restore default unsafe behaviour.

Obviously there are a few ways this could be implemented, the above is a suggestion. The main aim here is that site owners have a mechanism whereby they may disable active <meta> tags if they don't want to use them.

mikewest commented 8 years ago

I think the goal here is reasonable. The proposal, however, seems overly complicated. I wonder how much granularity is actually necessary.

That is, I wonder if we should simply consider both Set-Cookie and Refresh via <meta> as script, and gate it on script-src 'unsafe-inline' (or, I suppose, hashes, though I think we'd probably be able to avoid doing that if it didn't turn out to be a gating factor).

I'll add some metrics to Blink to see how much impact that change might have. Perhaps @dveditz would be interested in doing the same for Firefox?

mikewest commented 8 years ago

https://codereview.chromium.org/2308513002 adds metrics.

aidantwoods commented 8 years ago

I'd be happy with it getting rolled intoscript-src: 'unsafe-inline', though I'm not a heavy user of <meta http-equv="..., so it may be valuable to get some metrics on the impact of that change.

My reasoning for the seperate directive would be to allow people who need those meta tags to quite specifically define what they want to allow in terms of usage (I.e. don't want people feeling like they need to declare 'unsafe-inline' just to facilitate the usage of (dynamic) meta functions). A nonce could solve that in theory, though I'd expect if you are using these meta tags then you probably are doing so because you don't have access to set headers dynamically. That said, if no one is using these things then there probably isn't much need for the granularity.

Gelembjuk commented 6 years ago

Hello, I have a question related to this case.

In my web app i allow users to download html files they uploaded. I want to make this download to be maximum secure.

If users just open a html in new tab, it is insecure, there can be some script to catch cookies or so.

I added the header "Content-Security-Policy: sandbox" for such downloads. And it solves the problem.

But i got the problem with some subgroup of html files, which are "bookmarks". Files contain simple html like

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Opening http://example.com</title>
<meta http-equiv="REFRESH" content="0;url=http://example.com">
</HEAD>
<BODY style="font-family:Tahoma;Arial;font-size:12px;padding:20px;color:#aaa">
Opening <b>http://example.com</b>...
</BODY>
</HTML>

After it is opened in new tab, i need a user to be redirected to the host in the file. It works without the header "Content-Security-Policy: sandbox" , but doen't work with it.

I tried different sandbox modes Content-Security-Policy: sandbox allow-scripts Content-Security-Policy: sandbox allow-top-navigation

But nothing allows to execute that redirect.

is there a way to do it?