From 7fa6edc03be9566fd7d6e3b81126a4671ace0bec Mon Sep 17 00:00:00 2001 From: int2001 Date: Mon, 29 Dec 2025 19:38:23 +0000 Subject: [PATCH] Fix several potential SQL-Injections at Notes/OQRS --- application/controllers/Notes.php | 5 ++++- application/models/Note.php | 23 ++++++++++++++++------- application/models/Oqrs_model.php | 4 ++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/application/controllers/Notes.php b/application/controllers/Notes.php index 546d7bbe4..faf205709 100644 --- a/application/controllers/Notes.php +++ b/application/controllers/Notes.php @@ -153,7 +153,10 @@ class Notes extends CI_Controller { $per_page = (int)$this->input->post('per_page', TRUE); $sort_col = $this->input->post('sort_col', TRUE); $sort_dir = $this->input->post('sort_dir', TRUE); - if ($per_page < 1) $per_page = 15; + + // Validate and sanitize pagination parameters + $max_per_page = 100; // Prevent denial of service + if ($per_page < 1 || $per_page > $max_per_page) $per_page = 15; if ($page < 1) $page = 1; // Get paginated, sorted notes $result = $this->note->search_paginated($searchCriteria, $page, $per_page, $sort_col, $sort_dir); diff --git a/application/models/Note.php b/application/models/Note.php index 044a93aa1..056b5c74c 100644 --- a/application/models/Note.php +++ b/application/models/Note.php @@ -186,6 +186,9 @@ class Note extends CI_Model { // Search notes with pagination and sorting for the logged-in user public function search_paginated($criteria = [], $page = 1, $per_page = 25, $sort_col = null, $sort_dir = null) { + $page = max(1, intval($page)); + $per_page = max(1, min(100, intval($per_page))); // Enforce max limit + $user_id = $this->session->userdata('user_id'); $params = array($user_id); $where_clause = "WHERE user_id = ?"; @@ -216,15 +219,21 @@ class Note extends CI_Model { // Build main query with sorting $sql = "SELECT id, cat, title, note, creation_date, last_modified FROM notes $where_clause"; - // Sorting - $columns = ['cat', 'title', 'creation_date', 'last_modified']; - if ($sort_col !== null && in_array($sort_col, $columns) && ($sort_dir === 'asc' || $sort_dir === 'desc')) { - $sql .= " ORDER BY $sort_col $sort_dir"; - } + // Sorting - use strict array key mapping to prevent SQL injection + $allowed_columns = [ + 'cat' => 'cat', + 'title' => 'title', + 'creation_date' => 'creation_date', + 'last_modified' => 'last_modified' + ]; + $sort_column = isset($allowed_columns[$sort_col]) ? $allowed_columns[$sort_col] : 'creation_date'; + $sort_direction = ($sort_dir === 'desc') ? 'DESC' : 'ASC'; + $sql .= " ORDER BY $sort_column $sort_direction"; - // Pagination $offset = ($page - 1) * $per_page; - $sql .= " LIMIT $per_page OFFSET $offset"; + $limit = intval($per_page); + $offset_val = intval($offset); + $sql .= " LIMIT $limit OFFSET $offset_val"; $query = $this->db->query($sql, $params); $notes = []; diff --git a/application/models/Oqrs_model.php b/application/models/Oqrs_model.php index 73f2113bb..921559a3c 100644 --- a/application/models/Oqrs_model.php +++ b/application/models/Oqrs_model.php @@ -513,8 +513,8 @@ class Oqrs_model extends CI_Model { "; if ($searchCriteria['oqrsResults'] !== 'All') { - $limit = $searchCriteria['oqrsResults']; - $sql .= "LIMIT $limit"; + $limit = max(1, min(1000, intval($searchCriteria['oqrsResults']))); // Sanitize and enforce max + $sql .= " LIMIT " . $limit; } $data = $this->db->query($sql, $binding);