]> BookStack Code Mirror - bookstack/commitdiff
Added iframe JS and data url escaping
authorDan Brown <redacted>
Tue, 6 Aug 2019 20:08:24 +0000 (21:08 +0100)
committerDan Brown <redacted>
Tue, 6 Aug 2019 20:08:24 +0000 (21:08 +0100)
Related to #1531

app/Entities/Repos/EntityRepo.php
tests/Entity/PageContentTest.php

index aad9a1205895a18bfce0b0143ae244e2d9bffd51..7ca25b785286cb7f4e5e44ccbb4216c1c1881c4e 100644 (file)
@@ -765,6 +765,12 @@ class EntityRepo
             $scriptElem->parentNode->removeChild($scriptElem);
         }
 
             $scriptElem->parentNode->removeChild($scriptElem);
         }
 
+        // Remove data or JavaScript iFrames
+        $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')]');
+        foreach ($badIframes as $badIframe) {
+            $badIframe->parentNode->removeChild($badIframe);
+        }
+
         // Remove 'on*' attributes
         $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
         foreach ($onAttributes as $attr) {
         // Remove 'on*' attributes
         $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
         foreach ($onAttributes as $attr) {
index c80b5f1d96f1b9c85ec5bf281c42e7f0c3f17895..b447a7c5d87f73c39d87c14f22a3bbcb6c81b40c 100644 (file)
@@ -80,6 +80,7 @@ class PageContentTest extends TestCase
         $page->save();
 
         $pageView = $this->get($page->getUrl());
         $page->save();
 
         $pageView = $this->get($page->getUrl());
+        $pageView->assertStatus(200);
         $pageView->assertDontSee($script);
         $pageView->assertSee('abc123abc123');
     }
         $pageView->assertDontSee($script);
         $pageView->assertSee('abc123abc123');
     }
@@ -103,12 +104,42 @@ class PageContentTest extends TestCase
             $page->save();
 
             $pageView = $this->get($page->getUrl());
             $page->save();
 
             $pageView = $this->get($page->getUrl());
+            $pageView->assertStatus(200);
             $pageView->assertElementNotContains('.page-content', '<script>');
             $pageView->assertElementNotContains('.page-content', '</script>');
         }
 
     }
 
             $pageView->assertElementNotContains('.page-content', '<script>');
             $pageView->assertElementNotContains('.page-content', '</script>');
         }
 
     }
 
+    public function test_iframe_js_and_base64_urls_are_removed()
+    {
+        $checks = [
+            '<iframe src="javascript:alert(document.cookie)"></iframe>',
+            '<iframe SRC=" javascript: alert(document.cookie)"></iframe>',
+            '<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnaGVsbG8nKTwvc2NyaXB0Pg==" frameborder="0"></iframe>',
+            '<iframe src=" data:text/html;base64,PHNjcmlwdD5hbGVydCgnaGVsbG8nKTwvc2NyaXB0Pg==" frameborder="0"></iframe>',
+
+        ];
+
+        $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', '<iframe>');
+            $pageView->assertElementNotContains('.page-content', '</iframe>');
+            $pageView->assertElementNotContains('.page-content', 'src=');
+            $pageView->assertElementNotContains('.page-content', 'javascript:');
+            $pageView->assertElementNotContains('.page-content', 'data:');
+            $pageView->assertElementNotContains('.page-content', 'base64');
+        }
+
+    }
+
     public function test_page_inline_on_attributes_removed_by_default()
     {
         $this->asEditor();
     public function test_page_inline_on_attributes_removed_by_default()
     {
         $this->asEditor();
@@ -118,6 +149,7 @@ class PageContentTest extends TestCase
         $page->save();
 
         $pageView = $this->get($page->getUrl());
         $page->save();
 
         $pageView = $this->get($page->getUrl());
+        $pageView->assertStatus(200);
         $pageView->assertDontSee($script);
         $pageView->assertSee('<p>Hello</p>');
     }
         $pageView->assertDontSee($script);
         $pageView->assertSee('<p>Hello</p>');
     }
@@ -130,6 +162,7 @@ class PageContentTest extends TestCase
             '<div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div>',
             '<div><div><div><div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div></div></div></div>',
             '<div onclick="console.log(\'test\')">Lorem ipsum dolor sit amet.</div><p onclick="console.log(\'test\')">Hello</p><div></div>',
             '<div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div>',
             '<div><div><div><div>Lorem ipsum dolor sit amet.<p onclick="console.log(\'test\')">Hello</p></div></div></div></div>',
             '<div onclick="console.log(\'test\')">Lorem ipsum dolor sit amet.</div><p onclick="console.log(\'test\')">Hello</p><div></div>',
+            '<a a="<img src=1 onerror=\'alert(1)\'> ',
         ];
 
         $this->asEditor();
         ];
 
         $this->asEditor();
@@ -140,6 +173,7 @@ class PageContentTest extends TestCase
             $page->save();
 
             $pageView = $this->get($page->getUrl());
             $page->save();
 
             $pageView = $this->get($page->getUrl());
+            $pageView->assertStatus(200);
             $pageView->assertElementNotContains('.page-content', 'onclick');
         }
 
             $pageView->assertElementNotContains('.page-content', 'onclick');
         }