Skip to content

Commit

Permalink
Added filter for xlink:href svg xss
Browse files Browse the repository at this point in the history
Simply remove all such attributes
  • Loading branch information
ssddanbrown committed Sep 3, 2021
1 parent 5e6092a commit 040997f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 6 deletions.
26 changes: 20 additions & 6 deletions app/Util/HtmlContentFilter.php
Expand Up @@ -2,6 +2,7 @@

namespace BookStack\Util;

use DOMAttr;
use DOMDocument;
use DOMNodeList;
use DOMXPath;
Expand Down Expand Up @@ -43,13 +44,14 @@ public static function removeScripts(string $html): string
$badIframes = $xPath->query('//*[' . static::xpathContains('@src', 'data:') . '] | //*[' . static::xpathContains('@src', 'javascript:') . '] | //*[@srcdoc]');
static::removeNodes($badIframes);

// Remove elements with a xlink:href attribute
// Used in SVG but deprecated anyway, so we'll be a bit more heavy-handed here.
$xlinkHrefAttributes = $xPath->query('//@*[contains(name(), \'xlink:href\')]');
static::removeAttributes($xlinkHrefAttributes);

// Remove 'on*' attributes
$onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
foreach ($onAttributes as $attr) {
/** @var \DOMAttr $attr */
$attrName = $attr->nodeName;
$attr->parentNode->removeAttribute($attrName);
}
static::removeAttributes($onAttributes);

$html = '';
$topElems = $doc->documentElement->childNodes->item(0)->childNodes;
Expand All @@ -72,12 +74,24 @@ protected static function xpathContains(string $property, string $value): string
}

/**
* Removed all of the given DOMNodes.
* Remove all the given DOMNodes.
*/
protected static function removeNodes(DOMNodeList $nodes): void
{
foreach ($nodes as $node) {
$node->parentNode->removeChild($node);
}
}

/**
* Remove all the given attribute nodes.
*/
protected static function removeAttributes(DOMNodeList $attrs): void
{
/** @var DOMAttr $attr */
foreach ($attrs as $attr) {
$attrName = $attr->nodeName;
$attr->parentNode->removeAttribute($attrName);
}
}
}
22 changes: 22 additions & 0 deletions tests/Entity/PageContentTest.php
Expand Up @@ -305,6 +305,28 @@ public function test_page_content_scripts_show_when_configured()
$pageView->assertDontSee('abc123abc123');
}

public function test_svg_xlink_hrefs_are_removed()
{
$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 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>'
];

$this->asEditor();
$page = Page::query()->first();

foreach ($checks as $check) {
$page->html = $check;
$page->save();

$pageView = $this->get($page->getUrl());
$pageView->assertStatus(200);
$pageView->assertElementNotContains('.page-content', 'alert');
$pageView->assertElementNotContains('.page-content', 'xlink:href');
$pageView->assertElementNotContains('.page-content', 'application/xml');
}
}

public function test_page_inline_on_attributes_show_if_configured()
{
$this->asEditor();
Expand Down

0 comments on commit 040997f

Please sign in to comment.