Page MenuHomePhabricator

Add support for Content-Security-Policy (CSP) headers in MediaWiki
Open, MediumPublic

Description

A significant portion of security vulnerabilities in MediaWiki are XSS vulnerabilities. Content-Security-Policy is an HTTP header that allows you to disable certain HTML features, which are commonly used when exploiting XSS vulnerabilities. Adopting CSP has the potential to make MediaWiki sites significantly more safe.

See https://www.mediawiki.org/wiki/Requests_for_comment/Content-Security-Policy for the full proposal. See http://www.w3.org/TR/CSP2/ for the official CSP spec.

Summary:

  • CSP disables all the inline ways of executing javascript (e.g. <img onerror="alert(1)"> )
    • Only way that's left <script src="foo"> where foo is a whitelist, or <script nonce="bar"> where bar is in the http header
    • From our perspective, the primary benefit is when the attacker can inject non whitelisted attributes but not full on script tags, since users control javascript on our domain (and would riot if we took that away from them). It will also allow us to make super focused blacklists, concentrating just on <script>
  • This will break a lot of old gadgets. JS code following modern conventions mostly won't break. Nonetheless this will probably make a lot of local admins angry. I think this cost is worth the vast benefits, however we will need to provide support to communities to help them deal with the change
    • On the bright side, this will force people to update old code that is using dangerous patterns. Local on-wiki JS is definitely one of our weakest spots security wise.
  • We can enable CSP piece by piece, starting non-controversial, and working our way up. We can also enable a report-only mode to see what will break beforehand.

Related bugs: T117618, T28508, T120888, T130748

Related Objects

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Change 253969 merged by jenkins-bot:
[mediawiki/core@master] Initial support for Content Security Policy, disabled by default

https://gerrit.wikimedia.org/r/253969

Do we want to mark this as Resolved now, or wait until we've tested it in production a bit and addressed any follow-ups / fixes?

This is probably more of an epic task. Just because the patch is merged doesnt mean we can fully put CSP in enforce mode tomorrow (indeed initial rollout plan wont include removing unsafe-inline)

A more detailed rollout plan will be forthcoming

The errors I am getting are like this:

[16-May-2018 14:55:23 UTC] PHP Notice:  ResourceLoader::makeInlineScript did not get nonce. Will break CSP [Called from ResourceLoader::makeInlineScript in /srv/mediawiki/tags/2018-05-16_14:06:40/includes/resourceloader/ResourceLoader.php at line 1513] in /srv/mediawiki/tags/2018-05-16_14:06:40/includes/debug/MWDebug.php on line 309

Is it possible to make them more informative what is the source?

It probably means that some extension hasnt been updated for makeInlineScript() new arguments. (I guess this is a deprecation in a sense and i should email wikitech-l). Im travelling today and cant really look into it today...

Change 452407 had a related patch set uploaded (by Brian Wolff; owner: Brian Wolff):
[operations/mediawiki-config@master] Adjust CSP settings. For this stage allow inline but restrict src

https://gerrit.wikimedia.org/r/452407

Change 452407 merged by jenkins-bot:
[operations/mediawiki-config@master] Adjust CSP settings. For this stage allow inline but restrict src

https://gerrit.wikimedia.org/r/452407

Ok, so status update. We are now testing what we intend to be the initial deployment (Still allow inline scripts, but block loading of external stuff) on group0 wikis (e.g. https://test.wikipedia.org and https://mediawiki.org )

The description mentions some onerror attribute that I've never heard of:

CSP disables all the inline ways of executing javascript (e.g. <img onerror="alert(1)"> )

Will this also affect onclick attributes?

The description mentions some onerror attribute that I've never heard of:

CSP disables all the inline ways of executing javascript (e.g. <img onerror="alert(1)"> )

Will this also affect onclick attributes?

So our plans have changed a little bit since this bug was initially written. First step we are just going to block external stuff from non-Wikimedia domains. We expect that this transition is going to be complicated enough and take quite a bit of time, so for now we are dropping the disable inline javascript (Which includes disabling all attributes starting with on including onclick). Eventually I'd like to see the disabling of onclick and friends, but that's far in the future at this point.

There seems to be quite a bit of activity on this, but the RFC is still tagged as "under discussion". As far as I know, some parts of the RFC were approved, while other where still being discussed. What'S the status here? What remains to be done? What are the plans? Is this ready for a final discussion?

There seems to be quite a bit of activity on this, but the RFC is still tagged as "under discussion". As far as I know, some parts of the RFC were approved, while other where still being discussed. What's the status here? What remains to be done? What are the plans? Is this ready for a final discussion?

I wasn't aware it is still tagged under discussion - I thought it was largely "approved".

My plans have evolved somewhat since this was originally discussed. my current draft plan is https://www.mediawiki.org/wiki/User:BWolff_(WMF)/CSP_plan For the moment I want to drop the anti-XSS (no "unsafe-inline") parts and concentrate solely on enforcing no external loads (for privacy, and also ensuring better audit trail in event of MediaWiki:Common.js).

One aspect of this is user's who want to access external apis via JS (e.g. like the google calendar gadget at office wiki). What I would like to do is have a preference so that users who want to do this sort of thing can opt-out of the defence well still allowing us to protect the average user (still restricting script-src in all cases. I don't have the precise details worked out yet). This is something that I would like to bring up with TechCom and can use discussion.

TechCom has marked this approved, but there needs to be another RFC specifically related to the registry to opt-in and connect to 3rd party services. This was not considered as part of the original decision.

This is probably more of an epic task. Just because the patch is merged doesnt mean we can fully put CSP in enforce mode tomorrow (indeed initial rollout plan wont include removing unsafe-inline)

A more detailed rollout plan will be forthcoming

I think that rollout/apply-in-prod is better located at T28508 rather than here?

This is hopefully one of the last RFCs to be all-encompassing of a larger goal. Based on the 8 stages documented at the original RFC at https://www.mediawiki.org/wiki/Requests_for_comment/Content-Security-Policy, I believe that it can be summarised into four high-level stages of which three should be covered an RFC:

  1. The creation of the report-ingestion API.
  2. The immediate enforcing of a very strict CSP policy in browsers when viewing content directly on upload.wikimedia.org (e.g. original SVGs).
  3. Various logging and data gathering stages.
  4. The enforcing of CSP on page views, and its requirements (what default policy to use, how and what to change in core to abide by the policy, how to whitelist additional origins with the user's permission).

The first two bullet points I believe were approved by TechCom in 2016 ("Stage 0-3"), and have since been implemented.

The third bullet point represents the middle stages involving configuration and logging that don't require an RFC. The collecting and storing of data may have needed coordination with Analytics, Legal and/or SRE in terms of what and how long we retain (privacy), how much data in bytes to store and for how long (storage space requirements for Logstash and mwlog servers). This uses existing systems in ways they are designed for, of which additional use does not require architectural approval.

The fourth bullet point should be covered by an RFC. Some of the initial work in this has already started (with TechCom advising directly in Gerrit, https://gerrit.wikimedia.org/r/253969), but it's also clear that there's still a lot of details to be figured out. I'd recommend marking this task as resolved and creating a new task for that work.

A more detailed rollout plan will be forthcoming

I think that rollout/apply-in-prod is better located at T28508 rather than here?

Agreed :)

Can we exempt localhost URLs from this? It would impede user script development.

(I don't know if this is the right place to ask; let me know if it isn't.)

@Bawolff - What is now the correct way to import images to Commons from 3rd party websites on the client-side? For example, when I currently try to import images from Flickr using UploadWizard, I get the following error:

[Report Only] Refused to connect to 'https://api.flickr.com/services/rest/?&format=json&nojsoncallback=1&method=flickr.photos.licenses.getInfo' because it violates the following Content Security Policy directive: "default-src 'self' data: blob: https://upload.wikimedia.org meta.wikimedia.org *.wikimedia.org *.wikipedia.org *.wikinews.org *.wiktionary.org *.wikibooks.org *.wikiversity.org *.wikisource.org wikisource.org *.wikiquote.org *.wikidata.org *.wikivoyage.org *.mediawiki.org wikimedia.org". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

Should we add api.flickr.com to the CSP or does UploadWizard need to be refactored somehow?

Shouldn't that call be going via our API and urldownloader hosts?

@Krenair - The actual uploading is handled by urluploader, but UploadWizard has to do a lot of communicating with Flickr's API beforehand for information. Is there some kind of proxy API it should be using for that?

@Krenair - The actual uploading is handled by urluploader, but UploadWizard has to do a lot of communicating with Flickr's API beforehand for information. Is there some kind of proxy API it should be using for that?

Ideally it would be done through the server side to preserve user privacy. If it was required to be on client side, (and there was the neccesary privacy approval) the idea was that there would be an api extensions could use to add domains to the whitelist for a specific [special] page. Currently this exists via hooks, but the original plan i had was that a more useful internal api would be added for specific exemptions on specific urls.

Localhost URLs should be added to the CSP. Not being able to load javascript from a local server would severely impede development of user scripts and gadgets. Thanks.

Localhost URLs should be added to the CSP. Not being able to load javascript from a local server would severely impede development of user scripts and gadgets. Thanks.

After discussing this with several script developers, its clear that being able to load scripts from localhost is important to this group. I don't want to allow that generally, but I believe an appropriate compromise would be to have an option that people can opt in to, to allow loading scripts from localhost. More details about how that will work will come once it actually happens.

Ideally [talking to Flickr API] would be done through the server side to preserve user privacy.

The perspective exemplified in this sentence (which, I should note, is taken out of the context provided by the following sentence) needs to be explicitly qualified. Having the free ability to access arbitrary APIs is fundamental to the connected web, and thus critical both in terms of freedom and innovation (both of which I take it as given are among the values of the movement).

Needing to explicitly whitelist each such API is thus a "necessary evil" (tradeoff to achieve reasonable security) rather than a desirable goal in itself. Similarly, proxying third-party APIs—whether through Labs or Toolforge, or…—is thus not sustainable (the number of needed proxies is unbounded) and should only be attempted when the impact is broad and the benefits large: for example, only for something that will affect all or almost all users of Wikimedia sites (like the JS library etc. CDN proxy).

The point being that the framing of these measures needs to be "Access to third-party APIs should only happen with explicit and informed consent from the end user" and "It is preferable to architect functionality such that access to third-party APIs does not happen directly from the end user's web browser". Framing it as "Third-party APIs are bad and should be forbidden (but those pesky users keep demanding them)" carries a not-insignificant risk of taking the wrong turn when making implementation choices down the road.

And to be clear I don't expect that anyone actually disagrees with this, I just think it needs to be both made explicit and kept front and center when working on this to prevent security tunnel-vision from creeping in.

@Bawolff - What is now the correct way to import images to Commons from 3rd party websites on the client-side? For example, when I currently try to import images from Flickr using UploadWizard, I get the following error:

[Report Only] Refused to connect to 'https://api.flickr.com/services/rest/?&format=json&nojsoncallback=1&method=flickr.photos.licenses.getInfo' because it violates the following Content Security Policy directive: "default-src 'self' data: blob: https://upload.wikimedia.org meta.wikimedia.org *.wikimedia.org *.wikipedia.org *.wikinews.org *.wiktionary.org *.wikibooks.org *.wikiversity.org *.wikisource.org wikisource.org *.wikiquote.org *.wikidata.org *.wikivoyage.org *.mediawiki.org wikimedia.org". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

Should we add api.flickr.com to the CSP or does UploadWizard need to be refactored somehow?

At the very least UploadWizard should add the Flickr API to CSP on the special page, as UploadWizard is the extension responsible for contacting the Flickr API.
Maybe it can be done through Output->addDefaultSrc in SpecialUploadWizard.php?

On an unrelated note, is there any plans to add support for headers like img-src, frame-src, etc. ? It would allow stricter CSP as currently default-src is quite limited since it allows any kind of resources passing through.