aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Eilertsen <haraldei@anduin.net>2022-03-20 12:57:42 +0100
committerHarald Eilertsen <haraldei@anduin.net>2022-03-20 15:34:24 +0100
commit8c19ab8f9f47a522ad2b929495f3b5821efd2f34 (patch)
tree11b60be2ec18f48734665495353bc44424981d70
parent30ae198b898a987e0d934a0e049cc6811f500475 (diff)
downloadvolse-hubzilla-8c19ab8f9f47a522ad2b929495f3b5821efd2f34.tar.gz
volse-hubzilla-8c19ab8f9f47a522ad2b929495f3b5821efd2f34.tar.bz2
volse-hubzilla-8c19ab8f9f47a522ad2b929495f3b5821efd2f34.zip
Add helper to escape URLs.
The escaping makes the URL safe for display and for use in HTML element attributes (such as href="..." etc), but does not guarantee that the URL itself is valid after conversion. This should be good enough for mitigating XSS issues caused by injecting html or javascript into a URL. Also probably good enough for _most_ normal URLs, but there may be devils hidden in the details somewhere.
-rw-r--r--include/text.php12
-rw-r--r--tests/unit/AntiXSSTest.php20
2 files changed, 32 insertions, 0 deletions
diff --git a/include/text.php b/include/text.php
index 9a2ca1af4..0c806d009 100644
--- a/include/text.php
+++ b/include/text.php
@@ -114,6 +114,18 @@ function escape_tags($string) {
return (htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false));
}
+/**
+ * Escape URL's so they're safe for use in HTML and in HTML element attributes.
+ */
+function escape_url($input) {
+ if (empty($input)) {
+ return EMPTY_STR;
+ }
+
+ // This is a bit crude but seems to do the trick for now. It makes no
+ // guarantees that the URL is valid for use after escaping.
+ return htmlspecialchars($input, ENT_HTML5 | ENT_QUOTES);
+}
function z_input_filter($s,$type = 'text/bbcode',$allow_code = false) {
diff --git a/tests/unit/AntiXSSTest.php b/tests/unit/AntiXSSTest.php
index b45042a1e..09642726f 100644
--- a/tests/unit/AntiXSSTest.php
+++ b/tests/unit/AntiXSSTest.php
@@ -24,6 +24,26 @@ class AntiXSSTest extends TestCase {
$this->assertEquals("&lt;submit type=&quot;button&quot; onclick=&quot;alert('failed!');&quot; /&gt;", $escapedString);
}
+ /**
+ * @dataProvider urlTestProvider
+ */
+ public function testEscapeURL($url, $expected) : void {
+ $this->assertEquals($expected, escape_url($url));
+ }
+
+ public function urlTestProvider() : array {
+ return [
+ [
+ "https://example.com/settings/calendar/?f=&rpath=https://example.com/cdav/calendar'><script>alert('boom')</script>",
+ "https://example.com/settings/calendar/?f=&amp;rpath=https://example.com/cdav/calendar&apos;&gt;&lt;script&gt;alert(&apos;boom&apos;)&lt;/script&gt;"
+ ],
+ [
+ "settings/calendar/?f=&rpath=https://example.com'+accesskey=x+onclick=alert(/boom/);a='",
+ "settings/calendar/?f=&amp;rpath=https://example.com&apos;+accesskey=x+onclick=alert(/boom/);a=&apos;"
+ ],
+ ];
+ }
+
/**
*xmlify and unxmlify
*/