continued from http://drupal.org/node/324880 to discuss a more general hardening of Forms API against array keys that contain XSS and that are used as form name elements.

initial patch see: http://drupal.org/files/issues/book-fix-sdo545-1.patch

CommentFileSizeAuthor
#6 331879.patch1.49 KBfietserwin
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

webchick’s picture

subscribe.

pwolanin’s picture

Issue tags: +Security improvements

tagging

pwolanin’s picture

Priority: Normal » Critical

important for 7.x to reduce vulnerabilities proactively

chx’s picture

Version: 7.x-dev » 8.x-dev
Category: task » feature
Priority: Critical » Normal

Doing this is not trivial because if you change form indexes everything changes. I am more inclined to add this to write secure code page. This clearly wont happen in D7 however.

scor’s picture

Title: Harden FAPI aginst $form array keys containing XSS » Harden FAPI against $form array keys containing XSS

subscribe

fietserwin’s picture

Version: 8.x-dev » 7.x-dev
Category: feature » bug
FileSize
1.49 KB

To make this issue a bit broader. FAPI sanitizes almost all data supplied via the elements. It either uses:
- check_plain() on places where no html at all is allowed, e.g. values and attributes. (and that includes name as long as name gets rendered via drupal_attributes())
- filter_xss_admin() on places where some html is to be allowed, e.g. #title (which gets rendered as the content of a 'label' tag).

However I found (at least) 3 inconsistencies:
- Legend title (#title entry for #type = ‘fieldset’ elements): not filtered (whereas label text does go through xss_filter_admin()). According to the xhtml specification they accept both the same data between tag and closing tag: text and inline elements. Conceptually both are labels and thus should be handled the same.
- Optgroup text (multi level array #options entry for #type = ‘select’ elements): Select options can be grouped using the optgroup tag. The text for the optgroup does not get filtered, whereas if the #options array is not multi-level (not grouped), it does go through check_plain().
- #description does not get filtered. Description may contain html markup, but still, passing it through filter_xss_admin seems reasonable.

Functions concerned (all in form.inc):
- theme_fieldset() (versus theme_form_element_label())
- form_select_options()
- theme_fieldset(), theme_form_element()

Security implications are small, that's why the security team advised to publicly post these findings (as follow up to this post). IMO developers may assume consistent behaviour from FAPI and that behaviour being filtering/encoding all supplied data. Especially the keys in the select options being encoded when used as value attribute (flat array) but not encoded when used as optgroup (multi level array) is very inconsistent. Therefore I change the category to bug and the version back to 7.

Notes:
- D6 has the same problems and thus the same (minor) security implications. So I think it is better to solve it there as well.
- #field_prefix and #field_suffix are not filtered either. But I'm not sure that this should be done. I don't think so. These are helper fields that allow to render just about anything you (as developer) may want, that's their strength. I can't imagine a situation where this would come from user input.

I attached a patch (against D7 official release, so line count may be a bit off) for the above described situations.

fietserwin’s picture

Status: Active » Needs review
rfay’s picture

Status: Needs review » Needs work

I'm setting this to CNW just because the testbots seem to be testing over and over, and I'd like them to catch up. It's OK to queue this for testing later if it doesn't come back green. (It is in fact testing right now.)

stella’s picture

subscribe

scor’s picture

subscribe

fietserwin’s picture

Status: Needs work » Needs review
fietserwin’s picture

Version: 7.x-dev » 8.x-dev

Marked #932144: fieldset <legend /> uses $element['#title'] without filter_xss_admin() as a duplicate (but only covering part of this patch).

Changing to D8 as that's where it should be committed first, hopefully before the new html5 form element initiative is started.

rfay’s picture

Issue tags: +Needs backport to D7

And tagging...

fietserwin’s picture

Marked #319483: FAPI checkboxes and radios need strengthening for XSS as candidate for merging into this issue.

sun’s picture

Status: Needs review » Active

I agree with @chx in #4, and I don't think that #319483: FAPI checkboxes and radios need strengthening for XSS is related.

This issue is about form array keys that are dynamically defined via user input, not property values. Therefore, the patch in #6 is bogus.

fietserwin’s picture

I see. I overlooked that difference. I will broaden one of the other issues to "Harden FAPI against $form array values containing XSS" (#319483: FAPI checkboxes and radios need strengthening for XSS or #932144: fieldset <legend /> uses $element['#title'] without filter_xss_admin()) and combine my patch with the suggested changes in those issues.

Regarding this issue: I don't see a use case where either a translated string or user input would be used to construct a form array key (and expecting FAPI to check for safe and/or construct valid name, id, and class attributes). But then, don't underestimate the creativity of developers to use unchecked user input in the most unexpected places. But should/can we protect against that in this specific case?

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

larowlan’s picture

Issue summary: View changes
Issue tags: +Bug Smash Initiative

I assume twig auto escape effectively mitigates any vectors now, but will confirm before closing

larowlan’s picture

Version: 8.9.x-dev » 7.x-dev

Confirming this doesn't happen in D8+ because of twig auto-escaping

This test form doesn't yield any XSS alerts, everything is nicely stripped out.


$xss = function ($count) {
      return '<script type="text/javascript">alert("boo ' . $count . '👻");</script>';
    };

    $form[$xss(1)] = [
      '#title' => 'radios',
      '#type' => 'radios',
      '#options' => [
        $xss(2) => $xss(3),
        $xss(4) => $xss(5),
      ],
      '#default_value' => $xss(2),
    ];
    $form[$xss(6)] = [
      '#title' => 'checkboxes',
      '#type' => 'checkboxes',
      '#options' => [
        $xss(7) => $xss(8),
        $xss(9) => $xss(10),
      ],
      '#default_value' => $xss(7),
    ];
    $form[$xss(11)] = [
      '#type' => 'fieldset',
      '#title' => $xss(12),
      '#description' => $xss(13),
      $xss(14) => [
        '#title' => 'foo',
        '#description' => $xss(15),
        '#type' => 'textfield',
      ],
    ];