Closed
Bug 948151
Opened 12 years ago
Closed 5 years ago
Implement Content Security Policy (CSP) for MDN
Categories
(developer.mozilla.org Graveyard :: General, defect, P2)
Tracking
(Not tracked)
RESOLVED
WONTFIX
People
(Reporter: grobinson, Unassigned)
References
()
Details
(Whiteboard: [specification][type:feature])
What problems would this solve?
===============================
CSP is a W3C-standardized XSS mitigation technique. Used properly, it blocks XSS attacks that have made it through any server-side filters from executing in the user's browser. It is especially useful on sites that display user-generated content, especially when that content can contain markup. A wiki such as MDN is a good example of such a site.
Who would use this?
===================
CSP headers would reduce potential XSS attacks for all MDN users and site visitors.
What would users see?
=====================
Nothing, but they would enjoy greater protection from potential XSS attacks.
What would users do? What would happen as a result?
===================================================
Nothing - CSP 1.0 is implemented by Firefox and Chrome, so all developers have to do is set the headers and make sure they don't break the site to transparently enable protection for all users.
Is there anything else we should know?
======================================
I'm one of the CSP implementors on seceng and would be happy to assist in implementing this feature.
| Reporter | ||
Updated•12 years ago
|
Comment 1•12 years ago
|
||
(In reply to Garrett Robinson [:grobinson] from comment #0)
>
> What would users do? What would happen as a result?
> ===================================================
> Nothing - CSP 1.0 is implemented by Firefox and Chrome,
Safari 7 (OS X 10.9) also supports the unprefixed Content-Security-Policy header.
Comment 2•12 years ago
|
||
Is django-csp [1] enough to implement?
[1] https://github.com/mozilla/django-csp
Flags: needinfo?(jbennett)
Comment 3•12 years ago
|
||
(In reply to Luke Crouch [:groovecoder] from comment #2)
> Is django-csp [1] enough to implement?
>
> [1] https://github.com/mozilla/django-csp
No. That's just the beginning. If I recall, we also have to do things like ensure we have no in-line JS or CSS anywhere (we do) and we need an inventory of all the origins from which we load resources to build a whitelist
| Reporter | ||
Comment 4•12 years ago
|
||
(In reply to Les Orchard [:lorchard] from comment #3)
> No. That's just the beginning. If I recall, we also have to do things like
> ensure we have no in-line JS or CSS anywhere (we do) and we need an
> inventory of all the origins from which we load resources to build a
> whitelist
That's correct. If the site uses a lot of inline JS/CSS, transitioning could require a significant amount of work.
One common technique for transitioning is to leverage the Content-Security-Policy-Report-Only header. Start with a simple policy, like "default-src *". This policy will block inline scripts, eval, and inline styles, but let all other resource loads through. You can set a report-uri, which will receive POST requests from user's browsers when a CSP violation is detected - but the policy will not be enforced, so the experience for the user will be unchanged. You can then iterate by making fixing the violations reported for a given policy, tighten the policy, rinse, repeat...
It looks like django-csp can help setting up a report-uri endpoint.
For a large/busy site like MDN, you might want to enable Report-Only for a subset of users, or even start by enabling it on a development server and testing by browsing the site locally. Otherwise, your report-uri endpoint might receive an overwhelming number of violation reports.
Here are some other good resources:
1. Github's transition: https://github.com/blog/1477-content-security-policy
2. Twitter's transition: https://blog.twitter.com/2013/csp-to-the-rescue-leveraging-the-browser-for-security
3. DEFCON talk from Etsy about CSP (https://www.youtube.com/watch?v=rHq9omsTdrc) and the tools they developed (local browser proxy, other cool stuff: https://github.com/Kennysan/CSPTools)
I've also sent an email to the webappsec WG asking for an inventory of tools to help sites transition to CSP, which will hopefully yield some good suggestions: http://lists.w3.org/Archives/Public/public-webappsec/2014Jan/0075.html
Comment 5•12 years ago
|
||
(In reply to Garrett Robinson [:grobinson] from comment #4)
> (In reply to Les Orchard [:lorchard] from comment #3)
> > No. That's just the beginning. If I recall, we also have to do things like
> > ensure we have no in-line JS or CSS anywhere (we do) and we need an
> > inventory of all the origins from which we load resources to build a
> > whitelist
>
> That's correct. If the site uses a lot of inline JS/CSS, transitioning could
> require a significant amount of work.
The site does indeed use a lot of inline JS/CSS - particularly inline CSS in wiki pages, authored over the years & migrated over from previous installations of other wiki software.
So, probably the first task for this bug is to set up reporting and attempt to build an inventory of offending pages. FWIW, those may number in the 100's to 1000's and need manual edits for each.
Do we have any in-house tools for collecting this kind of reporting in bulk? Or will we need to set up our own from scratch with something like django-csp?
Comment 6•12 years ago
|
||
https://www.oxdef.info/posts/2013/12/08/csp-reporter/ might be useful here ?
| Reporter | ||
Comment 7•12 years ago
|
||
> So, probably the first task for this bug is to set up reporting and attempt to build an inventory of offending pages. FWIW, those may number in the 100's to 1000's and need manual edits for each.
A good intermediate step might be to use the new CSP 1.1 nonce-source (in m-c, currently behind a pref). This would allow you to whitelist specific inline scripts with a random (unguessable) nonce, which would require some small changes to your web application instead of 100's or 1000's of manual edits moving inline scripts to external scripts. Of course, it is desirable (for security, and best practice) to do so eventually.
| Reporter | ||
Comment 8•12 years ago
|
||
(In reply to Les Orchard [:lorchard] from comment #5)
> Do we have any in-house tools for collecting this kind of reporting in bulk?
> Or will we need to set up our own from scratch with something like
> django-csp?
Using django-csp is the way to go here.
My only concern is that using CSP-Report-Only in production is that it might be too noisy, and you will generate enormous logs quickly that could be hard to parse. I think it's worth trying to see how many violations you get. The csp-reporter tool that imelven suggested looks like a great way to parse the results, and appears to have been specifically designed to handle large numbers of violations (probably this exact use case).
Another option for getting started would be to use CSPTools (https://github.com/Kennysan/CSPTools). This uses a proxy server to append headers to any request you wish, and can redirect reporting to localhost. So you could set this up and browse around MDN in your browser, detecting the most obvious violations, and tightening the policy until it's not too noisy to use in production. Probably only worth the trouble if CSP-Report-Only turns out to be too noisy in production.
Comment 9•12 years ago
|
||
(In reply to Garrett Robinson [:grobinson] from comment #7)
> > So, probably the first task for this bug is to set up reporting and attempt to build an inventory of offending pages. FWIW, those may number in the 100's to 1000's and need manual edits for each.
>
> A good intermediate step might be to use the new CSP 1.1 nonce-source (in
> m-c, currently behind a pref).
Browsers supporting CSP without nonce (IE9? 10? 11? Chrome?) will see a broken MDN (they won't run inline scripts at all)
I devised a plan to implement a nonce-like feature https://groups.google.com/d/msg/mozilla.dev.mdn/TljmenoiPBw/rw7eBYMjGVgJ but that's laborious
> This would allow you to whitelist specific
> inline scripts with a random (unguessable) nonce, which would require some
> small changes to your web application instead of 100's or 1000's of manual
> edits moving inline scripts to external scripts. Of course, it is desirable
> (for security, and best practice) to do so eventually.
Why is it desirable for security to remove inline scripts?
A good first step would be to use a loose CSP policy and allow unsafe-inline. That would be an improvement over the current situation anyway. A good CSP policy can restrict what a malicious script can do. For instance, a malicious script could read session cookies, but not send them anywhere.
| Reporter | ||
Comment 10•12 years ago
|
||
(In reply to David Bruant from comment #9)
> Browsers supporting CSP without nonce (IE9? 10? 11? Chrome?) will see a
> broken MDN (they won't run inline scripts at all)
nonce-source is specially treated to address this case (backwards compatibility). If a CSP has "script-src 'nonce-abc' 'unsafe-inline'", CSP 1.0 parser will ignore the nonce and allow inline scripts, so the site won't break. 1.1 parsers ignore 'unsafe-inline' when it's used with nonce-source or hash-source, so they will only execute whitelisted inline scripts.
> I devised a plan to implement a nonce-like feature
> https://groups.google.com/d/msg/mozilla.dev.mdn/TljmenoiPBw/rw7eBYMjGVgJ but
> that's laborious
Yeah, that's overkill. Cool idea, though :)
> > This would allow you to whitelist specific
> > inline scripts with a random (unguessable) nonce, which would require some
> > small changes to your web application instead of 100's or 1000's of manual
> > edits moving inline scripts to external scripts. Of course, it is desirable
> > (for security, and best practice) to do so eventually.
> Why is it desirable for security to remove inline scripts?
Because then we can use CSP to disable them entirely on the page, and that makes it much harder for malicious actors to inject script.
> A good first step would be to use a loose CSP policy and allow
> unsafe-inline. That would be an improvement over the current situation
> anyway. A good CSP policy can restrict what a malicious script can do. For
> instance, a malicious script could read session cookies, but not send them
> anywhere.
It is absolutely a good idea to start with a loose policy that allows unsafe-inline, which is what Facebook, for example, is doing now. However, I would be cautious about limiting your imagination to session cookie exfiltration. There are a lot of other ways XSS can harm users, and the only real solution is to prevent all script other than the script you intend from running.
| Reporter | ||
Comment 11•12 years ago
|
||
To get started, I propose we:
1. Start by setting a loose policy that won't break anything. I will design such a policy.
2. Set up a CSP reporting endpoint. I will set up the endpoint.
3. Start sending the loose policy as both an enforced and report-only header.
We can then proceed with iteratively tightening the policy as discussed in Comment 4.
Comment 12•11 years ago
|
||
(In reply to Luke Crouch [:groovecoder] from comment #2)
> Is django-csp [1] enough to implement?
>
> [1] https://github.com/mozilla/django-csp
I don't actually know anything about CSP or that app, so your guess is as good as mine, unfortunately.
Flags: needinfo?(jbennett)
| Reporter | ||
Comment 13•11 years ago
|
||
So I got excited and promised a bunch of stuff in Comment 11 that I didn't/don't have time to do. Would be awesome if somebody else can pick this up! I am available to help consult. Also note that nonce/hash are riding the trains to release and are currently scheduled to land in 31 (bug 979580)
Comment 14•11 years ago
|
||
:grobinson - totally understand how that goes. Thanks for adding so much information in this bug for another contributor to pick it up. If we prioritize it for MDN, a staff contributor may grab it; if not it's here for a volunteer too.
Comment 15•10 years ago
|
||
I'd be happy to help consult on this, if you folks would like my assistance? I can at least put together a preliminary CSP header and recommendations. We recently completed adding CSP on AMO, so I am confident we can make it happen on MDN as well. :)
Summary: Use Content-Security-Policy (CSP) header on MDN → Implement Content Security Policy (CSP) for MDN
Comment 16•9 years ago
|
||
Some updates:
django-csp does not include a reporting endpoint anymore, so something else will need to be used:
http://django-csp.readthedocs.io/en/latest/reports.html
MDN is implemented in several sites, including:
developer.mozilla.org
developer.cdn.mozilla.net
mdn.mozillademos.org
For each site, the content and configuration is split across Apache configuration files, Django middleware code, and some endpoint-specific header setting. It's complicated, and there is no one on the team that has a current map of everything MDN does.
MDN relies on things like in-line CSS, in-page JS, user-uploaded files, and other things that will make it difficult to write anything less than the most permissive CSP.
We're also planning on moving the site to AWS (bug 1110799), which will take our complete backend development resources for at least a few months. The move will also require more understanding of all the interesting legacy bits of MDN. Progress on CSP in 2016 will probably look a lot like 2015, but we may know more about the ugly parts that make CSP difficult.
I'm interested in CSP, and I think it would be a benefit for MDN and it's users. I need a plan that can be executed incrementally, will not require up-front design changes to the way MDN works today, and won't take too much time away from the AWS move.
Comment 17•9 years ago
|
||
Adding blocker for Risk Record for MDN (Medium)
Comment 18•9 years ago
|
||
Just FYI report-uri.io is quite easy and free to set up and use.
Comment 19•8 years ago
|
||
:jwhitlock - per your CSP question in https://bugzilla.mozilla.org/show_bug.cgi?id=1427156#c5, I believe that would be subresource integrity for external refs and nonces for internal refs.
Comment 20•8 years ago
|
||
If you can't remove the inline JavaScript, the best way to make it work (as :claudijd said) are using hashes (if the page is static) or nonces (if it's dynamic).
Comment 21•8 years ago
|
||
If we're executing arbitrary JavaScript as written by any attacker, then there's not much to be gained from using CSP to nonce these inline scripts – having an external domain as we do is what's important.
You *could* use CSP to restrict where connections can be made to: you could say to only load inline scripts and things from our known domains. This would prevent arbitrary JavaScript from being able to do things like opening XHR connections to any domain that it wanted.
Updated•7 years ago
|
Assignee: nobody → jwhitlock
Status: NEW → ASSIGNED
Comment 22•7 years ago
|
||
Commits pushed to master at https://github.com/mozilla/kuma
https://github.com/mozilla/kuma/commit/abf6061741c89a40caa88a6efc578864f768545c
bug 948151: Add CSP config, reporting endpoint
Add a CSP configuration, based on testing several pages on development.
Enabling CSP and other options are configured from the environment, and
off by default. The policy is configured in the Django settings, and not
configured by the environment. The policy allows inline CSS and
JavaScript, so that the site works without modification, but doesn't
add as much security as it could.
CKEditor 4.5.10 still requires unsafe-eval, but 4.7 claims to remove
this requirement. A decorator adds unsafe-eval only on the editing
pages that use CKEditor.
The reporting view is copied from mozilla/bedrock, and it used to
forward violation reports to Sentry. There were no tests to copy.
https://github.com/mozilla/kuma/commit/ab8373029e4dd72b26187772cf558700c0fe8e5e
Merge pull request #5002 from jwhitlock/csp-948151
bug 948151: Add permissive CSP
Comment 23•7 years ago
|
||
Commits pushed to master at https://github.com/mozilla/kuma
https://github.com/mozilla/kuma/commit/4aa6a301f99b7faa0a263d2c64ddb06d65347d22
bug 948151: Add attachment URLs to CSP img-src
Add the production attachment URL to the list of CSP allowed domains for
images (img-src). Include the local attachment URL if it isn't
production or the same as the web domain (covered by 'self').
https://github.com/mozilla/kuma/commit/a12a0be5e642c40181600a54ff56ab594f8f8930
Merge pull request #5033 from jwhitlock/csp-img-src-uploads-948151
bug 948151: Add attachment URLs to CSP img-src
Comment 24•7 years ago
|
||
Useful article on how CSP could have mitigated the NewEgg / Magecart credit card harvest:
https://blog.sentry.io/2018/09/20/content-security-policy-newegg-breach
We're using connect-src as recommended, limited to "self" and Stripe. There's other ways to exfiltrate this data, but this closes the barn door.
The part that interested me is directly reporting CSP violations to Sentry, rather than re-using the custom reporter from mozilla/bedrock. It is possible that Sentry can be smarter about CSP violation reports using this method, choosing when to send the aggregated reports to developers.
Comment 25•7 years ago
|
||
CSP is not designed to prevent data exfiltration. You can make it very difficult, but there are lots of ways that are difficult to control in the current version of the specification (such as prefetches).
It's still good to put this stuff into place, but while it prevent a broad attack (such as a hijacked library), it probably won't help against an attacker who is attacking a specific property.
Comment 26•7 years ago
|
||
Commits pushed to master at https://github.com/mozilla/kuma
https://github.com/mozilla/kuma/commit/1bd4ec2a3b274c470c4e36545e22f49419de07ee
bug 948151: Use SITE_URL instead of 'self' in CSP
Use SITE_URL, such as 'https://developer.mozilla.org' instead of 'self'
in CSP rules, so that reports won't be generated when loading alternate
domain names like the origin URL.
https://github.com/mozilla/kuma/commit/7752fa9d64316b5b0d5aa9ad94ee3b20bf7cd8d9
bug 948151: Include Wordpress default image server
i2.wp.com is used to load a default avatar when the email
address doesn't have a registered Gravatar image, using the same
protocol as the website.
https://github.com/mozilla/kuma/commit/ce502614a6300344cd89ce1baa2e01efe8ce43dd
Merge pull request #5056 from jwhitlock/csp-cdn-948151
bug 948151: Adjust CSP for CDNs, Gravatar default image
Comment 27•7 years ago
|
||
Commits pushed to master at https://github.com/mozilla/kuma
https://github.com/mozilla/kuma/commit/7f9c9b13d9a1c7325dd20b840f48c7970fcb6465
bug 948151: Add release to Sentry CSP reports
If the CSP_REPORT_URI looks like a Sentry URI, add the commit hash as
sentry_release.
https://github.com/mozilla/kuma/commit/1d0be356c772279fbabb20c5899a35283c3a385c
Merge pull request #5065 from jwhitlock/sentry-csp-reporter-948151
bug 948151: Add release to Sentry CSP reports
Comment 28•7 years ago
|
||
The Sentry CSP reporting endpoint is nice, and allows us to update from the deprecated raven-sentry library [1] to the sentry-sdk library [2]. However, Sentry rejects reports without an effective-directive, which Firefox doesn't send (bug 1192684). Chrome is used by most MDN visitors, so I don't think this is a blocker.
[1] https://github.com/getsentry/raven-python
[2] https://github.com/getsentry/sentry-python
See Also: → 1192684
Comment 29•7 years ago
|
||
The CSP is now enforcing on staging, and Observatory [1] upgraded us from a B to a B+. The recommendations are:
* Remove 'unsafe-inline' from script-src (deducting points)
* Remove 'unsafe-inline' from style-src
* Use frame-ancestors (we can block on main site, but will need for demos domain)
* Use base-uri ('none' seems right for MDN)
* Use form-action (we could generate an allowed list)
I think we can make progress on these. We'll need some inline JS and CSS. We have some Do Not Track detection and analytics JS that have a measurable negative impact on page load when loaded as external scripts. django-csp supports nonce-based exclusions. Hash signatures might work as well. I'm not sure if there is a security reason to pick one or the other.
[1] https://observatory.mozilla.org/analyze/developer.allizom.org
Comment 30•6 years ago
|
||
I haven't made progress on this since comment #29, and I'm leaving the MDN team, so I'm putting back to unassigned.
A possible next step is to test CSP in reporting mode in production for 30-60 minutes, and collect the reports. The details for turning on CSP reports are in https://github.com/mdn/infra/pull/218.
The django-csp library contains a nonce implementation that I haven't attempted to integrate. It looks like it would work well with our template-based inline JS and CSS, while excluding any scripts or CSS that sneak into the content. I've read the source, talked briefly with April, and re-read comment #20, and I'm comfortable with the nonce instead of a hash.
Assignee: jwhitlock → nobody
Status: ASSIGNED → NEW
Updated•6 years ago
|
Priority: -- → P2
Updated•6 years ago
|
Comment 31•5 years ago
|
||
MDN Web Docs' bug reporting has now moved to GitHub. From now on, please file content bugs at https://github.com/mdn/sprints/issues/ and platform bugs at https://github.com/mdn/kuma/issues/.
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → WONTFIX
Updated•5 years ago
|
Product: developer.mozilla.org → developer.mozilla.org Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•