IMPORTANT: this issue has been cleared for public discussion and resolution by the Drupal Security Team based on the low evidence of vulnerable browsers still existing.

Problem/Motivation

filter_xss does not filter out the accent grave ` character. This opens up an m-XSS (mutation-XSS) vector in some versions of IE7/8, which treats ` as a delimiter character, and we can escape out of a valid attribute, since it does not put double quotes when it's returned via innerHTML property.

The issue is not marked critical because it only affects a small percentage of older browsers under older versions, but marked as "major" since it is XSS that could be easily triggered by non-privileged users on those browsers.

Proof of concept:

<html>
<head>
</head>
<div id="a"><input value="``onmouseover=alert(1)"></div>
<div id="b"></div>
<script>b.innerHTML=a.innerHTML</script>
</html>

Attacker's Input:

``onmouseover=alert(1)

Vulnerable Browser’s Output:

<div id="a"><input value=``onmouseover=alert(1)></div>

Patched Browser’s Output:

<div id="a"><input value="``onmouseover=alert(1)"></div>

Damien Tournoud was able to find that Drupal core’s autocomplete.js is a place where this vulnerability could be exploited, in anything that builds HTML autocomplete snippets (Entity Reference, for example):

$(this.ariaLive).html($(this.selected).html());

This bug was confirmed by grendzy on IE8 version 8.0.7601.17514 (windows 7) in December of 2013. According to Wikipedia, this is the latest stable release of IE8.

However, Pere Orga (June 2015) was unable to reproduce it in IE 8.0.6001.18702 (xp) (though could in IE 7.0.5730.13 (xp)). He was testing with browserstack, which for some reason only offers IE 8.0.6001.19600 on Windows 7 (this version should only be available in XP given the "6001" part of the version number).

Mario Heiderich, the author of http://www.slideshare.net/x00mario/the-innerhtml-apocalypse, claims on slide 28 that a patch is out for IE 8, but this hasn’t been able to be confirmed by the Drupal security team.

Proposed resolution

pwolanin notes that the paper at https://cure53.de/fp170.pdf seems to suggest a couple server-side and one client-side fix in section 5. David_Rothstein also noted that "Dealing with it in JavaScript seems like a good backup (maybe for situations where text is filtered without calling filter_xss(), like https://www.drupal.org/project/wysiwyg_filter?). But I think we need to fix it server-side in filter_xss() also."

A client-side fix is available by grendzy. While not a fix for direct calls to .innerHTML, it works by overriding jQuery.html() with a version that replaces ` with "`" for IE 8, and should meet most of core/contrib’s use cases. Note however that this direction still needs work; it was tested and found not to fix the issue. (It also has a stray console.log() but that’s pretty minor.)

A server-side fix is available by pwolanin, based on the HTMLPurifier library. This works by adding a new _filter_xss_ie8_fix_attr_value(&$string) function (called from _filter_xss_attributes()) that triggers IE8 to quote properly in the presence of a ` character. This was tested and found to work.

Remaining tasks

  • Need someone to test in actual IE 8 / Windows 7 to see if bug has in fact been patched.
  • get the client-side version working, add tests for the server-side version, back port both to D6.

API changes

Possibly, depending on the route taken. See "Proposed resolution."

Original report by Rafay Baloch

Rafay Baloch posted Dec 2 to security:

While testing your XSS filter function i found that, you are not filtering out the accent grave which has known problems with IE8.

https://api.drupal.org/api/drupal/modules%21filter%21filter.module/funct...

The issue occurs inside of internet explorer only because treats accent grave ` as a delimiter character, and we can escape out of a valid attribute inside of an un-patched IE 8, since it does not put double quotes around our vector when it's returned via innerHTML property.

=============
Proof of concept
=============

Here is the POC that came by slightly modifying the following example at html5sec.org#59.

The POC was tested in Internet explorer version 8:

<html>
<head>
</head>
<div id="a"><input value="``onmouseover=alert(1)"></div>
<div id="b"></div>
<script>b.innerHTML=a.innerHTML</script>
</html>

Attacker's Input:

``onmouseover=alert(1)

Vulnerable Browsers Output:

<div id="a"><input value=``onmouseover=alert(1)></div>

Patched Browsers Output:

<div id="a"><input value="``onmouseover=alert(1)"></div>

When the above POC is tested inside of an unpatched Internet explorer 8, it was noticed that IE 8 does not places quotes around it when it's rendered by innerHTML property. However, When placed in a patched version of internet explorer, it places double quotes around when the string is returned back to the user, hence stopping the attack.

===
Fix
===

Currently, I am not aware of any other solutions then stripping out the accent grave character, encoding doesn't seems to solve the problem here.

==========
References
==========

http://html5sec.org/#59
http://www.slideshare.net/x00mario/the-innerhtml-apocalypse
https://cure53.de/fp170.pdf

--
Warm Regards,
Rafay Baloch

http://rafayhackingarticles.net
http://techlotips.com

Comments

pwolanin created an issue. See original summary.

pwolanin’s picture

Issue summary: View changes
StatusFileSize
new3.7 KB

Attaching the most recent D7 patch - though there was some debate about:

 if (strpos($string, '``') === 0)

vs !== FALSE as the check.

patches were by droplet, and myself (pwolanin)

There was also a suggestion to encode the grave accent as a HTML entity if that prevents the attack.

pwolanin’s picture

StatusFileSize
new1.7 KB

And an earlier D6 version

pwolanin’s picture

Status: Active » Needs work
pwolanin’s picture

Issue summary: View changes
David_Rothstein’s picture

Title: [D6, D7] DOM Based XSS with ` character on IE8 » DOM Based XSS with ` character on IE8 and older versions
Version: 7.x-dev » 8.0.x-dev
Issue tags: +Needs backport to D7

This affects Drupal 8 too, which supports older browsers from a security + basic functionality point of view even if it doesn't support them otherwise (see https://www.drupal.org/node/1569578).

I'm not really sure it should be considered a critical issue though.

David_Rothstein’s picture

Some more up-to-date information from the private security issue.

On browser versions that may be vulnerable:

  1. For IE6, an older version (IE 6.0.2600.0000) was found to be vulnerable, but all tests with a newer version (IE 6.0.2900.5512) found them not to be vulnerable. That suggests this was fixed at some point in IE6/Windows XP itself.
  2. For IE7, IE 7.0.5730.13 (Windows XP) was found to be vulnerable, but a newer version, IE 7.0.6002.18005 (Windows Vista), was found not vulnerable. That suggests this was fixed at some point in IE7 itself (at least for Windows Vista).
  3. IE8 is still a mystery; a security team member (grendzy) testing this originally found IE 8.0.7601.17514 to be vulnerable (with pretty clear results including a screenshot), but it has not been reproduced on that exact same version since then despite multiple attempts. And that still appears to be the latest IE8 release.

So all evidence points to Microsoft having fixed this for IE6 and IE7, and no one has reproduced it for IE8 recently either. Unless we believe they fixed it for older versions but not newer ones, the most likely conclusion is that they patched it somehow for IE8 too (although it's still not clear how that relates to the version numbers).

Still it may be worth considering a fix.

Some notes on that:

  1. Another link that helps explain the issue:
    https://www.owasp.org/index.php/OWASP_Java_Encoder_Project#tab=Grave_Acc...
  2. The best example of a vulnerable code snippet is here (according to previous rounds of testing):
    http://crackingdrupal.com/iexss.html

    Which contains:
    <html>
    <head>
    </head>
    <em id="a"><code lang="``onmouseover=alert(1)">text text text</code></em>
    <div id="b"></div>
    <script>b.innerHTML=a.innerHTML</script>
    </html>

  3. Our current solution to fix this is based on this code (which probably needs to be credited in the patch):
    https://github.com/ezyang/htmlpurifier/blob/v4.7.0/library/HTMLPurifier/...
  4. For Drupal 7, at least, fixing in check_plain() (rather than drupal_attributes()) may be a more robust way to go.
  5. axel.rutz suggested testing &#96; and &grave;. If those aren't vulnerable, then converting the accent grave to one of those may be better (especially if we are including a fix within check_plain() itself, because then it's much more inline with the purpose of that function).
catch’s picture

I also think this doesn't need to be critical, it would have been in 2010 or so. The support for older browsers for security means we wouldn't automatically mark it won't fix, not that fixing it is critical (although if it's confirmed fixed in IE8 then I'm not sure we need to do anything here generally).

xjm’s picture

Priority: Critical » Major

Discussed with @catch; we agreed the issue does not need to be critical at this point.

xjm’s picture

Issue summary: View changes
xjm’s picture

Issue summary: View changes

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.

xjm’s picture

Version: 8.1.x-dev » 7.x-dev
Issue tags: -Needs backport to D7

At this point, Drupal 8 officially does not support IE 8:
https://www.drupal.org/node/1569578
https://www.drupal.org/docs/8/system-requirements/browser-requirements

Based on that, and the fact that this issue only affected old versions of IE 8 and was not reproduced reliably, @catch, @alexpott, @effulgentsia, @Cottser, and I agreed to consider this wontfix for Drupal 8.

Moving to 7.x for the D7 maintainers to decide what they would like to do for this issue (if anything) since D7 still supports IE8.

Thanks!

xjm’s picture

Title: DOM Based XSS with ` character on IE8 and older versions » DOM-based XSS with ` character on IE8 and older versions
David_Rothstein’s picture

Version: 7.x-dev » 8.2.x-dev
Issue tags: +Needs backport to D7

That's the same change notice I linked to above. It says that front-end support was dropped, but server-side/functional support wasn't. And I believe there is still code in the Drupal 8 filter system, form API, etc, that exists to support older versions of Internet Explorer.

If there was a decision to drop support further, I can't find any record of it. And dropping security support for older browsers should be a Drupal-wide decision, not a separate decision for different stable releases.

There is actually a discussion of that policy ongoing at #2390621: [policy, no patch] Update Drupal's browser support policy. My take is that security issues are worth fixing at least when the impact of the fix is low. (We can't know what browsers people will access a site with, and if an older browser had a certain behavior it's certainly possible some other browser in the future could wind up having the same behavior too.)

I am not sure if the fix for this issue would be low-impact or not. Note that since the comments above, @droplet actually did find some reliable ways to reproduce this on IE8 (not all installatons of IE8, but particular ones) and also found that replacing the accent grave character with &#96; does not fix the issue, but replacing it with &grave; does "fix" it in the sense that IE8 doesn't know how to interpret that entity at all. So assuming all modern browsers do interpret it correctly and that no one cares about breaking the accent grave character's display on IE8 at this point, it's a possible easy fix.

David_Rothstein’s picture

I forgot to mention, @droplet also suggested it might be sufficient to replace a double accent-grave (``) only, unlike HTMLPurifier which deals with single accent grave characters also. This is because of other XSS filtering protection Drupal already has.

Not sure if that's 100% guaranteed to be true, but if so it's a potentially even lower-impact fix.

effulgentsia’s picture

So assuming all modern browsers do interpret it correctly and that no one cares about breaking the accent grave character's display on IE8 at this point, it's a possible easy fix.

This seems to me like an appealing fix. &grave; is explicitly defined in HTML5 and is not defined in HTML4. Perhaps this is the reason it's not recognized in IE8? Since Drupal 8's html.html.twig uses the HTML5 doctype, I think a filter that converts from a grave character to &grave; is pretty reasonable. However, is this reasonable for D7 backport, which does not use HTML5?

xjm’s picture

Hm I thought @catch had fixed the CR; it was not updated entirely.

https://www.drupal.org/docs/8/system-requirements/browser-requirements specifically says "Internet Explorer 9.x and later" and for me that is what we support.

xjm’s picture

@Dries said in #1787012-139: [policy, no patch] Write D8 JS against ECMAScript 5. Prevent errors with feature detection (drop IE8 support):

Having thought about this more I'm comfortable removing IE8 support from Drupal 8 core. If IE8 support is important for people, we should recommend them to stay with Drupal 7 for another year or so. I also have hopes that we can build a contributed module that provide IE8 support for Drupal 8.

So that's what I think we need to make the documentation reflect, and also why D7 still needs this fix.

effulgentsia’s picture

I believe there is still code in the Drupal 8 filter system, form API, etc, that exists to support older versions of Internet Explorer

Form API does have some code that coddles Internet Explorer, such as the code that starts with the comment in FormBuilder::doBuildForm():

// If a form contains a single textfield, and the ENTER key is pressed
// within it, Internet Explorer submits the form with no POST data

But AFAIK, that's true for IE9. I'm not aware of any D8 FAPI code that's there to coddle IE8 or lower, but if you find any, please reference that.

However, D8 does still have this code in Xss::filter():

// Only operate on valid UTF-8 strings. This is necessary to prevent cross
// site scripting issues on Internet Explorer 6.
if (!Unicode::validateUtf8($string)) {
  return '';
}

So you're right that there's some precedent for D8 still having security-related code for unsupported IE versions.

If there was a decision to drop support further, I can't find any record of it.

Answered in #18 and #19.

We can't know what browsers people will access a site with... dropping security support for older browsers should be a Drupal-wide decision, not a separate decision for different stable releases.

Hm, this is basically claiming that Drupal should be responsible for security, even on browsers that don't meet the requirements in https://www.drupal.org/docs/8/system-requirements/browser-requirements. That might be a reasonable position, given that that same page also says:

Websites built using just Drupal core (i.e. with no additional, contributed modules) are compatible with, and fully functional, in all modern browsers that support CSS and JavaScript.

xjm’s picture

Websites built using just Drupal core (i.e. with no additional, contributed modules) are compatible with, and fully functional, in all modern browsers that support CSS and JavaScript

IE5 supported CSS and JavaScript. ;) If "modern" is the difference vs. IE5, IE8 is not modern either.

I guess maybe we need to check back in with the security working group as to whether we should reopen discussion to qualify Dries' decision.

David_Rothstein’s picture

This seems to me like an appealing fix. &grave; is explicitly defined in HTML5 and is not defined in HTML4. Perhaps this is the reason it's not recognized in IE8? ... However, is this reasonable for D7 backport, which does not use HTML5?

Hm, yes, looks like it would make Drupal 7's HTML not validate (although as a practical matter modern browsers recognize the character even on HTML4 pages).

However, I also found that for both Drupal 7 and 8 &grave; doesn't seem to work at all on modern browsers either (even with Full HTML)... which is strange because it works with bare HTML using the same DOCTYPE that Drupal 7 or 8 use. Didn't have time to investigate further right now, but it calls into question whether this fix would actually provide any real benefit for IE8 too (maybe IE8 does interpret &grave; in certain contexts after all).

In the worst case the HTMLPurifier fix is probably good enough. It's not comprehensive if we don't protect against things like <tag attribute="@value"> (where @value is user input that has been run through Drupal's HTML-escaping), but as a practical matter protecting against this in XSS-filtering only would tend to be pretty effective.

I only skimmed through #1787012: [policy, no patch] Write D8 JS against ECMAScript 5. Prevent errors with feature detection (drop IE8 support) but I don't see where it suggested dropping core support for IE8 beyond the front-end. And there even exists https://www.drupal.org/project/ie8 in contrib now, although it doesn't seem to be getting much use :)

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.

gapple’s picture

Status: Needs work » Closed (outdated)

Support for Internet Explorer versions prior to 11 was dropped in 8.4
https://www.drupal.org/node/2897971