Changing how SSL state interacts with the HTTP cache

75 views
Skip to first unread message

David Benjamin

unread,
Jun 8, 2015, 3:03:55 PM6/8/15
to security-dev, net-dev
Hi folks,

This email is an FYI about a change we're planning to make on how the HTTP cache and SSL interact, and a request for comments on any terrible implications that we may have missed.

The HTTP cache stores SSL state, including the certificate and cipher suite, alongside each resource. This is partly so we have data to report when using a cached resource, such as the information displayed if the user clicks the lock icon.

If an entry has expired, we send a revalidation request to the server. On 304 Not Modified, the cached entry is used with some updates from the new headers. Today, the SSL state is NOT updated. The net stack returns the SSL state from when the resource was first fetched.

This has some unfortunate consequences. Consider a resource originally fetched with a SHA-1 certificate. If the resource is unchanged and the server reports 304 Not Modified, we will report the cached SSL state, long after the server deploys a new certificate. This persists across refresh (as that merely forces a revalidation) and until the cache entry expires or the user hits *shift* refresh (which ignores the cache entry). This also applies to changes in cipher suites. This isn't ideal.

We plan on changing this to report the SSL state from the revalidation request and update the cached entry. (The response on disk is already updated with new headers.) Note that this has no bearing on how certificates are verified. By the time the cache sees a certificate, all that is complete. This is purely UI.

Borrowing from the extensions team: Imagine you're Dr. Evil Network Attacker, list the worst evil deeds you could commit with your change:

- An attacker with a misissued certificate could enter something bad in the cache with legitimate ETag. Later the certificate is revoked and browser connects to the legitimate site. If the ETag is still fresh, the cache entry will be reused. In the UI, the cached response will appear with the new certificate rather than the old.

This has never been a security boundary. Before and after the change, any script in that resource already has run under the origin. Moreover, the UI only reports the certificate of the main frame while subresources are also critical to an origin's security. Chrome does not expect users to manually inspect certificates, especially not after content has already run. Finally, today, the converse is possible: a legitimate but stale resource under one certificate could be reported as fresh under a misissued certificate without UI feedback.

David

Chris Palmer

unread,
Jun 8, 2015, 3:26:40 PM6/8/15
to David Benjamin, security-dev, net-dev
SGTM. That exploit scenario is definitely interesting, though; can we
make sure it gets documented somewhere (if it hasn't already been)?
> To unsubscribe from this group and stop receiving emails from it, send an
> email to security-dev...@chromium.org.

Ryan Sleevi

unread,
Jun 8, 2015, 3:48:09 PM6/8/15
to Chris Palmer, David Benjamin, security-dev, net-dev
On Mon, Jun 8, 2015 at 12:26 PM, 'Chris Palmer' via net-dev <net...@chromium.org> wrote:
SGTM. That exploit scenario is definitely interesting, though; can we
make sure it gets documented somewhere (if it hasn't already been)?

Where do you see it being documented?

Either way, this results in someone non-intuitive behaviours, which is why I wanted to make sure we circulated this widely and saw if we missed on any other UX concerns.

Chris Palmer

unread,
Jun 8, 2015, 3:52:48 PM6/8/15
to Ryan Sleevi, David Benjamin, security-dev, net-dev
On Mon, Jun 8, 2015 at 12:48 PM, Ryan Sleevi <rsl...@chromium.org> wrote:

>> SGTM. That exploit scenario is definitely interesting, though; can we
>> make sure it gets documented somewhere (if it hasn't already been)?
>
> Where do you see it being documented?

Anywhere where we can point confused developers, e.g. the Chrome
Security FAQ, comments in code, a blog post, ... whatever is easiest
for you all.

Lucas Garron

unread,
Jun 8, 2015, 3:54:58 PM6/8/15
to Chris Palmer, Ryan Sleevi, David Benjamin, security-dev, net-dev
I second putting it at https://www.chromium.org/Home/chromium-security/education/tls
There's already a "common pitfalls" section.

»Lucas
--
»Lucas

David Benjamin

unread,
Jun 8, 2015, 4:16:16 PM6/8/15
to Lucas Garron, Chris Palmer, Ryan Sleevi, security-dev, net-dev
It's really not a pitfall for the server operator or something that a server operator would even care about I think. Quite the opposite: I'm removing a pitfall for the server operator. Before, there would be weird cases where we'd show stale SSL information, making the SHA-1 deprecation much less reliable and harder to debug. (Also just changing your SSL configuration in general.)

I think perhaps the concrete thing we might want to spell out is that we (as with every other browser that I know of) trust what's in the HTTP cache. And that means that, yes, a temporarily misissued certificate can poison your cache and make you sad for longer than the window the certificate was valid for.

Sigbjørn Vik

unread,
Jun 19, 2015, 5:22:11 AM6/19/15
to David Benjamin, security-dev, net-dev
Hi,

Glad to see that you are planning to handle this scenario.

We have the following scenario:
User loads resource, is presented with certificate A.
User later gets a 304 from the server, is presented with certificate B.

Assume that either certificate A or B is bad, but not both. The overall
security of the resource shown to the user is no higher than the weakest
of the two certificates. In this case, presenting the user with just one
certificate cannot catch all cases. If presenting certificata A, while
certificate B is bad, the user might be tricked, and vice versa.

Assume the bad certificate (controlled by an attacker) is already
accepted by the user - e.g. as a requirement to log in to wifi, social
engineering, to see an unrelated cute cat picture, etc. Or alternatively
that the bad certificate was presented to a user as a 0-day-exploit, the
browser has since been upgraded, but cache remains. Also assume that the
browser displays only the good certificate.
Current behavior: If A is good and B is bad, an attacker can serve 304s
for any server resources. This can block server updates (including
security fixes to files) or cause the web site to malfunction (DoS).
Proposed behavior: If A is bad and B is good, an attacker can serve his
own resources for any resource the server responds to with 304. Replace
another domain's jQuery files with your cached version, and gain access
to all data used there. E.g. inject a JS file for banks (when the user
is not logged in), and automatically get information if the user does
log in some time in the future. The user might never be aware of the JS
file being cached (inline on a cat site), and when checking the
certificate before logging in to the bank, all looks well.
In both the attack scenarios, the user would be presented with a green
padlock and full security. While both cases are bad, the second is
significantly worse.

One potential fix is to do an unconditional reload of the resource in
step 2 when encountering this scenario (invalidating all cached
resources using a bad cert for an origin when a good cert for that
origin is encountered). This will ensure that the overall security of
the resource is well-known and easily presentable to the user.

Another potential fix is to display the security as the weakest of the
cached and the current connection. For inline images, the UI (padlock)
already displays according to the weakest part of the main connection
and the inlines.

Another potential fix is to apply cache separation between secure and
insecure contexts. If only one of A and B is bad, then they will enter
separate caches (just like http and https do today), and not interfere,
and there would either be only good certificates or bad certificates for
the resource. Cache separation has a number of other benefits too, but
is unfortunately somewhat of an effort to undertake.

Also see
https://code.google.com/p/chromium/issues/detail?id=366609
> To unsubscribe from this group and stop receiving emails from it, send
> an email to security-dev...@chromium.org
> <mailto:security-dev...@chromium.org>.


--
Sigbjørn Vik
Opera Software

Ryan Sleevi

unread,
Jun 19, 2015, 5:43:19 AM6/19/15
to Sigbjørn Vik, David Benjamin, security-dev, net-dev
On Fri, Jun 19, 2015 at 2:22 AM, Sigbjørn Vik <sigb...@opera.com> wrote:
Hi,

Glad to see that you are planning to handle this scenario.

We have the following scenario:
User loads resource, is presented with certificate A.
User later gets a 304 from the server, is presented with certificate B.

Assume that either certificate A or B is bad, but not both. The overall
security of the resource shown to the user is no higher than the weakest
of the two certificates. In this case, presenting the user with just one
certificate cannot catch all cases. If presenting certificata A, while
certificate B is bad, the user might be tricked, and vice versa.

It's not possible for A to have been bad at the time it entered the cache, because we only cache resources that were loaded over good connections.

That is, if there's a cert error, we will not enter it to the cache.

So the only scenario would be when we've loaded A, cached it, and then later, during revalidation, get B. Depending on the semantics of the cached item, we will either load the original cached item (unable to validate if it was stale), or, if it was unusable, the connection will fail (because B could not be loaded, and the 304 thus ignored)

Another potential fix is to apply cache separation between secure and
insecure contexts. If only one of A and B is bad, then they will enter
separate caches (just like http and https do today), and not interfere,
and there would either be only good certificates or bad certificates for
the resource. Cache separation has a number of other benefits too, but
is unfortunately somewhat of an effort to undertake.


This has always been done, except the separation is "in the cache" and "not in the cache".

So it doesn't sound like any issue requires addressing w/ this change.

Sigbjørn Vik

unread,
Jun 19, 2015, 8:12:43 AM6/19/15
to rsl...@chromium.org, David Benjamin, security-dev, net-dev
On 19-Jun-15 11:43, Ryan Sleevi wrote:
>
>
> On Fri, Jun 19, 2015 at 2:22 AM, Sigbjørn Vik <sigb...@opera.com
> <mailto:sigb...@opera.com>> wrote:
>
> We have the following scenario:
> User loads resource, is presented with certificate A.
> User later gets a 304 from the server, is presented with certificate B.
>
> It's not possible for A to have been bad at the time it entered the
> cache, because we only cache resources that were loaded over good
> connections.
>
> That is, if there's a cert error, we will not enter it to the cache.

Then there must be a bug somewhere. When testing, I can easily show that
resources with bad certificates are cached.

1 Clear all browsing data, exit Chrome.
2 Set Fiddler up as an untrusted HTTPS MitM
3 Start Chrome, load https://people.opera.com/sigbjorn/temp/New1.html
(click through the warning and load the page)
4 Reload https://people.opera.com/sigbjorn/temp/New1.html

Observe that in step 4, Fiddler will list one of the responses as 304.
Yet the browser shows the picture, hence it must be cached.

Not caching insecure https resources is similar to the suggestion of
invalidating such resources when encountering a secure connection to the
same domain.

> Another potential fix is to apply cache separation between secure and
> insecure contexts. If only one of A and B is bad, then they will enter
> separate caches (just like http and https do today), and not interfere,
> and there would either be only good certificates or bad certificates for
> the resource. Cache separation has a number of other benefits too, but
> is unfortunately somewhat of an effort to undertake.
>
>
> This has always been done, except the separation is "in the cache" and
> "not in the cache".

If that works, that is a great first step towards a proper separation
between contexts. A proper separation would also keep track of all other
offline storage, cookies as well as other types. Not supporting cookies
for insecure https would cause breakage, so they would have to be cached
somewhere, i.e. an insecure cache context.

Adam Rice

unread,
Jun 19, 2015, 8:38:10 AM6/19/15
to Sigbjørn Vik, Ryan Sleevi, David Benjamin, security-dev, net-dev
On 19 June 2015 at 21:12, Sigbjørn Vik <sigb...@opera.com> wrote:
1 Clear all browsing data, exit Chrome.
2 Set Fiddler up as an untrusted HTTPS MitM
3 Start Chrome, load https://people.opera.com/sigbjorn/temp/New1.html
(click through the warning and load the page)
4 Reload https://people.opera.com/sigbjorn/temp/New1.html

Observe that in step 4, Fiddler will list one of the responses as 304.
Yet the browser shows the picture, hence it must be cached.

I'm guessing it's in the Blink cache. Try doing step 4 in a new tab.

Ryan Sleevi

unread,
Jun 19, 2015, 10:06:32 AM6/19/15
to Sigbjørn Vik, David Benjamin, security-dev, net-dev


On Jun 19, 2015 5:12 AM, "Sigbjørn Vik" <sigb...@opera.com> wrote:
>
> Then there must be a bug somewhere. When testing, I can easily show that
> resources with bad certificates are cached.
>

> Observe that in step 4, Fiddler will list one of the responses as 304.
> Yet the browser shows the picture, hence it must be cached.

As Adam said, this is almost certainly the Blink in-memory cache rather than anything broken. We allow the in-memory cache of the renderer.

> If that works, that is a great first step towards a proper separation
> between contexts. A proper separation would also keep track of all other
> offline storage, cookies as well as other types. Not supporting cookies
> for insecure https would cause breakage, so they would have to be cached
> somewhere, i.e. an insecure cache context.

There is no plan at all to make these sorts of things hard security boundaries. Not fragmenting the cache/storage layers based onnl things like good/bad, DV vs OV vs EV, CA 1 vs CA 2, etc. Heck, the split between first party and third party, which is barely even a boundary, already causes real performance issues.

Sigbjørn Vik

unread,
Jun 19, 2015, 10:15:16 AM6/19/15
to Adam Rice, Ryan Sleevi, David Benjamin, security-dev, net-dev
tl:dr; ignore me ;)

On 19-Jun-15 14:38, Adam Rice wrote:
> On 19 June 2015 at 21:12, Sigbjørn Vik <sigb...@opera.com
The cached response seems to only be valid for same-tab, same-domain (or
some such), so might very well be a different cache, thanks for the hint.

Assuming the HTTP cache doesn't cache anything for invalid certificates,
there is certainly less potential for mixups. :) The suggested solution
seems sufficient, although not entirely perfect. Being dr Evil:

An attacker would have to somehow manage to serve data over a valid
connection for any attacks to work. With the suggested change, if he
does manage to serve such data, that data will be cached, and treated as
good even if the original certificate no longer is. Some examples:
* Steal a certificate, and have data served with it cached even after it
is revoked
* Inject a local root (SuperFish), and have data cached even after the
computer is cleaned
* Exploit a 0-day, and have data cached even after the browser is updated
* Deface a website, and have data cached even after the website is
cleaned up (but part of the cleanup ought to be to invalidate all cached
resources, rendering this point moot)
* The resource was fetched over a weak cipher suite and replaced by an
active MitM, and persists even after the MitM is gone

Another approach to deal with this problem would be to revalidate the
old certificate if the same resource is now served with a new one. If
either certificate is bad, refetch the resource unconditionally.
Reply all
Reply to author
Forward
0 new messages