Follow-up to #2510104: Convert drupalSettings from JavaScript to JSON, to allow for CSP in the future
Problem/Motivation
Content security policy is a browser feature available that helps prevent XSS attacks based on headers sent by the site.
For CSP spec see: http://www.w3.org/TR/CSP/
https://www.owasp.org/index.php/Content_Security_Policy
https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
Inline JS is not compatible with enabling a reasonable secure content security policy, so this issue is postponed until the Drupal settings are fixed in the related issue
Proposed resolution
Implement a basic and reasonably secure CSP header for Drupal core, such as
Content-Security-Policy: default-src 'self'; frame-ancestors 'self';
Possibly (or as a follow-up or in contrib): Add a callback to receive and log CSP violation reports to watchdog. e.g. with CSP report-uri directive like:
Content-Security-Policy: default-src 'self'; frame-ancestors 'self'; report-uri /system/csp-report-logger;
Likely this reporting should be supported only as a something that can be temporarily enabled for debugging. It has obvious potential for abuse (DoS attacks, bogus data, etc) such as outlined at https://www.virtuesecurity.com/blog/abusing-csp-violation-reporting/
Remaining tasks
Implement
User interface changes
Possibly an admin page to configure some aspects of the CSP (optional for 8.0.x)
API changes
API addition to allow modules to alter or add to the CSP header for each page/or response event.
Beta phase evaluation
Issue category | Task because it is security hardening. |
---|---|
Issue priority | Major because CSP is an important security practice. |
Prioritized changes | The main goal of this issue are security improvements. |
Disruption | Likely not disruptive for contributed modules - unless they embed iframe or load 3rd party JS. |
Comment | File | Size | Author |
---|---|---|---|
#37 | 2513356-nr-bot.txt | 1.63 KB | needs-review-queue-bot |
Issue fork drupal-2513356
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedComment #2
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedComment #3
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedComment #4
Fabianx CreditAttribution: Fabianx as a volunteer commentedNice!
Some questions:
- Can we via our libraries mechanism automatically emit headers for external JS added via that way?
- Is it possible to also restrict directories? Given we know all directories due to aggregation could we restrict those directories?
Comment #5
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedFrom discussion with webchick, having a CSP in core that restricts JS execution should be 8.1.x material.
Not sure about X-Frame-Options: SAMEORIGIN however
Comment #6
Fabianx CreditAttribution: Fabianx as a volunteer commentedEven if we make it an optional hardening?
Comment #7
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedyes, optional == contrib. I think for 8.0.x
Comment #8
Fabianx CreditAttribution: Fabianx as a volunteer commentedWell, core needs to support the API from day 0 - even if then only the contrib module enables it.
Adding at 8.1 will potentially break contrib modules and it is one of the most important security hardenings we can do.
It is also just 'ready' now. And the web is evolving ...
Comment #12
Wim Leers#2789139: [upstream] CSP requires 'unsafe-inline' because of CKEditor 4 also helps make this possible! :)
Comment #14
gappleCore currently still requires
'unsafe-inline'
when CSS aggregation is disabled due to #2897408: Remove IE9 support from CssCollectionRenderer and provide it in contrib instead.--
I've started working on a contrib module to provide automated CSP headers at https://www.drupal.org/project/csp
Currently it parses defined libraries to add a
Content-Security-Policy-Report-Only
header with the necessary domains forscript-src
andstyle-src
. It doesn't actually report anywhere yet other than the browser console, but a built-in report endpoint is also in the works.#2895245: API for modules to alter policy considers adding an additional attribute to library definitions to support additional policies such as
connect-src
.--
Policies can only specify domains, not directories, but I have another experiment where I used Apache rewrite rules to establish separate subdomains restricted to their responsibilities, altered URIs to their respective subdomains, and applied the policy:
Comment #15
gappleComment #16
AnybodyComment #18
gappleI reopened #2789139: [upstream] CSP requires 'unsafe-inline' because of CKEditor 4, since CKEditor still requires
'unsafe-inline'
. The improvements in CKEditor 4.7 only removed the need for'unsafe-eval'
.Comment #20
gappleAny documentation or articles I've seen so far only uses domains, and I haven't tested the state of browser support, but the spec does allow restricting by directory (CSP Level 3 - 6.6.2.10. path-part matching).
So this would theoretically be possible:
Comment #21
gappleCSP module has seen significant improvements, and has a stable release now.
I've proposed using an additional property in library definitions to enable support for additional directives: #2895245: API for modules to alter policy
Comment #30
mxr576#2789139: [upstream] CSP requires 'unsafe-inline' because of CKEditor 4 comment #30
Is that unblock this issue?
Comment #31
gappleA remaining issue is that the
core/drupal.ajax
library still requiresstyle-src 'unsafe-inline'
: #3110517: Improve Drupal\Core\Ajax\AddCssCommand to accept an array of CSS assets----
The CSP module's default enforced policy is currently quite lenient (
frame-ancestors 'self'; object-src 'none'
), because it's reasonably likely that something likedefault-src 'self'
will block expected functionality and has the potential to DDOS your own site with the default of logging violation reports to the site log (if not properly configured in a dev environment before deploying to an active site).The default report-only policy is stricter (adding
style-src
andscript-src
directives, and will include any relevant domains from library definitions), but also only reports to the browser console in anticipation of the potential initial violations.Comment #33
bkosborneI guess the X-Frame-Options header that core adds via FinishResponseSubscriber should also be removed when this is done. The "frame-ancestors" directive in the CSP header is well supported and obsoletes X-Frame-Options.
Comment #34
gappleWith IE no longer being supported, core could replace its default
X-Frame-Options: SAMEORIGIN
withContent-Security-Policy: frame-ancestors 'self'
. Starting to always add a default CSP header could cause problems for a site that setsX-Frame-Options: DENY
though. (It looks like IE was the only browser to supportALLOW-FROM
).A possible transition is:
[11.1] Add a late-subscriber that translates x-frame-options to a CSP frame-ancestors if the response does not have a CSP header (assume if a CSP header is set but does not include frame-ancestors, then it was intended to allow any frame parent). Issue a deprecation warning if the response has a value other than
X-Frame-Options: SAMEORIGIN
to notify users to use CSP instead.[12.0] Remove the late subscriber, and replace
X-Frame-Options
with a static CSP policy that includesframe-ancestors 'self'
. A site that uses the Content-Security-Policy module, SecKit, or a custom listener to set the CSP header will override this default value.My suggestion for a minimal static policy that core can add by default:
The simplest way to allow modifying the default CSP (or adding a CSP-Report-Only), would be to have a container parameter. Users wanting a more flexible implementation can use the CSP module.
Comment #36
gappleA slightly rough MR:
- Introduce a new service parameter for setting static CSP values
- A late acting response subscriber will translate
X-Frame-Options
toContent-Secutity-Policy: frame-ancestors
- If a CSP policy is set (via service parameter, or another module like CSP or seckit), then that value is not changed.
- The
X-Frame-Options
header is always removed - either it's being replaced by core with an equivalent CSP policy, or we assume that the CSP policy set by the user has their desiredframe-ancestors
value (including the option of being omitted).- If
X-Frame-Options
is not set toSAMEORIGIN
, then a deprecation warning is issued to use CSP to set the value. (If the value is still the defaultSAMEORIGIN
, then a future version of Drupal changing toframe-ancestors 'self'
will not change browser behaviour).-
ALLOW-FROM
is ignored by modern browsers (and equivalent to not sending theX-Frame-Options
header), but is translated to a CSP value if used.In a future version of Drupal:
- The service parameter can be set to a default enforced CSP value
- The late acting event subscriber can be completely removed
- Core can stop setting
X-Frame-Options
- Modules (such as CSP or seckit) will still override core's default (now static) value.
Why the CSP policy value:
-
script-src * 'unsafe-inline'
will only blockeval()
. Not including'unsafe-inline'
would have the potential to break existing sites (and hopefully its presence leads people to explore making sure it's not required...)-
object-src 'none'
is recommended to block legacy HTML elements-
frame-ancestors
replacesX-Frame-Options
- I don't think there's other values that can safely be added as a default enforced policy directive without a reasonable risk of negatively affecting some sites. (maybe
base-uri 'self'
?)Comment #37
needs-review-queue-bot CreditAttribution: needs-review-queue-bot as a volunteer commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.