Bug 179886

Summary: Add setting to disable same-origin and cross-origin subresource requests
Product: WebKit Reporter: Guido Trentalancia <guido2022>
Component: Page LoadingAssignee: WebKit Security Group <webkit-security-unassigned>
Status: RESOLVED WONTFIX    
Severity: Critical CC: annulen, ap, beidson, bfulgham, bugs-noreply, cgarcia, dbates, guido2022, mcatanzaro, product-security, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Local Build   
Hardware: All   
OS: All   
Attachments:
Description Flags
Proposed patch (based on the git development tree)
none
Patch for the current stable branch (2.18.x)
none
Manual Test
none
Proposed patch (based on the git development tree)
none
Proposed patch (based on the git development tree)
ap: review-
Companion patch for the epiphany browser (stable release 3.26.x)
none
Companion patch for the epiphany browser (git or development release 3.27.x) none

Description Guido Trentalancia 2017-11-20 08:01:29 PST
Created attachment 327361 [details]
Proposed patch (based on the git development tree)

The proposed patch adds code to disable Cross-Origin Resource Sharing (CORS) functionality for improved security and privacy.

It does so by adding the following three new Preferences/Settings to WebKit:

- disable-cors: to disable the CORS mode (can be tested for example here: https://test-cors.appspot.com/#technical);
- enable-cors-same-domain: to enable loading resources from a different site within the same domain (slightly less safe, but more functional);
- disable-cors-redirection: to disable redirection (safer, but much less functional).

Two patches are attached: one is intended for the current development tree (git) and the other one is intended for the current stable branch (2.18.x).
Comment 1 Radar WebKit Bug Importer 2017-11-20 08:01:57 PST
<rdar://problem/35646349>
Comment 2 Guido Trentalancia 2017-11-20 08:02:45 PST
Created attachment 327362 [details]
Patch for the current stable branch (2.18.x)
Comment 3 Guido Trentalancia 2017-11-20 08:10:05 PST
Created attachment 327363 [details]
Manual Test

Proposed manual test for the attached patch 327361.
Comment 4 Guido Trentalancia 2017-11-20 09:02:28 PST
Created attachment 327366 [details]
Proposed patch (based on the git development tree)
Comment 5 Guido Trentalancia 2017-11-21 07:52:27 PST
A companion patch is ready for selected browsers and will be posted as soon as this is landed.
Comment 6 Guido Trentalancia 2017-11-21 10:46:24 PST
Created attachment 327422 [details]
Proposed patch (based on the git development tree)
Comment 7 Guido Trentalancia 2017-11-23 10:10:02 PST
Created attachment 327508 [details]
Companion patch for the epiphany browser (stable release 3.26.x)
Comment 8 Guido Trentalancia 2017-11-23 10:10:56 PST
Created attachment 327509 [details]
Companion patch for the epiphany browser (git or development release 3.27.x)
Comment 9 Alexey Proskuryakov 2017-11-23 11:08:04 PST
Comment on attachment 327422 [details]
Proposed patch (based on the git development tree)

How is this different from the multiple existing ways to disable CORS checks in WebCore?
Comment 10 Guido Trentalancia 2017-11-23 11:53:13 PST
To the best of my knowledge there are no other existing "settings" or "preferences" to disable CORS in the existing code (and with the same granularity of preference, as in the three levels proposed here).

I have originally developed the patch for the stable release (2.18.x) and it is now tested quite extensively. It has then be "ported" to the git tree, but I think such new functionality is also missing in git.

For several days I had received no feedback. But thanks for getting back now.

The patch needs to be reviewed...
Comment 11 Konstantin Tokarev 2017-11-25 01:32:17 PST
Disabling CORS is a sure way to break lots of pages, or at least parts of them. It's also questionable as a security measure: if you don't trust CORS headers that web server is sending you, or you assume page author is using requests to other origins solely for ads, there is no reason to assume that requests to main resource origin can be trusted, e.g. main origin's web server may be proxying some requests to 3rd party servers and send them data about you.

I think that you should use generic content filtering, e.g. CONTENT_EXTENSIONS, to block unwanted requests instead.

Alternatively, you could use proxy server like Squid, which can do any modification of request and response headers, including removing CORS headers.
Comment 12 Guido Trentalancia 2017-11-25 04:40:02 PST
Thanks for your feedback, Konstantin but I have no plans to implement in a different way because it works so well, as in the tests that I carried out with the stable WebKit release.

Disabling CORS is an effective security measure to enforce that content is fetched only from the desired origin and not from other origins imposed by the content provider and not verified or authorized by the end user.

Suppose that A trusts B. If I trust A for whatever good reason, not necessarily trusting B is a good thing just because A trusts it.

Also, if a page breaks partially when CORS is disabled (such as some images do not load), that it because of their poor and flawed design.
Comment 13 Michael Catanzaro 2017-11-25 13:25:34 PST
(In reply to Alexey Proskuryakov from comment #9)
> How is this different from the multiple existing ways to disable CORS checks
> in WebCore?

^ This was your review here. r- means review denied... you'll need to investigate Alexey's question to advance this.

(In reply to Guido Trentalancia from comment #12)
> Also, if a page breaks partially when CORS is disabled (such as some images
> do not load), that it because of their poor and flawed design.

Could this be a misunderstanding of the purpose of CORS? CORS allows a website to instruct the browser which third-party resources should be allowed to load. It would be nonsense for CORS to exist at all if websites could not rely on it working as expected. So I think it would not be appropriate for a general-purpose browser like Epiphany to expose this setting.
Comment 14 Guido Trentalancia 2017-11-25 13:49:52 PST
I have already replied to the initial review: there is no such setting / preference / functionality in the existing WebKit code.

Also, I am quite sure there is no misunderstanding about CORS. CORS is a vulnerability in terms of both security and privacy. Its risks outweigh its benefits.

As already explained, the fact that an initial trusted content provider A "trusts" (or more generally, "is in business with") one (or more) secondary content provider B (and C, D, ...), and thus links its own resources to those provided by such secondary content providers, does not constitute a valid reason for a generic user browsing a web page served by A (trusted by the user) to also trust resources provided by B (and C, D, ...) which is not generally trusted by the user.

The proposed patch constitutes a countermeasure to allow safe and private browsing. Because it is configurable it can be enabled or disabled at the user's will, so I believe it is appropriate for all browsers.

I do highly recommend to use this patch.
Comment 15 Daniel Bates 2017-11-25 15:43:30 PST
(In reply to Guido Trentalancia from comment #0)
> Created attachment 327361 [details]
> Proposed patch (based on the git development tree)
> 
> The proposed patch adds code to disable Cross-Origin Resource Sharing (CORS)
> functionality for improved security and privacy.

This is disingenuous. This patch does not so much as disable CORS as it adds a settings to disallow same-origin and cross-origin subresource requests.

Cross-Origin Resource Sharing (CORS) refers to the protocol described in <https://www.w3.org/TR/cors/>. And this protocol can be summarized as a way to allow JavaScript to load/access the contents of a cross-origin resource that is typically blocked by the same-origin policy.

As mentioned by Konstantin Tokarev in his remark in comment #11, content filtering is the preferred way to achieve the effect that you want. If you are unable to use content filtering to achieve your desired effect then please explain what issue(s) you are running into.
Comment 16 Daniel Bates 2017-11-25 15:45:51 PST
(In reply to Guido Trentalancia from comment #14)
> I have already replied to the initial review: there is no such setting /
> preference / functionality in the existing WebKit code.
> 
> Also, I am quite sure there is no misunderstanding about CORS. CORS is a
> vulnerability in terms of both security and privacy. Its risks outweigh its
> benefits.

This is a misunderstanding of CORS.
Comment 17 Daniel Bates 2017-11-25 15:46:49 PST
(In reply to Daniel Bates from comment #16)
> (In reply to Guido Trentalancia from comment #14)
> > I have already replied to the initial review: there is no such setting /
> > preference / functionality in the existing WebKit code.
> > 
> > Also, I am quite sure there is no misunderstanding about CORS. CORS is a
> > vulnerability in terms of both security and privacy. Its risks outweigh its
> > benefits.
> 
> This is a misunderstanding of CORS.

See second paragraph of my remark in comment #15 for more details.
Comment 18 Konstantin Tokarev 2017-11-25 16:55:03 PST
(In reply to Guido Trentalancia from comment #12)

There are lots of sites and web applications that use different domains for different types of content, and not necessarily on the same privatly controlled domain, for example when they use CDNs. CORS headers specify which domains are required for the page to correctly function when same-origin policy is enforced. 

>Also, if a page breaks partially when CORS is disabled (such as some images do not load), that it because of their poor and flawed design.

If page is compliant with W3C recommendations and breaks because of non-standard behavior of user agent, page author cannot be blaimed for that.

That said, such behavior can be introduced at different layer without making intrusive WebCore hacks. It seems you are interested in GTK port -  WebKitWebPage::send-request signal should allow to do such filtering without touching WebKit code.
Comment 19 Konstantin Tokarev 2017-11-25 17:36:01 PST
(In reply to Guido Trentalancia from comment #14)
> As already explained, the fact that an initial trusted content provider A
> "trusts" (or more generally, "is in business with") one (or more) secondary
> content provider B (and C, D, ...), and thus links its own resources to
> those provided by such secondary content providers, does not constitute a
> valid reason for a generic user browsing a web page served by A (trusted by
> the user) to also trust resources provided by B (and C, D, ...) which is not
> generally trusted by the user.

If you think more about it you will see that your setting actually requires customization for each posible "A" domain (and this customization may be different for different users, as we don't only have "generic" ones at hand). WebCore::Settings is suitable only for per-page settings, not per-domain.
Comment 20 Brent Fulgham 2017-11-27 11:59:02 PST
Given that the preferred way to deal with unwanted cross-site loads is to handle this through the content filtering code paths, I think this should be closed as NTBF.