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
Comment | File | Size | Author |
---|---|---|---|
#6 | 331879.patch | 1.49 KB | fietserwin |
Comments
Comment #1
webchicksubscribe.
Comment #2
pwolanin CreditAttribution: pwolanin commentedtagging
Comment #3
pwolanin CreditAttribution: pwolanin commentedimportant for 7.x to reduce vulnerabilities proactively
Comment #4
chx CreditAttribution: chx commentedDoing 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.
Comment #5
scor CreditAttribution: scor commentedsubscribe
Comment #6
fietserwinTo 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.
Comment #7
fietserwinComment #8
rfayI'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.)
Comment #9
stella CreditAttribution: stella commentedsubscribe
Comment #10
scor CreditAttribution: scor commentedsubscribe
Comment #11
fietserwinComment #12
fietserwinMarked #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.
Comment #13
rfayAnd tagging...
Comment #14
fietserwinMarked #319483: FAPI checkboxes and radios need strengthening for XSS as candidate for merging into this issue.
Comment #15
sunI 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.
Comment #16
fietserwinI 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?
Comment #25
larowlanI assume twig auto escape effectively mitigates any vectors now, but will confirm before closing
Comment #26
larowlanConfirming 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.