aboutsummaryrefslogtreecommitdiffhomepage
path: root/application
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-10-06 17:30:18 +0200
committerArthurHoaro <arthur@hoa.ro>2020-10-06 17:30:18 +0200
commit72fbbcd6794facea2cf06d9742359d190257b00f (patch)
treea4d6f446ec861f9a7591edb31f322e2a846b2bac /application
parentdf25b28dcd3cde54d42c18a55a810daa82bf5727 (diff)
downloadShaarli-72fbbcd6794facea2cf06d9742359d190257b00f.tar.gz
Shaarli-72fbbcd6794facea2cf06d9742359d190257b00f.tar.zst
Shaarli-72fbbcd6794facea2cf06d9742359d190257b00f.zip
Security: fix multiple XSS vulnerabilities + fix search tags with special chars
XSS vulnerabilities fixed in editlink, linklist, tag.cloud and tag.list. Also fixed tag search with special characters: urlencode function needs to be applied on raw data, before espaping, otherwise the rendered URL is wrong.
Diffstat (limited to 'application')
-rw-r--r--application/Utils.php4
-rw-r--r--application/formatter/BookmarkFormatter.php26
-rw-r--r--application/front/controller/admin/ManageShaareController.php10
-rw-r--r--application/front/controller/admin/ManageTagController.php4
-rw-r--r--application/front/controller/visitor/BookmarkListController.php7
-rw-r--r--application/front/controller/visitor/TagCloudController.php12
-rw-r--r--application/render/PageBuilder.php2
7 files changed, 50 insertions, 15 deletions
diff --git a/application/Utils.php b/application/Utils.php
index 9c9eaaa2..bcfda65c 100644
--- a/application/Utils.php
+++ b/application/Utils.php
@@ -95,14 +95,14 @@ function escape($input)
95 return null; 95 return null;
96 } 96 }
97 97
98 if (is_bool($input)) { 98 if (is_bool($input) || is_int($input) || is_float($input) || $input instanceof DateTimeInterface) {
99 return $input; 99 return $input;
100 } 100 }
101 101
102 if (is_array($input)) { 102 if (is_array($input)) {
103 $out = array(); 103 $out = array();
104 foreach ($input as $key => $value) { 104 foreach ($input as $key => $value) {
105 $out[$key] = escape($value); 105 $out[escape($key)] = escape($value);
106 } 106 }
107 return $out; 107 return $out;
108 } 108 }
diff --git a/application/formatter/BookmarkFormatter.php b/application/formatter/BookmarkFormatter.php
index 22ba7aae..0042dafe 100644
--- a/application/formatter/BookmarkFormatter.php
+++ b/application/formatter/BookmarkFormatter.php
@@ -58,7 +58,9 @@ abstract class BookmarkFormatter
58 $out['title'] = $this->formatTitle($bookmark); 58 $out['title'] = $this->formatTitle($bookmark);
59 $out['description'] = $this->formatDescription($bookmark); 59 $out['description'] = $this->formatDescription($bookmark);
60 $out['thumbnail'] = $this->formatThumbnail($bookmark); 60 $out['thumbnail'] = $this->formatThumbnail($bookmark);
61 $out['urlencoded_taglist'] = $this->formatUrlEncodedTagList($bookmark);
61 $out['taglist'] = $this->formatTagList($bookmark); 62 $out['taglist'] = $this->formatTagList($bookmark);
63 $out['urlencoded_tags'] = $this->formatUrlEncodedTagString($bookmark);
62 $out['tags'] = $this->formatTagString($bookmark); 64 $out['tags'] = $this->formatTagString($bookmark);
63 $out['sticky'] = $bookmark->isSticky(); 65 $out['sticky'] = $bookmark->isSticky();
64 $out['private'] = $bookmark->isPrivate(); 66 $out['private'] = $bookmark->isPrivate();
@@ -182,6 +184,18 @@ abstract class BookmarkFormatter
182 } 184 }
183 185
184 /** 186 /**
187 * Format Url Encoded Tags
188 *
189 * @param Bookmark $bookmark instance
190 *
191 * @return array formatted Tags
192 */
193 protected function formatUrlEncodedTagList($bookmark)
194 {
195 return array_map('urlencode', $this->filterTagList($bookmark->getTags()));
196 }
197
198 /**
185 * Format TagString 199 * Format TagString
186 * 200 *
187 * @param Bookmark $bookmark instance 201 * @param Bookmark $bookmark instance
@@ -194,6 +208,18 @@ abstract class BookmarkFormatter
194 } 208 }
195 209
196 /** 210 /**
211 * Format TagString
212 *
213 * @param Bookmark $bookmark instance
214 *
215 * @return string formatted TagString
216 */
217 protected function formatUrlEncodedTagString($bookmark)
218 {
219 return implode(' ', $this->formatUrlEncodedTagList($bookmark));
220 }
221
222 /**
197 * Format Class 223 * Format Class
198 * Used to add specific CSS class for a link 224 * Used to add specific CSS class for a link
199 * 225 *
diff --git a/application/front/controller/admin/ManageShaareController.php b/application/front/controller/admin/ManageShaareController.php
index 59ba2de9..bb083486 100644
--- a/application/front/controller/admin/ManageShaareController.php
+++ b/application/front/controller/admin/ManageShaareController.php
@@ -78,13 +78,13 @@ class ManageShaareController extends ShaarliAdminController
78 $title = $this->container->conf->get('general.default_note_title', t('Note: ')); 78 $title = $this->container->conf->get('general.default_note_title', t('Note: '));
79 } 79 }
80 80
81 $link = escape([ 81 $link = [
82 'title' => $title, 82 'title' => $title,
83 'url' => $url ?? '', 83 'url' => $url ?? '',
84 'description' => $description ?? '', 84 'description' => $description ?? '',
85 'tags' => $tags ?? '', 85 'tags' => $tags ?? '',
86 'private' => $private, 86 'private' => $private,
87 ]); 87 ];
88 } else { 88 } else {
89 $formatter = $this->container->formatterFactory->getFormatter('raw'); 89 $formatter = $this->container->formatterFactory->getFormatter('raw');
90 $link = $formatter->format($bookmark); 90 $link = $formatter->format($bookmark);
@@ -345,14 +345,14 @@ class ManageShaareController extends ShaarliAdminController
345 $tags[BookmarkMarkdownFormatter::NO_MD_TAG] = 1; 345 $tags[BookmarkMarkdownFormatter::NO_MD_TAG] = 1;
346 } 346 }
347 347
348 $data = [ 348 $data = escape([
349 'link' => $link, 349 'link' => $link,
350 'link_is_new' => $isNew, 350 'link_is_new' => $isNew,
351 'http_referer' => escape($this->container->environment['HTTP_REFERER'] ?? ''), 351 'http_referer' => $this->container->environment['HTTP_REFERER'] ?? '',
352 'source' => $request->getParam('source') ?? '', 352 'source' => $request->getParam('source') ?? '',
353 'tags' => $tags, 353 'tags' => $tags,
354 'default_private_links' => $this->container->conf->get('privacy.default_private_links', false), 354 'default_private_links' => $this->container->conf->get('privacy.default_private_links', false),
355 ]; 355 ]);
356 356
357 $this->executePageHooks('render_editlink', $data, TemplatePage::EDIT_LINK); 357 $this->executePageHooks('render_editlink', $data, TemplatePage::EDIT_LINK);
358 358
diff --git a/application/front/controller/admin/ManageTagController.php b/application/front/controller/admin/ManageTagController.php
index 0380ef1f..2065c3e2 100644
--- a/application/front/controller/admin/ManageTagController.php
+++ b/application/front/controller/admin/ManageTagController.php
@@ -41,8 +41,8 @@ class ManageTagController extends ShaarliAdminController
41 41
42 $isDelete = null !== $request->getParam('deletetag') && null === $request->getParam('renametag'); 42 $isDelete = null !== $request->getParam('deletetag') && null === $request->getParam('renametag');
43 43
44 $fromTag = escape(trim($request->getParam('fromtag') ?? '')); 44 $fromTag = trim($request->getParam('fromtag') ?? '');
45 $toTag = escape(trim($request->getParam('totag') ?? '')); 45 $toTag = trim($request->getParam('totag') ?? '');
46 46
47 if (0 === strlen($fromTag) || false === $isDelete && 0 === strlen($toTag)) { 47 if (0 === strlen($fromTag) || false === $isDelete && 0 === strlen($toTag)) {
48 $this->saveWarningMessage(t('Invalid tags provided.')); 48 $this->saveWarningMessage(t('Invalid tags provided.'));
diff --git a/application/front/controller/visitor/BookmarkListController.php b/application/front/controller/visitor/BookmarkListController.php
index 2988bee6..18368751 100644
--- a/application/front/controller/visitor/BookmarkListController.php
+++ b/application/front/controller/visitor/BookmarkListController.php
@@ -34,7 +34,7 @@ class BookmarkListController extends ShaarliVisitorController
34 $formatter = $this->container->formatterFactory->getFormatter(); 34 $formatter = $this->container->formatterFactory->getFormatter();
35 $formatter->addContextData('base_path', $this->container->basePath); 35 $formatter->addContextData('base_path', $this->container->basePath);
36 36
37 $searchTags = escape(normalize_spaces($request->getParam('searchtags') ?? '')); 37 $searchTags = normalize_spaces($request->getParam('searchtags') ?? '');
38 $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));; 38 $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));;
39 39
40 // Filter bookmarks according search parameters. 40 // Filter bookmarks according search parameters.
@@ -104,8 +104,9 @@ class BookmarkListController extends ShaarliVisitorController
104 'page_current' => $page, 104 'page_current' => $page,
105 'page_max' => $pageCount, 105 'page_max' => $pageCount,
106 'result_count' => count($linksToDisplay), 106 'result_count' => count($linksToDisplay),
107 'search_term' => $searchTerm, 107 'search_term' => escape($searchTerm),
108 'search_tags' => $searchTags, 108 'search_tags' => escape($searchTags),
109 'search_tags_url' => array_map('urlencode', explode(' ', $searchTags)),
109 'visibility' => $visibility, 110 'visibility' => $visibility,
110 'links' => $linkDisp, 111 'links' => $linkDisp,
111 ] 112 ]
diff --git a/application/front/controller/visitor/TagCloudController.php b/application/front/controller/visitor/TagCloudController.php
index f9c529bc..76ed7690 100644
--- a/application/front/controller/visitor/TagCloudController.php
+++ b/application/front/controller/visitor/TagCloudController.php
@@ -66,10 +66,18 @@ class TagCloudController extends ShaarliVisitorController
66 $tags = $this->formatTagsForCloud($tags); 66 $tags = $this->formatTagsForCloud($tags);
67 } 67 }
68 68
69 $tagsUrl = [];
70 foreach ($tags as $tag => $value) {
71 $tagsUrl[escape($tag)] = urlencode((string) $tag);
72 }
73
69 $searchTags = implode(' ', escape($filteringTags)); 74 $searchTags = implode(' ', escape($filteringTags));
75 $searchTagsUrl = urlencode(implode(' ', $filteringTags));
70 $data = [ 76 $data = [
71 'search_tags' => $searchTags, 77 'search_tags' => escape($searchTags),
72 'tags' => $tags, 78 'search_tags_url' => $searchTagsUrl,
79 'tags' => escape($tags),
80 'tags_url' => $tagsUrl,
73 ]; 81 ];
74 $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type); 82 $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type);
75 $this->assignAllView($data); 83 $this->assignAllView($data);
diff --git a/application/render/PageBuilder.php b/application/render/PageBuilder.php
index c52e3b76..41b357dd 100644
--- a/application/render/PageBuilder.php
+++ b/application/render/PageBuilder.php
@@ -137,7 +137,7 @@ class PageBuilder
137 $this->tpl->assign('language', $this->conf->get('translation.language')); 137 $this->tpl->assign('language', $this->conf->get('translation.language'));
138 138
139 if ($this->bookmarkService !== null) { 139 if ($this->bookmarkService !== null) {
140 $this->tpl->assign('tags', $this->bookmarkService->bookmarksCountPerTag()); 140 $this->tpl->assign('tags', escape($this->bookmarkService->bookmarksCountPerTag()));
141 } 141 }
142 142
143 $this->tpl->assign( 143 $this->tpl->assign(