From fa1da3f252f66869f9ac7b06d02eb32181388564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?= Date: Fri, 15 Mar 2024 08:59:36 +0000 Subject: [PATCH 1/2] Editor toolbar: Load preferences for a new user is broken (#2431) relates to xibosignage/xibo#3371 --- ui/src/editor-core/toolbar.js | 3 +-- ui/src/layout-editor/main.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/src/editor-core/toolbar.js b/ui/src/editor-core/toolbar.js index 203fc5b273..964f5cd9f5 100644 --- a/ui/src/editor-core/toolbar.js +++ b/ui/src/editor-core/toolbar.js @@ -592,8 +592,7 @@ Toolbar.prototype.loadPrefs = function() { type: linkToAPI.type, }).done(function(res) { if (res.success) { - const loadedData = JSON.parse(res.data.value); - + const loadedData = JSON.parse(res.data.value ?? '{}'); const findMenuIndexByName = function(name) { let foundMenu = -1; diff --git a/ui/src/layout-editor/main.js b/ui/src/layout-editor/main.js index b51317a6fb..31118362bd 100644 --- a/ui/src/layout-editor/main.js +++ b/ui/src/layout-editor/main.js @@ -4424,7 +4424,7 @@ lD.loadPrefs = function() { type: linkToAPI.type, }).done(function(res) { if (res.success) { - const loadedData = JSON.parse(res.data.value); + const loadedData = JSON.parse(res.data.value ?? '{}'); if (loadedData.snapOptions) { self.viewer.moveableOptions = loadedData.snapOptions; From 49f018fd9fe64fcd417d7c2ef96078bd7b2b88b7 Mon Sep 17 00:00:00 2001 From: Dan Garner Date: Mon, 18 Mar 2024 12:40:49 +0000 Subject: [PATCH 2/2] Improvements to filtering IP and sessions (#2433) * Sessions: Add sanitization in getIp() and disable output of session ID in session grid. xibosignage/xibo#3375 * Bump to 4.0.9 --- lib/Controller/Sessions.php | 30 ++++++++++--------------- lib/Factory/SessionFactory.php | 30 +++++++++++++------------ lib/Helper/Environment.php | 2 +- lib/Helper/Session.php | 8 +++---- lib/Xmds/Soap.php | 2 +- views/sessions-form-confirm-logout.twig | 2 +- 6 files changed, 35 insertions(+), 39 deletions(-) diff --git a/lib/Controller/Sessions.php b/lib/Controller/Sessions.php index 4a3418fb13..5e57c31af3 100644 --- a/lib/Controller/Sessions.php +++ b/lib/Controller/Sessions.php @@ -96,6 +96,11 @@ public function grid(Request $request, Response $response): Response|\Psr\Http\M if (!$this->isApi($request) && $this->getUser()->isSuperAdmin()) { $row->includeProperty('buttons'); + // No buttons on expired sessions + if ($row->isExpired == 1) { + continue; + } + // logout, current user/session if ($row->userId === $this->getUser()->userId && session_id() === $row->sessionId) { $url = $this->urlFor($request, 'logout'); @@ -104,7 +109,7 @@ public function grid(Request $request, Response $response): Response|\Psr\Http\M $url = $this->urlFor( $request, 'sessions.confirm.logout.form', - ['id' => $row->sessionId] + ['id' => $row->userId] ); } @@ -127,13 +132,13 @@ public function grid(Request $request, Response $response): Response|\Psr\Http\M * Confirm Logout Form * @param Request $request * @param Response $response - * @param $id + * @param int $id The UserID * @return \Psr\Http\Message\ResponseInterface|Response * @throws AccessDeniedException * @throws \Xibo\Support\Exception\ControllerNotImplemented * @throws \Xibo\Support\Exception\GeneralException */ - function confirmLogoutForm(Request $request, Response $response, $id) + public function confirmLogoutForm(Request $request, Response $response, $id) { if ($this->getUser()->userTypeId != 1) { throw new AccessDeniedException(); @@ -141,7 +146,7 @@ function confirmLogoutForm(Request $request, Response $response, $id) $this->getState()->template = 'sessions-form-confirm-logout'; $this->getState()->setData([ - 'sessionId' => $id, + 'userId' => $id, ]); return $this->render($request, $response); @@ -158,25 +163,14 @@ function confirmLogoutForm(Request $request, Response $response, $id) * @throws \Xibo\Support\Exception\GeneralException * @throws \Xibo\Support\Exception\NotFoundException */ - function logout(Request $request, Response $response, $id) + public function logout(Request $request, Response $response, $id) { if ($this->getUser()->userTypeId != 1) { throw new AccessDeniedException(); } - $session = $this->sessionFactory->getById($id); - - if ($session->userId != 0) { - $this->store->update( - 'UPDATE `session` SET IsExpired = 1 WHERE userID = :userId ', - ['userId' => $session->userId] - ); - } else { - $this->store->update( - 'UPDATE `session` SET IsExpired = 1 WHERE session_id = :session_id ', - ['session_id' => $id] - ); - } + // We log out all of this user's sessions. + $this->sessionFactory->expireByUserId($id); // Return $this->getState()->hydrate([ diff --git a/lib/Factory/SessionFactory.php b/lib/Factory/SessionFactory.php index 5626d82178..fe3023255c 100644 --- a/lib/Factory/SessionFactory.php +++ b/lib/Factory/SessionFactory.php @@ -1,8 +1,8 @@ query(null, ['sessionId' => $sessionId]); - - if (count($session) <= 0) - throw new NotFoundException(); - - return $session[0]; + $this->getStore()->update( + 'UPDATE `session` SET IsExpired = 1 WHERE userID = :userId ', + ['userId' => $userId] + ); } /** @@ -143,7 +138,14 @@ public function query($sortOrder = null, $filterBy = []) foreach ($this->getStore()->select($sql, $params) as $row) { - $entries[] = $this->createEmpty()->hydrate($row, ['stringProperties' => ['sessionId']]); + $session = $this->createEmpty()->hydrate($row, [ + 'stringProperties' => ['sessionId'], + 'intProperties' => ['isExpired'], + ]); + $session->userAgent = htmlspecialchars($session->userAgent); + $session->remoteAddress = filter_var($session->remoteAddress, FILTER_VALIDATE_IP); + $session->excludeProperty('sessionId'); + $entries[] = $session; } // Paging diff --git a/lib/Helper/Environment.php b/lib/Helper/Environment.php index 0599ebab02..694419c795 100644 --- a/lib/Helper/Environment.php +++ b/lib/Helper/Environment.php @@ -30,7 +30,7 @@ */ class Environment { - public static $WEBSITE_VERSION_NAME = '4.0.8'; + public static $WEBSITE_VERSION_NAME = '4.0.9'; public static $XMDS_VERSION = '7'; public static $XLF_VERSION = 4; public static $VERSION_REQUIRED = '8.1.0'; diff --git a/lib/Helper/Session.php b/lib/Helper/Session.php index f68ed739ca..c38485df13 100644 --- a/lib/Helper/Session.php +++ b/lib/Helper/Session.php @@ -1,6 +1,6 @@ key = $key; - $userAgent = substr($_SERVER['HTTP_USER_AGENT'], 0, 253); + $userAgent = substr(htmlspecialchars($_SERVER['HTTP_USER_AGENT']), 0, 253); try { $dbh = $this->getDb(); @@ -422,7 +422,7 @@ private function insertSession($key, $data, $lastAccessed, $expiry) 'lastAccessed' => Carbon::createFromTimestamp($lastAccessed)->format(DateFormatHelper::getSystemFormat()), 'userId' => $this->userId, 'expired' => ($this->expired) ? 1 : 0, - 'useragent' => substr($_SERVER['HTTP_USER_AGENT'], 0, 253), + 'useragent' => substr(htmlspecialchars($_SERVER['HTTP_USER_AGENT']), 0, 253), 'remoteaddr' => $this->getIp() ]; @@ -471,7 +471,7 @@ private function getIp() $clientIp = ''; $keys = array('X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP', 'REMOTE_ADDR'); foreach ($keys as $key) { - if (isset($_SERVER[$key])) { + if (isset($_SERVER[$key]) && filter_var($_SERVER[$key], FILTER_VALIDATE_IP) !== false) { $clientIp = $_SERVER[$key]; break; } diff --git a/lib/Xmds/Soap.php b/lib/Xmds/Soap.php index 582906967b..c33687bce0 100644 --- a/lib/Xmds/Soap.php +++ b/lib/Xmds/Soap.php @@ -2640,7 +2640,7 @@ protected function getIp() $keys = array('X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP', 'REMOTE_ADDR'); foreach ($keys as $key) { - if (isset($_SERVER[$key])) { + if (isset($_SERVER[$key]) && filter_var($_SERVER[$key], FILTER_VALIDATE_IP) !== false) { $clientIp = $_SERVER[$key]; break; } diff --git a/views/sessions-form-confirm-logout.twig b/views/sessions-form-confirm-logout.twig index 9eab988755..4aa376443a 100644 --- a/views/sessions-form-confirm-logout.twig +++ b/views/sessions-form-confirm-logout.twig @@ -36,7 +36,7 @@ {% block formHtml %}
-
+ {% set message %}{% trans "Are you sure you want to logout this user?" %}{% endset %} {{ forms.message(message) }}