Added content filtering of tags with javascript or data in values attr

Case would be blocked by CSP but adding for cases where CSP may not be
active when content taken externally.

For #3636
This commit is contained in:
Dan Brown 2022-08-11 10:26:33 +01:00
parent 375abca1ee
commit 5f7cd735ea
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
2 changed files with 14 additions and 4 deletions

View File

@ -45,6 +45,11 @@ class HtmlContentFilter
$badIframes = $xPath->query('//*[' . static::xpathContains('@src', 'data:') . '] | //*[' . static::xpathContains('@src', 'javascript:') . '] | //*[@srcdoc]'); $badIframes = $xPath->query('//*[' . static::xpathContains('@src', 'data:') . '] | //*[' . static::xpathContains('@src', 'javascript:') . '] | //*[@srcdoc]');
static::removeNodes($badIframes); static::removeNodes($badIframes);
// Remove tags hiding JavaScript or data uris in values attribute.
// For example, SVG animate tag can exploit javascript in values.
$badValuesTags = $xPath->query('//*[' . static::xpathContains('@values', 'data:') . '] | //*[' . static::xpathContains('@values', 'javascript:') . ']');
static::removeNodes($badValuesTags);
// Remove elements with a xlink:href attribute // Remove elements with a xlink:href attribute
// Used in SVG but deprecated anyway, so we'll be a bit more heavy-handed here. // Used in SVG but deprecated anyway, so we'll be a bit more heavy-handed here.
$xlinkHrefAttributes = $xPath->query('//@*[contains(name(), \'xlink:href\')]'); $xlinkHrefAttributes = $xPath->query('//@*[contains(name(), \'xlink:href\')]');

View File

@ -325,11 +325,14 @@ class PageContentTest extends TestCase
$pageView->assertDontSee('abc123abc123'); $pageView->assertDontSee('abc123abc123');
} }
public function test_svg_xlink_hrefs_are_removed() public function test_svg_script_usage_is_removed()
{ {
$checks = [ $checks = [
'<svg id="test" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100"><a xlink:href="javascript:alert(document.domain)"><rect x="0" y="0" width="100" height="100" /></a></svg>', '<svg id="test" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100"><a xlink:href="javascript:alert(document.domain)"><rect x="0" y="0" width="100" height="100" /></a></svg>',
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><use xlink:href="data:application/xml;base64 ,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGRlZnM+CjxjaXJjbGUgaWQ9InRlc3QiIHI9IjAiIGN4PSIwIiBjeT0iMCIgc3R5bGU9ImZpbGw6ICNGMDAiPgo8c2V0IGF0dHJpYnV0ZU5hbWU9ImZpbGwiIGF0dHJpYnV0ZVR5cGU9IkNTUyIgb25iZWdpbj0nYWxlcnQoZG9jdW1lbnQuZG9tYWluKScKb25lbmQ9J2FsZXJ0KCJvbmVuZCIpJyB0bz0iIzAwRiIgYmVnaW49IjBzIiBkdXI9Ijk5OXMiIC8+CjwvY2lyY2xlPgo8L2RlZnM+Cjx1c2UgeGxpbms6aHJlZj0iI3Rlc3QiLz4KPC9zdmc+#test"/></svg>', '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><use xlink:href="data:application/xml;base64 ,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGRlZnM+CjxjaXJjbGUgaWQ9InRlc3QiIHI9IjAiIGN4PSIwIiBjeT0iMCIgc3R5bGU9ImZpbGw6ICNGMDAiPgo8c2V0IGF0dHJpYnV0ZU5hbWU9ImZpbGwiIGF0dHJpYnV0ZVR5cGU9IkNTUyIgb25iZWdpbj0nYWxlcnQoZG9jdW1lbnQuZG9tYWluKScKb25lbmQ9J2FsZXJ0KCJvbmVuZCIpJyB0bz0iIzAwRiIgYmVnaW49IjBzIiBkdXI9Ijk5OXMiIC8+CjwvY2lyY2xlPgo8L2RlZnM+Cjx1c2UgeGxpbms6aHJlZj0iI3Rlc3QiLz4KPC9zdmc+#test"/></svg>',
'<svg><animate href=#xss attributeName=href values=javascript:alert(1) /></svg>',
'<svg><animate href="#xss" attributeName="href" values="a;javascript:alert(1)" /></svg>',
'<svg><animate href="#xss" attributeName="href" values="a;data:alert(1)" /></svg>',
]; ];
$this->asEditor(); $this->asEditor();
@ -341,9 +344,11 @@ class PageContentTest extends TestCase
$pageView = $this->get($page->getUrl()); $pageView = $this->get($page->getUrl());
$pageView->assertStatus(200); $pageView->assertStatus(200);
$this->withHtml($pageView)->assertElementNotContains('.page-content', 'alert'); $html = $this->withHtml($pageView);
$this->withHtml($pageView)->assertElementNotContains('.page-content', 'xlink:href'); $html->assertElementNotContains('.page-content', 'alert');
$this->withHtml($pageView)->assertElementNotContains('.page-content', 'application/xml'); $html->assertElementNotContains('.page-content', 'xlink:href');
$html->assertElementNotContains('.page-content', 'application/xml');
$html->assertElementNotContains('.page-content', 'javascript');
} }
} }