From 96411bff84da9b78298643084e3805a4ffd1d81c Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Fri, 27 Mar 2026 20:23:28 -0700 Subject: [PATCH] security: fix RLIKE SQLi, XSS, integer casting, and dynamic dispatch Fix RLIKE SQL injection in db_functions.php by wrapping get_request_var('rfilter') with db_qstr() instead of manual string concatenation. This is guest-accessible when monitor.php sets $guest_account=true. Add html_escape() to all hidden input value attributes in monitor_controller.php to prevent reflected XSS. Add html_escape() to host description and hostname in email notification body in poller_functions.php to prevent stored XSS via rogue SNMP device responses. Add (int) cast to integer request vars (crit, site) before SQL concatenation in db_functions.php as defense-in-depth. Add allowlist validation for the grouping parameter before dynamic function dispatch in monitor_controller.php. Only default, tree, site, and template are permitted. Signed-off-by: Thomas Vincent --- db_functions.php | 6 +++--- monitor_controller.php | 14 ++++++++------ poller_functions.php | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/db_functions.php b/db_functions.php index dac37e2..780d14d 100644 --- a/db_functions.php +++ b/db_functions.php @@ -96,21 +96,21 @@ function renderGroupConcat(string &$sql_where, string $sql_join, string $sql_fie */ function renderWhereJoin(string &$sql_where, string &$sql_join): void { if (get_request_var('crit') > 0) { - $awhere = 'h.monitor_criticality >= ' . get_request_var('crit'); + $awhere = 'h.monitor_criticality >= ' . (int) get_request_var('crit'); } else { $awhere = ''; } if (get_request_var('grouping') == 'site') { if (get_request_var('site') > 0) { - $awhere .= ($awhere == '' ? '' : ' AND ') . 'h.site_id = ' . get_request_var('site'); + $awhere .= ($awhere == '' ? '' : ' AND ') . 'h.site_id = ' . (int) get_request_var('site'); } elseif (get_request_var('site') == -2) { $awhere .= ($awhere == '' ? '' : ' AND ') . ' h.site_id = 0'; } } if (get_request_var('rfilter') != '') { - $awhere .= ($awhere == '' ? '' : ' AND ') . " h.description RLIKE '" . get_request_var('rfilter') . "'"; + $awhere .= ($awhere == '' ? '' : ' AND ') . ' h.description RLIKE ' . db_qstr(get_request_var('rfilter')); } if (get_request_var('grouping') == 'tree') { diff --git a/monitor_controller.php b/monitor_controller.php index 7eb2b69..2202d94 100644 --- a/monitor_controller.php +++ b/monitor_controller.php @@ -106,7 +106,9 @@ function drawPage(): void { // Default with permissions = default_by_permission // Tree = group_by_tree - $function = 'render' . ucfirst(get_request_var('grouping')); + $allowed_groupings = ['default', 'tree', 'site', 'template']; + $grouping = in_array(get_request_var('grouping'), $allowed_groupings, true) ? get_request_var('grouping') : 'default'; + $function = 'render' . ucfirst($grouping); if (function_exists($function) && get_request_var('view') != 'list') { if (get_request_var('grouping') == 'default' || get_request_var('grouping') == 'site') { @@ -548,23 +550,23 @@ function monitorRenderGroupingDropdowns(array $classes, array $criticalities, ar */ function monitorRenderHiddenFilterInputs(): void { if (get_request_var('grouping') != 'tree') { - print '' . PHP_EOL; + print '' . PHP_EOL; } if (get_request_var('grouping') != 'site') { - print '' . PHP_EOL; + print '' . PHP_EOL; } if (get_request_var('grouping') != 'template') { - print '' . PHP_EOL; + print '' . PHP_EOL; } if (get_request_var('view') == 'list') { - print '' . PHP_EOL; + print '' . PHP_EOL; } if (get_request_var('view') != 'default') { - print '' . PHP_EOL; + print '' . PHP_EOL; } } diff --git a/poller_functions.php b/poller_functions.php index ddb8568..776dbbe 100644 --- a/poller_functions.php +++ b/poller_functions.php @@ -317,8 +317,8 @@ function buildRebootDetails(array $hosts): array { $last_host = $host; $body .= '' . - '' . $host['description'] . '' . - '' . $host['hostname'] . '' . + '' . html_escape($host['description']) . '' . + '' . html_escape($host['hostname']) . '' . '' . PHP_EOL; $body_txt .=