', array('table'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- another tag.');
-
- $f = Xss::filter('', array('base'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing -- one more attribute and tag.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- varying case.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- UTF-8 decimal encoding.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- long UTF-8 encoding.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- UTF-8 hex encoding.');
-
- $f = Xss::filter("", array('img'));
- $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an embedded tab.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an encoded, embedded tab.');
-
- $f = Xss::filter('', 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
- // 
, so it's OK.
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'script', 'HTML scheme clearing evasion -- an encoded, embedded carriage return.');
-
- $f = Xss::filter("", array('img'));
- $this->assertNoNormalized($f, 'cript', 'HTML scheme clearing evasion -- broken into many lines.');
-
- $f = Xss::filter("", array('img'));
- $this->assertNoNormalized($f, 'cript', 'HTML scheme clearing evasion -- embedded nulls.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'javascript', 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'vbscript', 'HTML scheme clearing evasion -- another scheme.');
-
- $f = Xss::filter('', array('img'));
- $this->assertNoNormalized($f, 'nosuchscheme', 'HTML scheme clearing evasion -- unknown scheme.');
-
- // Netscape 4.x javascript entities.
- $f = Xss::filter('
', array('br'));
- $this->assertNoNormalized($f, 'alert', 'Netscape 4.x javascript entities.');
+ public function testFilterXssNormalized($value, $expected, $message) {
+ $this->assertNormalized($expected, Xss::filter($value), $message);
+ }
- // DRUPAL-SA-2008-006: Invalid UTF-8, these only work as reflected XSS with
- // Internet Explorer 6.
- $f = Xss::filter("\" style=\"background-image: url(javascript:alert(0));\"\xe0
", array('p'));
- $this->assertNoNormalized($f, 'style', 'HTML filter -- invalid UTF-8.');
+ /**
+ * Data provider for testFilterXssNormalized().
+ *
+ * @see testFilterXssNormalized()
+ *
+ * @return array
+ * An array of arrays containing strings:
+ * - The value to filter.
+ * - The value to expect after filtering.
+ * - The assertion message.
+ */
+ public function providerTestFilterXssNormalized() {
+ return array(
+ array(
+ "\xc0aaa",
+ '',
+ 'HTML filter -- overlong UTF-8 sequences.',
+ ),
+ array(
+ "Who's Online",
+ "who's online",
+ 'HTML filter -- html entity number',
+ ),
+ array(
+ "Who's Online",
+ "who's online",
+ 'HTML filter -- encoded html entity number',
+ ),
+ );
+ }
- $f = Xss::filter("\xc0aaa");
- $this->assertEquals($f, '', 'HTML filter -- overlong UTF-8 sequences.');
+ /**
+ * 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.
+ *
+ * @param string $value
+ * The value to filter.
+ * @param string $expected
+ * The expected result.
+ * @param string $message
+ * The assertion message to display upon failure.
+ * @param array $allowed_tags
+ * (Optional) The allowed tags to be passed on Xss::filter().
+ *
+ * @dataProvider providerTestFilterXssNotNormalized
+ */
+ public function testFilterXssNotNormalized($value, $expected, $message, array $allowed_tags = NULL) {
+ if ($allowed_tags === NULL) {
+ $value = Xss::filter($value);
+ }
+ else {
+ $value = Xss::filter($value, $allowed_tags);
+ }
+ $this->assertNotNormalized($expected, $value, $message);
+ }
- $f = Xss::filter("Who's Online");
- $this->assertNormalized($f, "who's online", 'HTML filter -- html entity number');
+ /**
+ * Data provider for testFilterXssNotNormalized().
+ *
+ * @see testFilterXssNotNormalized()
+ *
+ * @return array
+ * An array of arrays containing the following elements:
+ * - The value to filter string.
+ * - The value to expect after filtering string.
+ * - The assertion message string.
+ * - (optional) The allowed html tags array that should be passed to
+ * Xss::filter().
+ */
+ public function providerTestFilterXssNotNormalized() {
+ return array(
+ // Tag stripping, different ways to work around removal of HTML tags.
+ array(
+ '',
+ 'script',
+ 'HTML tag stripping -- simple script without special characters.',
+ ),
+ array(
+ '',
+ 'script',
+ 'HTML tag stripping -- empty script with source.',
+ ),
+ 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
+ // 
, 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(
+ '',
+ 'javascript',
+ 'HTML scheme clearing evasion -- spaces and metacharacters before scheme.',
+ 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'),
+ ),
+ );
+ }
- $f = Xss::filter("Who's Online");
- $this->assertNormalized($f, "who's online", 'HTML filter -- encoded html entity number');
+ /**
+ * 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($expected, Xss::filter($value), $message);
+ }
- $f = Xss::filter("Who&#039; Online");
- $this->assertNormalized($f, "who' online", 'HTML filter -- double encoded html entity number');
+ /**
+ * 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 invalid multi-byte sequences are rejected.
+ * Checks that strings starting with a question sign are correctly processed.
*/
- public function testInvalidMultiByte() {
- $text = Xss::filter("Foo\xC0barbaz");
- $this->assertEquals($text, '', 'filter_xss() accepted invalid sequence "Foo\xC0barbaz"');
- $text = Xss::filter("Fooÿñ");
- $this->assertEquals($text, "Fooÿñ", 'filter_xss() rejects valid sequence Fooÿñ');
+ public function testQuestionSign() {
+ $value = Xss::filter('');
+ $this->assertTrue(stripos($value, 'assertTrue(strpos(strtolower(String::decodeEntities($haystack)), $needle) === FALSE, $message, $group);
}