diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php index bd6ae23d8c6..8b645f73c17 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php @@ -112,188 +112,6 @@ class FilterUnitTest extends DrupalUnitTestBase { } } - /** - * Tests limiting allowed tags and XSS prevention. - * - * XSS tests assume that script is disallowed by default and src is allowed - * by default, but on* and style attributes are disallowed. - * - * Script injection vectors mostly adopted from http://ha.ckers.org/xss.html. - * - * Relevant CVEs: - * - CVE-2002-1806, ~CVE-2005-0682, ~CVE-2005-2106, CVE-2005-3973, - * CVE-2006-1226 (= rev. 1.112?), CVE-2008-0273, CVE-2008-3740. - */ - function testFilterXSS() { - // Tag stripping, different ways to work around removal of HTML tags. - $f = filter_xss(''); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping -- simple script without special characters.'); - - $f = filter_xss(''); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- non whitespace character after tag name.'); - - $f = filter_xss(''); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- no space between tag and attribute.'); - - // Null between < and tag name works at least with IE6. - $f = filter_xss("<\0scr\0ipt>alert(0)"); - $this->assertNoNormalized($f, 'ipt', 'HTML tag stripping evasion -- breaking HTML with nulls.'); - - $f = filter_xss(""); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- filter just removing "script".'); - - $f = filter_xss('<'); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- double opening brackets.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- a malformed image tag.'); - - $f = filter_xss('
', array('blockquote')); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- script in a blockqoute.'); - - $f = filter_xss(""); - $this->assertNoNormalized($f, 'script', 'HTML tag stripping evasion -- script within a comment.'); - - // Dangerous attributes removal. - $f = filter_xss('

', array('p')); - $this->assertNoNormalized($f, 'onmouseover', 'HTML filter attributes removal -- events, no evasion.'); - - $f = filter_xss('

  • ', array('li')); - $this->assertNoNormalized($f, 'style', 'HTML filter attributes removal -- style, no evasion.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'onerror', 'HTML filter attributes removal evasion -- spaces before equals sign.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'onabort', 'HTML filter attributes removal evasion -- non alphanumeric characters before equals sign.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'onmediaerror', 'HTML filter attributes removal evasion -- varying case.'); - - // Works at least with IE6. - $f = filter_xss("", array('img')); - $this->assertNoNormalized($f, 'focus', 'HTML filter attributes removal evasion -- breaking with nulls.'); - - // Only whitelisted scheme names allowed in attributes. - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- no evasion.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- no quotes.'); - - // A bit like CVE-2006-0070. - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- no alert ;)'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- grave accents.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- rare attribute.'); - - $f = filter_xss('', array('table')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- another tag.'); - - $f = filter_xss('', array('base')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- one more attribute and tag.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- varying case.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- UTF-8 decimal encoding.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- long UTF-8 encoding.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- UTF-8 hex encoding.'); - - $f = filter_xss("", array('img')); - $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an embedded tab.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an encoded, embedded tab.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an encoded, embedded newline.'); - - // With this test would fail, but the entity gets turned into - // &#xD;, so it's OK. - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an encoded, embedded carriage return.'); - - $f = filter_xss("", array('img')); - $this->assertNoNormalized($f, 'cript', 'HTML scheme clearing evasion -- broken into many lines.'); - - $f = filter_xss("", array('img')); - $this->assertNoNormalized($f, 'cript', 'HTML scheme clearing evasion -- embedded nulls.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'vbscript', 'HTML scheme clearing evasion -- another scheme.'); - - $f = filter_xss('', array('img')); - $this->assertNoNormalized($f, 'nosuchscheme', 'HTML scheme clearing evasion -- unknown scheme.'); - - // Netscape 4.x javascript entities. - $f = filter_xss('
    ', array('br')); - $this->assertNoNormalized($f, 'alert', 'Netscape 4.x javascript entities.'); - - // DRUPAL-SA-2008-006: Invalid UTF-8, these only work as reflected XSS with - // Internet Explorer 6. - $f = filter_xss("

    \" style=\"background-image: url(javascript:alert(0));\"\xe0

    ", array('p')); - $this->assertNoNormalized($f, 'style', 'HTML filter -- invalid UTF-8.'); - - $f = filter_xss("\xc0aaa"); - $this->assertEqual($f, '', 'HTML filter -- overlong UTF-8 sequences.'); - - $f = filter_xss("Who's Online"); - $this->assertNormalized($f, "who's online", 'HTML filter -- html entity number'); - - $f = filter_xss("Who&#039;s Online"); - $this->assertNormalized($f, "who's online", 'HTML filter -- encoded html entity number'); - - $f = filter_xss("Who&amp;#039; Online"); - $this->assertNormalized($f, "who&#039; online", 'HTML filter -- double encoded html entity number'); - } /** * Tests filter settings, defaults, access restrictions and similar. @@ -382,21 +200,6 @@ class FilterUnitTest extends DrupalUnitTestBase { $this->assertNormalized($f, 'rel="nofollow"', 'Spam deterrent evasion -- with rel set - rel="nofollow" added.'); } - /** - * Tests the loose, admin HTML filter. - */ - function testFilterXSSAdmin() { - // DRUPAL-SA-2008-044 - $f = filter_xss_admin(''); - $this->assertNoNormalized($f, 'object', 'Admin HTML filter -- should not allow object tag.'); - - $f = filter_xss_admin('', + 'script', + 'HTML tag stripping -- simple script without special characters.', + ), + array( + '', + 'script', + 'HTML tag stripping evasion -- non whitespace character after tag name.', + ), + array( + '', + 'script', + 'HTML tag stripping evasion -- no space between tag and attribute.', + ), + // Null between < and tag name works at least with IE6. + array( + "<\0scr\0ipt>alert(0)", + 'ipt', + 'HTML tag stripping evasion -- breaking HTML with nulls.', + ), + array( + "", + 'script', + 'HTML tag stripping evasion -- filter just removing "script".', + ), + array( + '<', + 'script', + 'HTML tag stripping evasion -- double opening brackets.', + ), + array( + '', + 'script', + 'HTML tag stripping evasion -- a malformed image tag.', + array('img'), + ), + array( + '
    ', + 'script', + 'HTML tag stripping evasion -- script in a blockqoute.', + array('blockquote'), + ), + array( + "", + 'script', + 'HTML tag stripping evasion -- script within a comment.', + ), + // Dangerous attributes removal. + array( + '

    ', + 'onmouseover', + 'HTML filter attributes removal -- events, no evasion.', + array('p'), + ), + array( + '

  • ', + 'style', + 'HTML filter attributes removal -- style, no evasion.', + array('li'), + ), + array( + '', + 'onerror', + 'HTML filter attributes removal evasion -- spaces before equals sign.', + array('img'), + ), + array( + '', + 'onabort', + 'HTML filter attributes removal evasion -- non alphanumeric characters before equals sign.', + array('img'), + ), + array( + '', + 'onmediaerror', + 'HTML filter attributes removal evasion -- varying case.', + array('img'), + ), + // Works at least with IE6. + array( + "", + 'focus', + 'HTML filter attributes removal evasion -- breaking with nulls.', + array('img'), + ), + // Only whitelisted scheme names allowed in attributes. + array( + '', + 'javascript', + 'HTML scheme clearing -- no evasion.', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- no quotes.', + array('img'), + ), + // A bit like CVE-2006-0070. + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- no alert ;)', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- grave accents.', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing -- rare attribute.', + array('img'), + ), + array( + '
  • ', + 'javascript', + 'HTML scheme clearing -- another tag.', + array('table'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing -- one more attribute and tag.', + array('base'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- varying case.', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- UTF-8 decimal encoding.', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- long UTF-8 encoding.', + array('img'), + ), + array( + '', + 'javascript', + 'HTML scheme clearing evasion -- UTF-8 hex encoding.', + array('img'), + ), + array( + "", + 'script', + 'HTML scheme clearing evasion -- an embedded tab.', + array('img'), + ), + array( + '', + 'script', + 'HTML scheme clearing evasion -- an encoded, embedded tab.', + array('img'), + ), + array( + '', + 'script', + 'HTML scheme clearing evasion -- an encoded, embedded newline.', + array('img'), + ), + // With this test would fail, but the entity gets turned into + // &#xD;, so it's OK. + array( + '', + 'script', + 'HTML scheme clearing evasion -- an encoded, embedded carriage return.', + array('img'), + ), + array( + "", + 'cript', + 'HTML scheme clearing evasion -- broken into many lines.', + array('img'), + ), + array( + "", + 'cript', + 'HTML scheme clearing evasion -- embedded nulls.', + array('img'), + ), + array( + '', + 'vbscript', + 'HTML scheme clearing evasion -- another scheme.', + array('img'), + ), + array( + '', + 'nosuchscheme', + 'HTML scheme clearing evasion -- unknown scheme.', + array('img'), + ), + // Netscape 4.x javascript entities. + array( + '
    ', + 'alert', + 'Netscape 4.x javascript entities.', + array('br'), + ), + // DRUPAL-SA-2008-006: Invalid UTF-8, these only work as reflected XSS with + // Internet Explorer 6. + array( + "

    \" style=\"background-image: url(javascript:alert(0));\"\xe0

    ", + 'style', + 'HTML filter -- invalid UTF-8.', + array('p'), + ), + ); + // @fixme This dataset currently fails under 5.4 because of + // https://drupal.org/node/1210798 . Restore after its fixed. + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $cases[] = array( + '', + 'javascript', + 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.', + array('img'), + ); + } + return $cases; + } + + /** + * Checks that invalid multi-byte sequences are rejected. + * + * @param string $value + * The value to filter. + * @param string $expected + * The expected result. + * @param string $message + * The assertion message to display upon failure. + * + * @dataProvider providerTestInvalidMultiByte + */ + public function testInvalidMultiByte($value, $expected, $message) { + $this->assertEquals(Xss::filter($value), $expected, $message); + } + + /** + * Data provider for testInvalidMultiByte(). + * + * @see testInvalidMultiByte() + * + * @return array + * An array of arrays containing strings: + * - The value to filter. + * - The value to expect after filtering. + * - The assertion message. + */ + public function providerTestInvalidMultiByte() { + return array( + array("Foo\xC0barbaz", '', 'Xss::filter() accepted invalid sequence "Foo\xC0barbaz"'), + array("Fooÿñ", "Fooÿñ", 'Xss::filter() rejects valid sequence Fooÿñ"'), + array("\xc0aaa", '', 'HTML filter -- overlong UTF-8 sequences.'), + ); + } + + /** + * Checks that strings starting with a question sign are correctly processed. + */ + public function testQuestionSign() { + $value = Xss::filter(''); + $this->assertTrue(stripos($value, '