From 851c989df10affb464b97a0de660a6bf371b7f99 Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Fri, 27 Mar 2026 20:16:36 -0700 Subject: [PATCH] security: fix SQLi, XSS, credential exposure, and insecure deserialization Replace bare unserialize() with cacti_unserialize() plus array validation in mactrack_view_macs.php. The original call allowed PHP object injection on a guest-accessible page. Strip 9 SNMP credential columns (community strings, SNMPv3 usernames, passwords, auth/priv protocols, passphrases) from the guest-accessible CSV export in mactrack_view_devices.php. Any user with Viewer realm could download all network device SNMP credentials. Addresses GHSA-9829-w9mx-2cgm. Replace all 27 unsafe LIKE string interpolation sites across 9 files with db_qstr() quoting. Also fix mactrack_create_sql_filter() in lib/mactrack_functions.php. Six of the affected files are guest-accessible, making filter SQLi pre-authentication. Replace raw db_qstr()-less CSV value interpolation in the import processors of mactrack_devices.php and mactrack_device_types.php. CSV cell values were concatenated directly into INSERT VALUES and WHERE clauses with only single-quote stripping (bypassable via backslash escaping). Replace get_request_var('filter') with html_escape_request_var() in 11 HTML input value attributes to prevent reflected XSS. Wrap 4 SNMP response variables with html_escape() in mactrack_devices.php to prevent stored XSS via rogue SNMP agents. Signed-off-by: Thomas Vincent --- lib/mactrack_functions.php | 4 ++-- mactrack_device_types.php | 25 ++++++++++++------------- mactrack_devices.php | 31 +++++++++++++++---------------- mactrack_macauth.php | 6 +++--- mactrack_macwatch.php | 10 +++++----- mactrack_sites.php | 8 ++++---- mactrack_snmp.php | 4 ++-- mactrack_vendormacs.php | 8 ++++---- mactrack_view_arp.php | 2 +- mactrack_view_devices.php | 20 +++++++------------- mactrack_view_interfaces.php | 2 +- mactrack_view_macs.php | 9 +++++++-- mactrack_view_sites.php | 8 ++++---- 13 files changed, 67 insertions(+), 70 deletions(-) diff --git a/lib/mactrack_functions.php b/lib/mactrack_functions.php index 9c47f6d..c436963 100644 --- a/lib/mactrack_functions.php +++ b/lib/mactrack_functions.php @@ -3360,7 +3360,7 @@ function mactrack_create_sql_filter($filter, $fields) { $query .= '('; } - $query .= ($field_no == 1 ? '' : " $operator ") . "($field $type LIKE '%" . $filter . "%')"; + $query .= ($field_no == 1 ? '' : " $operator ") . "($field $type LIKE " . db_qstr('%' . $filter . '%') . ")"; $field_no++; } @@ -3582,7 +3582,7 @@ function mactrack_site_filter($page = 'mactrack_sites.php') { - '> + '> diff --git a/mactrack_device_types.php b/mactrack_device_types.php index 0ee23f6..032f85d 100644 --- a/mactrack_device_types.php +++ b/mactrack_device_types.php @@ -749,7 +749,6 @@ function mactrack_device_type_import_processor(&$device_types) { foreach ($line_array as $line_item) { if (in_array($j, $insert_columns, true)) { - $line_item = trim(str_replace("'", '', $line_item)); $line_item = trim(str_replace('"', '', $line_item)); if (!$first_column) { @@ -762,15 +761,15 @@ function mactrack_device_type_import_processor(&$device_types) { if ($sql_where != '') { switch($j) { case $device_type_id: - $sql_where .= " AND device_type='$line_item'"; + $sql_where .= ' AND device_type=' . db_qstr($line_item); break; case $sysDescr_match_id: - $sql_where .= " AND sysDescr_match='$line_item'"; + $sql_where .= ' AND sysDescr_match=' . db_qstr($line_item); break; case $sysObjectID_match_id: - $sql_where .= " AND sysObjectID_match='$line_item'"; + $sql_where .= ' AND sysObjectID_match=' . db_qstr($line_item); break; default: @@ -779,15 +778,15 @@ function mactrack_device_type_import_processor(&$device_types) { } else { switch($j) { case $device_type_id: - $sql_where .= "WHERE device_type='$line_item'"; + $sql_where .= 'WHERE device_type=' . db_qstr($line_item); break; case $sysDescr_match_id: - $sql_where .= "WHERE sysDescr_match='$line_item'"; + $sql_where .= 'WHERE sysDescr_match=' . db_qstr($line_item); break; case $sysObjectID_match_id: - $sql_where .= "WHERE sysObjectID_match='$line_item'"; + $sql_where .= 'WHERE sysObjectID_match=' . db_qstr($line_item); break; default: @@ -821,7 +820,7 @@ function mactrack_device_type_import_processor(&$device_types) { $description = $line_item; } - $save_value .= "'" . $line_item . "'"; + $save_value .= db_qstr($line_item); } $j++; @@ -901,10 +900,10 @@ function mactrack_device_type_edit() { function mactrack_get_device_types(&$sql_where, $rows, $apply_limits = true) { if (get_request_var('filter') != '') { - $sql_where = " WHERE (mtdt.vendor LIKE '%" . get_request_var('filter') . "%' OR - mtdt.description LIKE '%" . get_request_var('filter') . "%' OR - mtdt.sysDescr_match LIKE '%" . get_request_var('filter') . "%' OR - mtdt.sysObjectID_match LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = " WHERE (mtdt.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.sysDescr_match LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.sysObjectID_match LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (get_request_var('vendor') == 'All') { @@ -1053,7 +1052,7 @@ function mactrack_device_type_filter() { - '> + '> diff --git a/mactrack_devices.php b/mactrack_devices.php index 1435db5..a1ba75c 100644 --- a/mactrack_devices.php +++ b/mactrack_devices.php @@ -746,7 +746,6 @@ function mactrack_device_import_processor(&$devices) { if (cacti_sizeof($line_array)) { foreach ($line_array as $line_item) { if (in_array($j, $insert_columns, true)) { - $line_item = trim(str_replace("'", '', $line_item)); $line_item = trim(str_replace('"', '', $line_item)); if (!$first_column) { @@ -759,15 +758,15 @@ function mactrack_device_import_processor(&$devices) { if ($sql_where != '') { switch($j) { case $save_site_id_id: - $sql_where .= " AND site_id='$line_item'"; + $sql_where .= ' AND site_id=' . db_qstr($line_item); break; case $save_snmp_port_id: - $sql_where .= " AND snmp_port='$line_item'"; + $sql_where .= ' AND snmp_port=' . db_qstr($line_item); break; case $save_host_id: - $sql_where .= " AND hostname='$line_item'"; + $sql_where .= ' AND hostname=' . db_qstr($line_item); break; default: @@ -776,15 +775,15 @@ function mactrack_device_import_processor(&$devices) { } else { switch($j) { case $save_site_id_id: - $sql_where .= "WHERE site_id='$line_item'"; + $sql_where .= 'WHERE site_id=' . db_qstr($line_item); break; case $save_snmp_port_id: - $sql_where .= "WHERE snmp_port='$line_item'"; + $sql_where .= 'WHERE snmp_port=' . db_qstr($line_item); break; case $save_host_id: - $sql_where .= "WHERE hostname='$line_item'"; + $sql_where .= 'WHERE hostname=' . db_qstr($line_item); break; default: @@ -809,7 +808,7 @@ function mactrack_device_import_processor(&$devices) { $device_name = $line_item; } - $save_value .= "'" . $line_item . "'"; + $save_value .= db_qstr($line_item); } $j++; @@ -935,10 +934,10 @@ function mactrack_device_edit() { $snmp_objid = str_replace('OID: ', '', $snmp_objid); $snmp_objid = str_replace('.iso', '.1', $snmp_objid); - print '' . __('System:', 'mactrack') . " $snmp_system
\n"; - print '' . __('Uptime:', 'mactrack') . " $snmp_uptime
\n"; - print '' . __('Hostname:', 'mactrack') . " $snmp_hostname
\n"; - print '' . __('ObjectID:', 'mactrack') . " $snmp_objid
\n"; + print '' . __('System:', 'mactrack') . ' ' . html_escape($snmp_system) . "
\n"; + print '' . __('Uptime:', 'mactrack') . ' ' . html_escape($snmp_uptime) . "
\n"; + print '' . __('Hostname:', 'mactrack') . ' ' . html_escape($snmp_hostname) . "
\n"; + print '' . __('ObjectID:', 'mactrack') . ' ' . html_escape($snmp_objid) . "
\n"; } ?> @@ -973,9 +972,9 @@ function mactrack_device_edit() { function mactrack_get_devices(&$sql_where, $rows, $apply_limits = true) { // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mtd.hostname like '%" . get_request_var('filter') . "%' - OR mtd.device_name like '%" . get_request_var('filter') . "%' - OR mtd.notes like '%" . get_request_var('filter') . "%')"; + $sql_where = ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mtd.hostname LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " + OR mtd.device_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " + OR mtd.notes LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (get_request_var('status') == '-1') { @@ -1160,7 +1159,7 @@ function mactrack_device_filter() { - '> + '> diff --git a/mactrack_macauth.php b/mactrack_macauth.php index b559f07..1aa4baf 100644 --- a/mactrack_macauth.php +++ b/mactrack_macauth.php @@ -219,8 +219,8 @@ function mactrack_maca_get_maca_records(&$sql_where, $rows, $apply_limits = true $sql_where = ''; if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_address LIKE '%" . str_replace(['-', '.', ':'],'',get_request_var('filter')) . "%' OR " . - "description LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_address LIKE " . db_qstr('%' . str_replace(['-', '.', ':'],'',get_request_var('filter')) . '%') . " OR " . + "description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -384,7 +384,7 @@ function mactrack_maca_filter() { - '> + '> diff --git a/mactrack_macwatch.php b/mactrack_macwatch.php index 4013854..1303a98 100644 --- a/mactrack_macwatch.php +++ b/mactrack_macwatch.php @@ -203,10 +203,10 @@ function mactrack_macw_get_macw_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_address LIKE '%" . get_request_var('filter') . "%' OR " . - "name LIKE '%" . get_request_var('filter') . "%' OR " . - "ticket_number LIKE '%" . get_request_var('filter') . "%' OR " . - "description LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_address LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "ticket_number LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -392,7 +392,7 @@ function mactrack_macw_filter() { - '> + '> diff --git a/mactrack_sites.php b/mactrack_sites.php index 67c03e0..da38730 100644 --- a/mactrack_sites.php +++ b/mactrack_sites.php @@ -291,11 +291,11 @@ function mactrack_site_get_site_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { if (get_request_var('detail') == 'false') { - $sql_where = "WHERE (mts.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mts.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } else { - $sql_where = "WHERE (mts.vendor LIKE '%" . get_request_var('filter') . "%' OR " . - "mtdt.description LIKE '%" . get_request_var('filter') . "%' OR " . - "mts.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mts.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mtdt.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mts.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } } diff --git a/mactrack_snmp.php b/mactrack_snmp.php index 98ade52..0b4093b 100644 --- a/mactrack_snmp.php +++ b/mactrack_snmp.php @@ -541,7 +541,7 @@ function mactrack_snmp() { $sql_where = ''; if (get_request_var('filter') != '') { - $sql_where .= "WHERE (mac_track_snmp.name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where .= "WHERE (mac_track_snmp.name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $total_rows = db_fetch_cell("SELECT @@ -607,7 +607,7 @@ function snmp_options_filter() { - '> + '> diff --git a/mactrack_vendormacs.php b/mactrack_vendormacs.php index 6962de2..58db0aa 100644 --- a/mactrack_vendormacs.php +++ b/mactrack_vendormacs.php @@ -103,9 +103,9 @@ function mactrack_vmacs_get_vmac_records(&$sql_where, $rows, $apply_limits = tru // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_track_oui_database.vendor_name LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_oui_database.vendor_mac LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_oui_database.vendor_address LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_oui_database.vendor_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_oui_database.vendor_mac LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_oui_database.vendor_address LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -201,7 +201,7 @@ function mactrack_vmac_filter() { - '> + '> diff --git a/mactrack_view_arp.php b/mactrack_view_arp.php index 631e652..63b9ad2 100644 --- a/mactrack_view_arp.php +++ b/mactrack_view_arp.php @@ -453,7 +453,7 @@ function mactrack_ip_address_filter() { - '> + '> diff --git a/mactrack_view_devices.php b/mactrack_view_devices.php index 548260a..3fccc64 100644 --- a/mactrack_view_devices.php +++ b/mactrack_view_devices.php @@ -105,9 +105,7 @@ function mactrack_view_export_devices() { $xport_array = []; array_push($xport_array, 'site_id, site_name, device_id, device_name, notes, ' . - 'hostname, snmp_readstring, snmp_readstrings, snmp_version, ' . - 'snmp_username, snmp_password, snmp_auth_protocol, snmp_priv_passphrase, ' . - 'snmp_priv_protocol, snmp_context, snmp_engine_id, ' . + 'hostname, snmp_version, ' . 'snmp_port, snmp_timeout, snmp_retries, max_oids, snmp_sysName, snmp_sysLocation, ' . 'snmp_sysContact, snmp_sysObjectID, snmp_sysDescr, snmp_sysUptime, ' . 'ignorePorts, scan_type, disabled, ports_total, ports_active, ' . @@ -119,11 +117,7 @@ function mactrack_view_export_devices() { $device['site_id'] . '","' . $device['site_name'] . '","' . $device['device_id'] . '","' . $device['device_name'] . '","' . $device['notes'] . '","' . $device['hostname'] . '","' . - $device['snmp_readstring'] . '","' . $device['snmp_readstrings'] . '","' . - $device['snmp_version'] . '","' . $device['snmp_username'] . '","' . - $device['snmp_password'] . '","' . $device['snmp_auth_protocol'] . '","' . - $device['snmp_priv_passphrase'] . '","' . $device['snmp_priv_protocol'] . '","' . - $device['snmp_context'] . '","' . $device['snmp_engine_id'] . '","' . + $device['snmp_version'] . '","' . $device['snmp_port'] . '","' . $device['snmp_timeout'] . '","' . $device['snmp_retries'] . '","' . $device['max_oids'] . '","' . $device['snmp_sysName'] . '","' . $device['snmp_sysLocation'] . '","' . @@ -161,10 +155,10 @@ function mactrack_view_get_device_records(&$sql_where, $rows, $apply_limits = tr // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mac_track_devices.hostname LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_devices.notes LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_devices.device_name LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mac_track_devices.hostname LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_devices.notes LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_devices.device_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (cacti_sizeof($device_type_info)) { @@ -427,7 +421,7 @@ function mactrack_device_filter2() { - '> + '> diff --git a/mactrack_view_interfaces.php b/mactrack_view_interfaces.php index 66e4ad5..bebfb32 100644 --- a/mactrack_view_interfaces.php +++ b/mactrack_view_interfaces.php @@ -648,7 +648,7 @@ function mactrack_filter_table() { - '> + '> > diff --git a/mactrack_view_macs.php b/mactrack_view_macs.php index f19f3c0..e1e9ed1 100644 --- a/mactrack_view_macs.php +++ b/mactrack_view_macs.php @@ -88,7 +88,12 @@ function form_actions() { // if we are to save this form, instead of display it if (isset_request_var('selected_items')) { - $selected_items = unserialize(get_nfilter_request_var('selected_items')); + $selected_items = cacti_unserialize(stripslashes(get_nfilter_request_var('selected_items'))); + + if (!is_array($selected_items)) { + header('Location: mactrack_view_macs.php'); + exit; + } foreach ($selected_items as $mac=>$ip) { if (!filter_var($mac, FILTER_VALIDATE_MAC)) { @@ -1106,7 +1111,7 @@ function mactrack_mac_filter() { - '> + '> diff --git a/mactrack_view_sites.php b/mactrack_view_sites.php index 655bbc2..656f501 100644 --- a/mactrack_view_sites.php +++ b/mactrack_view_sites.php @@ -93,11 +93,11 @@ function mactrack_view_get_site_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { if (get_request_var('detail') == 'false') { - $sql_where = "WHERE (mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } else { - $sql_where = "WHERE (mac_track_device_types.vendor LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_device_types.description LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_device_types.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_device_types.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } }