From bbd1384acbe7e52c21f89af69f2dc391c95dbf54 Mon Sep 17 00:00:00 2001 From: PercussiveElbow Date: Tue, 27 Oct 2020 01:34:51 +0000 Subject: [PATCH] XSS and redirect fixes with test cases --- app/Entities/Managers/PageContent.php | 18 ++++++++ tests/Entity/PageContentTest.php | 66 +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/app/Entities/Managers/PageContent.php b/app/Entities/Managers/PageContent.php index a787e5d99..7338a36b3 100644 --- a/app/Entities/Managers/PageContent.php +++ b/app/Entities/Managers/PageContent.php @@ -296,6 +296,24 @@ class PageContent $scriptElem->parentNode->removeChild($scriptElem); } + // Remove clickable links to JavaScript URI + $badLinks = $xPath->query('//*[contains(@href, \'javascript:\')]'); + foreach ($badLinks as $badLink) { + $badLink->parentNode->removeChild($badLink); + } + + // Remove forms with calls to JavaScript URI + $badForms = $xPath->query('//*[contains(@action, \'javascript:\')] | //*[contains(@formaction, \'javascript:\')]'); + foreach ($badForms as $badForm) { + $badForm->parentNode->removeChild($badForm); + } + + // Remove meta tag to prevent external redirects + $metaTags = $xPath->query('//meta[contains(@content, \'url\')]'); + foreach ($metaTags as $metaTag) { + $metaTag->parentNode->removeChild($metaTag); + } + // Remove data or JavaScript iFrames $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]'); foreach ($badIframes as $badIframe) { diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php index 99547fd17..e97df2c7e 100644 --- a/tests/Entity/PageContentTest.php +++ b/tests/Entity/PageContentTest.php @@ -159,6 +159,72 @@ class PageContentTest extends TestCase } + public function test_javascript_uri_links_are_removed() + { + $checks = [ + ''); + $pageView->assertElementNotContains('.page-content', 'href=javascript:'); + } + } + public function test_form_actions_with_javascript_are_removed() + { + $checks = [ + '
', + '
', + '
' + ]; + + $this->asEditor(); + $page = Page::first(); + + foreach ($checks as $check) { + $page->html = $check; + $page->save(); + + $pageView = $this->get($page->getUrl()); + $pageView->assertStatus(200); + $pageView->assertElementNotContains('.page-content', '