[TikiWiki-commits] [Git][tikiwiki/tiki][24.x] [FIX] Sanitize ORDER BY direction in performance stats to prevent SQL injection

"Alfred Syatsukwa \(@alfredsyatsukwa\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <6a84d1d44055b_38f2112461774@gitlab-sidekiq-low-urgency-cpu-bound-v2-789dc4448d-9ptkt.mail>

Alfred Syatsukwa pushed to branch 24.x at Tiki Wiki CMS Groupware / Tiki


Commits:
8e1e3bc1 by Alfred Syatsukwa at 2026-08-18T21:35:40+00:00
[FIX] Sanitize ORDER BY direction in performance stats to prevent SQL injection
---
* [FIX] Sanitize ORDER BY direction in performance stats to prevent SQL injection
---

See merge request tikiwiki/tiki!10964

(cherry picked from commit eaa564ccd8b374121e7e76c7f635054ec2b4d1a8)

See merge request tikiwiki/tiki!10965

- - - - -


6 changed files:

- lib/Logs/LogsQueryLib.php
- lib/core/Tracker/Query.php
- lib/filegals/filegallib.php
- lib/freetag/freetaglib.php
- lib/performance/performancestatslib.php
- tiki-performance_stats.php


Changes:

=====================================
lib/Logs/LogsQueryLib.php
=====================================
@@ -294,13 +294,10 @@ class LogsQueryLib
             " . ($this->groupType == "countByDate" ? " GROUP BY DATE_FORMAT(FROM_UNIXTIME(lastModif), '%Y%m%d') " : "") . "
 
             ORDER BY lastModif " . ($this->desc == true ? "DESC" : "ASC") . "
-
-            " . (! empty($this->limit) ?
-                " LIMIT " . $this->limit
-                : ""
-            ) . "
         ";
 
+        $numrows = ! empty($this->limit) ? (int)$this->limit : -1;
+
         $params = [$this->type];
 
         if (! empty($this->id)) {
@@ -322,7 +319,7 @@ class LogsQueryLib
         if ($this->groupType == "count") {
             return $tikilib->getOne($query, $params);
         } else {
-            return $tikilib->fetchAll($query, $params);
+            return $tikilib->fetchAll($query, $params, $numrows);
         }
     }
 }


=====================================
lib/core/Tracker/Query.php
=====================================
@@ -937,8 +937,10 @@ class Tracker_Query
                 " . ($isSearch == true ? ", search_item_fields.fieldId, search_item_fields.itemId " : "" ) . "
                 ORDER BY
                 tiki_tracker_items." . $dateUnit . " " . ($this->desc == true ? 'DESC' : 'ASC') . "
-                " . (! empty($this->limit) ? " LIMIT " . $this->limit : "") . "
-                " . (! empty($this->offset) ? " OFFSET " . $this->offset : "");
+                ";
+
+        $numrows = ! empty($this->limit) ? (int)$this->limit : -1;
+        $fetchOffset = ! empty($this->offset) ? (int)$this->offset : -1;
 
         if ($this->debug == true) {
             $result = [$query, $params];
@@ -946,7 +948,7 @@ class Tracker_Query
             print_r($tikilib->fetchAll($query, $params));
             die;
         } else {
-            $result = $tikilib->fetchAll($query, $params);
+            $result = $tikilib->fetchAll($query, $params, $numrows, $fetchOffset);
         }
 
         $newResult = [];


=====================================
lib/filegals/filegallib.php
=====================================
@@ -2853,10 +2853,9 @@ class FileGalLib extends TikiLib
             $numQuery = preg_replace("/^SELECT.*?FROM/", "SELECT COUNT(*) FROM", $query);
             $numQuery = preg_replace("/ ORDER BY .*$/", "", $numQuery);
             $numResults = $this->getOne($numQuery, $bindvars);
-            $limit = $offset == -1 ? 0 : $offset;
-            $limit .= ', ' . ($maxRecords == -1 ? PHP_INT_MAX : $maxRecords);
-            $query .= " LIMIT $limit";
-            $result = $this->fetchAll($query, $bindvars);
+            $fetchOffset = ($offset == -1) ? -1 : (int)$offset;
+            $fetchMaxRecords = ($maxRecords == -1) ? -1 : (int)$maxRecords;
+            $result = $this->fetchAll($query, $bindvars, $fetchMaxRecords, $fetchOffset);
         } else {
             $result = $this->fetchAll($query, $bindvars);
             $numResults = count($result);


=====================================
lib/freetag/freetaglib.php
=====================================
@@ -314,12 +314,11 @@ class FreetagLib extends ObjectLib
         $ret = [];
         $permMap = TikiLib::lib('object')->map_object_type_to_permission();
         while ($row = $result->fetchRow()) {
-
             if ($row['type'] == "trackeritem" && $prefs['feature_sefurl'] == 'y') {
                 $href = explode("&", $row['href']);
                 $row['href'] = $href[0];
             }
-            
+
             $ok = false;
             if ($row['type'] == 'blog post') {
                 $bloglib = TikiLib::lib('blog');
@@ -1085,13 +1084,17 @@ class FreetagLib extends ObjectLib
             $lang = $prefs['language'];
         }
 
+        $max = filter_var($max, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
+        if ($max === false) {
+            $max = 10;
+        }
+
         $query = 'SELECT t.* FROM `tiki_freetags` t, `tiki_freetagged_objects` o'
                         . ' WHERE t.`tagId` = o.`tagId`'
                         . ' AND (`lang` = ? or `lang` IS null)'
-                        . ' ORDER BY ' . $this->convertSortMode('random')
-                        . ' LIMIT ' . $max;
+                        . ' ORDER BY ' . $this->convertSortMode('random');
 
-        $result = $this->query($query, [ $lang ]);
+        $result = $this->query($query, [ $lang ], $max);
 
         $tags = [];
         $index = [];


=====================================
lib/performance/performancestatslib.php
=====================================
@@ -52,7 +52,15 @@ class PerformanceStatsLib extends TikiLib
      */
     public function getRequestsBasedOnAverageRequestTime(int $amount = 25, int $offset = 0, string $find = '', string $order = 'DESC')
     {
-        return $this->query("SELECT url, round(AVG(time_taken)) AS average_time_taken FROM tiki_performance WHERE url LIKE ? GROUP BY url ORDER BY average_time_taken $order LIMIT $amount OFFSET $offset", ["%$find%"]);
+        $order = strtoupper($order);
+        if (! in_array($order, ['ASC', 'DESC'])) {
+            $order = 'DESC';
+        }
+        if ($orderType == 'no_of_requests') {
+            return $this->query("SELECT url, round(AVG(time_taken)) AS average_time_taken, COUNT(url) AS number_of_requests FROM tiki_performance WHERE url LIKE ? GROUP BY url ORDER BY number_of_requests $order", ["%$find%"], $amount, $offset);
+        } else {
+            return $this->query("SELECT url, round(AVG(time_taken)) AS average_time_taken, COUNT(url) AS number_of_requests FROM tiki_performance WHERE url LIKE ? GROUP BY url ORDER BY average_time_taken $order", ["%$find%"], $amount, $offset);
+        }
     }
 
     /**
@@ -65,7 +73,11 @@ class PerformanceStatsLib extends TikiLib
      */
     public function getRequestsBasedOnMaximumProcessingTime(int $amount = 25, int $offset = 0, string $find = '', string $order = 'DESC')
     {
-        return $this->query("SELECT url, MAX(time_taken) AS maximum_time_taken FROM tiki_performance WHERE url LIKE ? GROUP BY url ORDER BY maximum_time_taken $order LIMIT $amount OFFSET $offset", ["%$find%"]);
+        $order = strtoupper($order);
+        if (! in_array($order, ['ASC', 'DESC'])) {
+            $order = 'DESC';
+        }
+        return $this->query("SELECT url, MAX(time_taken) AS maximum_time_taken FROM tiki_performance WHERE url LIKE ? GROUP BY url ORDER BY maximum_time_taken $order", ["%$find%"], $amount, $offset);
     }
 
     /**


=====================================
tiki-performance_stats.php
=====================================
@@ -20,7 +20,26 @@ $find = $_REQUEST['find'] ?? '';
 $averageStatOffset = $_REQUEST['average_stat_offset'] ?? 0;
 $averageStatOrder = $_REQUEST['average_stat_order'] ?? 'DESC';
 $maximumStatOffset = $_REQUEST['maximum_stat_offset'] ?? 0;
+$detailsUrl = $_REQUEST['details_url'] ?? '';
 $maximumStatOrder = $_REQUEST['maximum_stat_order'] ?? 'DESC';
+$maximumStatOrder = strtoupper($maximumStatOrder);
+if (! in_array($maximumStatOrder, ['ASC', 'DESC'])) {
+    $maximumStatOrder = 'DESC';
+}
+$averageStatOrder = $_REQUEST['average_stat_order'] ?? 'DESC';
+$averageStatOrder = strtoupper($averageStatOrder);
+if (! in_array($averageStatOrder, ['ASC', 'DESC'])) {
+    $averageStatOrder = 'DESC';
+}
+$orderType = 'average_stat_order';
+$noOfRequests = $_REQUEST['no_of_requests'] ?? '';
+if (! empty($noOfRequests)) {
+    $noOfRequests = strtoupper($noOfRequests);
+    $averageStatOrder = in_array($noOfRequests, ['ASC', 'DESC']) ? $noOfRequests : 'DESC';
+    $orderType = 'no_of_requests';
+} else {
+    $orderType = 'average_stat_order';
+}
 
 $smarty->assign('performance_stats_lib', $performanceLib);
 $smarty->assign('find', $find);



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/8e1e3bc1a3ca47750f92d3719b76477d7bf730b6

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/8e1e3bc1a3ca47750f92d3719b76477d7bf730b6
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.