Follow-up to #2510104: Convert drupalSettings from JavaScript to JSON, to allow for CSP in the future

Problem/Motivation

The current selector for the drupalSettings is:

var settingsElement = document.querySelector('script[type="application/json"][data-drupal-selector="drupal-settings-json"]');

This means that when someone manages to place some drupalSettings on the page by exploiting XSS they could with CSP on manipulate settings, which could potentially lead to a real XSS exploit. (provided the drupalSettings are in the footer)

Proposed resolution

Use a selector as true child of head or body instead:

var settingsElement = document.querySelector('head > script[type="application/json"][data-drupal-selector="drupal-settings-json"], body > script[type="application/json"][data-drupal-selector="drupal-settings-json"]');

e.g. While before this patch with CSP enabled someone could e.g. put a script element into a hypothetical non-secure page-title element (via some buggy contrib module), which would be at:

   content > div.main-region > span.page-title

After this patch, this exploit vector no longer works as it is way harder to manipulate something that is a direct child of BODY or HEAD.

Remaining tasks

- Create patch
- Commit

User interface changes

- None

API changes

- None

RC phase evaluation

  • - Category: Task, because it is security hardening
  • - Priority: Major, because it is security hardening
  • - Prioritized changes: Security
  • - Disruption: None, as it is just the selector that is changed and other selectors will continue to work.

Comments

Fabianx created an issue. See original summary.

sagar ramgade’s picture

Status: Active » Needs review
StatusFileSize
new671 bytes

Patch attached.

fabianx’s picture

Assigned: Unassigned » nod_

Thanks for the patch!

+++ b/core/misc/drupalSettingsLoader.js
@@ -7,7 +7,7 @@
-  var settingsElement = document.querySelector('script[type="application/json"][data-drupal-selector="drupal-settings-json"]');
+    var settingsElement = document.querySelector('head > script[type="application/json"][data-drupal-selector="drupal-settings-json"], body > script[type="application/json"][data-drupal-selector="drupal-settings-json"]');

There is a slight space change that needs to be fixed.

--

Assigning to nod_ for review.

droplet’s picture

It's like better but useless. anyone able to insert a "script" tag, they could inject settings in many way. I'd say close as won't fix and KISS.

pere orga’s picture

It's like better but useless. anyone able to insert a "script" tag, they could inject settings in many way. I'd say close as won't fix and KISS.

Unless CSP is enabled. Then JavaScript code inside script tags would not run, but settings could still be injected that way.

The reason I would close this is because document.querySelector() returns the first element within the document, so the patch would not make much difference.

fabianx’s picture

#5: Oh, yes it would.

Settings are usually at the bottom of the body by now, so someone could inject settings that way - in case of XSS and CSP enabled and given our Drupal.ajax structure I am pretty sure settings are enough to exploit this somehow.

fabianx’s picture

Title: Harden drupalSettings selector against XSS » Harden drupalSettings selector against XSS when CSP is enabled

Clarifying title ...

droplet’s picture

Unless CSP is enabled. Then JavaScript code inside script tags would not run, but settings could still be injected that way.

Umm. make sense.

pere orga’s picture

Settings are usually at the bottom of the body by now, so someone could inject settings that way - in case of XSS and CSP enabled and given our Drupal.ajax structure I am pretty sure settings are enough to exploit this somehow.

Ah, if Drupal settings are in the bottom then yes.

nod_’s picture

At a high level we're in the same situation with D7. anything can add a script tag that messes with Drupal.settings value.

If we take the initial scenario:

This means that when someone manages to place some drupalSettings on the page by exploiting XSS they could manipulate settings, which could potentially lead to a real XSS exploit.

If someone manage to place some drupalSettings on the page, it means they managed to put a script tag on the page (whatever the type attribute is) and if that's the case, all bets are off. We can't do anything to salvage the situation.

The only thing we could do is make drupalsettings an inline script again and add the CSP header + attribute needed: http://www.html5rocks.com/en/tutorials/security/content-security-policy/... short of that I'd vote for a won't fix on this issue.

fabianx’s picture

#10: Huh?

If CSP is enabled and someone manages to put a script tag on the page, it usually is in a deeper down level as only very very few things directly are below BODY or HEAD elements.

So why would this direct-child-of-body-or-head selector not harden the security on that?

nod_’s picture

Status: Needs review » Needs work

Doesn't hurt and it does prevent potential issues when CSP is on. I sort of missed the point in #10.

NW only because of whitespace. RTBC otherwise.

fabianx’s picture

Issue summary: View changes

Updated IS and added RC evaluation.

fabianx’s picture

Status: Needs work » Needs review
StatusFileSize
new782 bytes

Fixed whitespace and added some docs so someone is not "simplifying" this in the future.

nod_’s picture

Status: Needs review » Reviewed & tested by the community

all good

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -rc target triage +rc target

Tagging as RC target after discussing with the other committers.

However no need to self-reference this issue in the comment, git blame (or an explanation) is better.

fabianx’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new740 bytes

Here we go with the self-reference removed.

wim leers’s picture

I think there's a typo? Perhaps I'm just tired.

+++ b/core/misc/drupalSettingsLoader.js
@@ -7,7 +7,8 @@
+  // Use direct child elements to harden XSS exploits when CSP is on.

s/harden XSS exploits/harden against XSS exploits/

Can be fixed on commit either way; all committers are native English speakers :P

fabianx’s picture

StatusFileSize
new610 bytes
new748 bytes

Uhm, ... Thanks! Nice catch :p.

Fixed in attached patch.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed ddda2af on 8.0.x
    Issue #2592925 by Fabianx, Sagar Ramgade: Harden drupalSettings selector...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.