CVE-2024-29022 (published 2024-04-12T21:15Z)

Xibo is an Open Source Digital Signage platform with a web content management system and Windows display player software. In affected versions some request headers are not correctly sanitised when stored in the session and display tables. These headers can be used to inject a malicious script into the session page to exfiltrate session IDs and User Agents. These session IDs / User Agents can subsequently be used to hijack active sessions. A malicious script can be injected into the display grid to exfiltrate information related to displays. Users should upgrade to version 3.3.10 or 4.0.9 which fix this issue. Customers who host their CMS with the Xibo Signage service have already received an upgrade or patch to resolve this issue regardless of the CMS version that they are running. Upgrading to a fixed version is necessary to remediate. Patches are available for earlier versions of Xibo CMS that are out of security support: 2.3 patch ebeccd000b51f00b9a25f56a2f252d6812ebf850.diff. 1.8 patch a81044e6ccdd92cc967e34c125bd8162432e51bc.diff. There are no known workarounds for this issue.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/dasgarner/xibo-cms
commit_details: repo_url: https://github.com/dasgarner/xibo-cms
author: Dan Garner
author_date: 2024-03-18 08:52:12+00:00
msg: Sessions: Add sanitization in getIp() and disable output of session ID in session grid.
repository: repo_url: https://github.com/dasgarner/xibo-cms
repo_name: dasgarner/xibo-cms
description: Xibo Content Management System
repo_language: PHP
owner: dasgarner
file_changes: filename: Sessions.php
change_type: ModificationType.MODIFY
diff: @@ -88,11 +88,11 @@ class Sessions extends Base
                 $row->includeProperty('buttons');
 
                 // Edit
-                $row->buttons[] = array(
+                /*$row->buttons[] = array(
                     'id' => 'sessions_button_logout',
                     'url' => $this->urlFor('sessions.confirm.logout.form', ['id' => $row->sessionId]),
                     'text' => __('Logout')
-                );
+                );*/
             }
         }
 

programming_language: PHP
filename: SessionFactory.php
change_type: ModificationType.MODIFY
diff: @@ -150,7 +150,14 @@ class SessionFactory extends BaseFactory
 
 
         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

programming_language: PHP
filename: Session.php
change_type: ModificationType.MODIFY
diff: @@ -170,7 +170,7 @@ class Session implements \SessionHandlerInterface
         $data = '';
         $this->key = $key;
 
-        $userAgent = substr($_SERVER['HTTP_USER_AGENT'], 0, 253);
+        $userAgent = substr(htmlspecialchars($_SERVER['HTTP_USER_AGENT']), 0, 253);
 
         try {
             $dbh = $this->getDb();
@@ -420,7 +420,7 @@ class Session implements \SessionHandlerInterface
             'lastAccessed' => date('Y-m-d H:i:s', $lastAccessed),
             '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()
         ];
 
@@ -469,7 +469,7 @@ class Session implements \SessionHandlerInterface
         $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;
             }

programming_language: PHP
filename: Soap.php
change_type: ModificationType.MODIFY
diff: @@ -1772,7 +1772,7 @@ class Soap
 
         $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;
             }

programming_language: PHP