From 6bea59b8a0807e3a68dcebe6e186912c655fab3d Mon Sep 17 00:00:00 2001 From: Jellyfrog Date: Fri, 10 Jul 2020 16:17:09 +0200 Subject: [PATCH] Fix SQL injections in ajax_table.php (#11920) * Fix SQL injections via searchPhrase parameter * Fix SQL injections via address parameter * Fix sort injection Co-authored-by: Tony Murray --- html/ajax_table.php | 4 +++- includes/html/table/address-search.inc.php | 7 +++++-- includes/html/table/alertlog-stats.inc.php | 6 +++++- includes/html/table/alerts.inc.php | 7 ++++++- includes/html/table/as-selection.inc.php | 8 +++++--- includes/html/table/edit-ports.inc.php | 5 ++++- includes/html/table/eventlog.inc.php | 8 +++++++- includes/html/table/inventory.inc.php | 6 +++++- includes/html/table/ix-list.inc.php | 3 ++- includes/html/table/ix-peers.inc.php | 5 ++++- includes/html/table/mempool-edit.inc.php | 6 +++++- includes/html/table/mempool.inc.php | 4 +++- includes/html/table/poll-log.inc.php | 11 ++++++++--- includes/html/table/processor-edit.inc.php | 6 +++++- includes/html/table/processor.inc.php | 4 +++- includes/html/table/routing-edit.inc.php | 5 ++++- includes/html/table/sensors-common.php | 5 ++++- includes/html/table/storage-edit.inc.php | 6 +++++- includes/html/table/storage.inc.php | 4 +++- includes/html/table/toner.inc.php | 5 ++++- 20 files changed, 90 insertions(+), 25 deletions(-) diff --git a/html/ajax_table.php b/html/ajax_table.php index 56aca04cf4..cca6ffb65c 100644 --- a/html/ajax_table.php +++ b/html/ajax_table.php @@ -25,8 +25,10 @@ $current = $_REQUEST['current']; settype($current, 'integer'); $rowCount = $_REQUEST['rowCount']; settype($rowCount, 'integer'); -if (isset($_REQUEST['sort']) && is_array($_POST['sort'])) { +if (isset($_REQUEST['sort']) && is_array($_REQUEST['sort'])) { foreach ($_REQUEST['sort'] as $k => $v) { + $k = preg_replace('/[^A-Za-z0-9_]/', '', $k); // only allow plain columns + $v = strtolower($v) == 'desc' ? 'DESC' : 'ASC'; $sort .= " $k $v"; } } diff --git a/includes/html/table/address-search.inc.php b/includes/html/table/address-search.inc.php index efec4f3818..d70f9fcbe6 100644 --- a/includes/html/table/address-search.inc.php +++ b/includes/html/table/address-search.inc.php @@ -15,7 +15,8 @@ if ($vars['search_type'] == 'ipv4') { $sql = ' FROM `ipv4_addresses` AS A, `ports` AS I, `ipv4_networks` AS N, `devices` AS D'; $sql .= " WHERE I.port_id = A.port_id AND I.device_id = D.device_id AND N.ipv4_network_id = A.ipv4_network_id $where "; if (!empty($address)) { - $sql .= " AND ipv4_address LIKE '%".$address."%'"; + $sql .= " AND ipv4_address LIKE ?"; + $param[] = "%$address%"; } if (!empty($prefix)) { @@ -26,7 +27,9 @@ if ($vars['search_type'] == 'ipv4') { $sql = ' FROM `ipv6_addresses` AS A, `ports` AS I, `ipv6_networks` AS N, `devices` AS D'; $sql .= " WHERE I.port_id = A.port_id AND I.device_id = D.device_id AND N.ipv6_network_id = A.ipv6_network_id $where "; if (!empty($address)) { - $sql .= " AND (ipv6_address LIKE '%".$address."%' OR ipv6_compressed LIKE '%".$address."%')"; + $sql .= " AND (ipv6_address LIKE ? OR ipv6_compressed LIKE ?)"; + $param[] = "%$address%"; + $param[] = "%$address%"; } if (!empty($prefix)) { diff --git a/includes/html/table/alertlog-stats.inc.php b/includes/html/table/alertlog-stats.inc.php index 5e6670d20c..b3dc16b8fa 100644 --- a/includes/html/table/alertlog-stats.inc.php +++ b/includes/html/table/alertlog-stats.inc.php @@ -39,7 +39,11 @@ if (Auth::user()->hasGlobalRead()) { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `D`.`sysName` LIKE '%$searchPhrase%' OR `E`.`time_logged` LIKE '%$searchPhrase%' OR `name` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `D`.`sysName` LIKE ? OR `E`.`time_logged` LIKE ? OR `name` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(DISTINCT D.sysname, R.name) $sql"; diff --git a/includes/html/table/alerts.inc.php b/includes/html/table/alerts.inc.php index a27ca39d0e..9ec331919b 100644 --- a/includes/html/table/alerts.inc.php +++ b/includes/html/table/alerts.inc.php @@ -60,7 +60,12 @@ if (!$show_recovered) { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $where .= " AND (`timestamp` LIKE '%$searchPhrase%' OR `rule` LIKE '%$searchPhrase%' OR `name` LIKE '%$searchPhrase%' OR `hostname` LIKE '%$searchPhrase%' OR `sysName` LIKE '%$searchPhrase%')"; + $where .= " AND (`timestamp` LIKE ? OR `rule` LIKE ? OR `name` LIKE ? OR `hostname` LIKE ? OR `sysName` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $sql = ' FROM `alerts` LEFT JOIN `devices` ON `alerts`.`device_id`=`devices`.`device_id`'; diff --git a/includes/html/table/as-selection.inc.php b/includes/html/table/as-selection.inc.php index 64862f523b..5aabf0e7fc 100644 --- a/includes/html/table/as-selection.inc.php +++ b/includes/html/table/as-selection.inc.php @@ -1,17 +1,19 @@ 0 AND (`bgpLocalAs` < 64512 OR `bgpLocalAs` > 65535) AND `bgpLocalAs` < 4200000000 "; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`bgpLocalAs` LIKE '%$searchPhrase%')"; + $sql .= " AND (`bgpLocalAs` LIKE ?)"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(*) $sql"; -$total = dbFetchCell($count_sql); +$total = dbFetchCell($count_sql, $param); if (empty($total)) { $total = 0; } @@ -33,7 +35,7 @@ if ($rowCount != -1) { $sql = "SELECT `bgpLocalAs` $sql"; -foreach (dbFetchRows($sql) as $asn) { +foreach (dbFetchRows($sql, $param) as $asn) { $astext = get_astext($asn['bgpLocalAs']); $response[] = array( 'bgpLocalAs' => $asn['bgpLocalAs'], diff --git a/includes/html/table/edit-ports.inc.php b/includes/html/table/edit-ports.inc.php index c59494a3fb..95498fab69 100644 --- a/includes/html/table/edit-ports.inc.php +++ b/includes/html/table/edit-ports.inc.php @@ -8,7 +8,10 @@ $sql = 'FROM `ports` WHERE `device_id` = ?'; $param = array($device_id); if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`ifName` LIKE '%$searchPhrase%' OR `ifAlias` LIKE '%$searchPhrase%' OR `ifDescr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`ifName` LIKE ? OR `ifAlias` LIKE ? OR `ifDescr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`port_id`) $sql"; diff --git a/includes/html/table/eventlog.inc.php b/includes/html/table/eventlog.inc.php index 0713d5b699..e230e50cc6 100644 --- a/includes/html/table/eventlog.inc.php +++ b/includes/html/table/eventlog.inc.php @@ -38,7 +38,13 @@ if (Auth::user()->hasGlobalRead()) { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `D`.`sysName` LIKE '%$searchPhrase%' OR `E`.`datetime` LIKE '%$searchPhrase%' OR `E`.`message` LIKE '%$searchPhrase%' OR `E`.`type` LIKE '%$searchPhrase%' OR `E`.`username` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `D`.`sysName` LIKE ? OR `E`.`datetime` LIKE ? OR `E`.`message` LIKE ? OR `E`.`type` LIKE ? OR `E`.`username` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(event_id) $sql"; diff --git a/includes/html/table/inventory.inc.php b/includes/html/table/inventory.inc.php index 9b5a2bca0e..c5dbe60295 100644 --- a/includes/html/table/inventory.inc.php +++ b/includes/html/table/inventory.inc.php @@ -12,7 +12,11 @@ if (!Auth::user()->hasGlobalRead()) { $sql = " FROM entPhysical AS E, devices AS D WHERE $where AND D.device_id = E.device_id"; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `E`.`entPhysicalDescr` LIKE '%$searchPhrase%' OR `E`.`entPhysicalModelName` LIKE '%$searchPhrase%' OR `E`.`entPhysicalSerialNum` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `E`.`entPhysicalDescr` LIKE ? OR `E`.`entPhysicalModelName` LIKE ? OR `E`.`entPhysicalSerialNum` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } if (isset($vars['string']) && strlen($vars['string'])) { diff --git a/includes/html/table/ix-list.inc.php b/includes/html/table/ix-list.inc.php index 75ee06f1ce..d0ca874be0 100644 --- a/includes/html/table/ix-list.inc.php +++ b/includes/html/table/ix-list.inc.php @@ -29,7 +29,8 @@ $params = array($asn); if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`name` LIKE '%$searchPhrase%')"; + $sql .= " AND (`name` LIKE ?)"; + $params[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(*) $sql"; diff --git a/includes/html/table/ix-peers.inc.php b/includes/html/table/ix-peers.inc.php index 9b045627fb..b90bbc8ca9 100644 --- a/includes/html/table/ix-peers.inc.php +++ b/includes/html/table/ix-peers.inc.php @@ -38,7 +38,10 @@ if ($status === 'unconnected') { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`remote_ipaddr4` LIKE '%$searchPhrase%' OR `remote_asn` LIKE '%$searchPhrase%' OR `P`.`name` LIKE '%$searchPhrase%')"; + $sql .= " AND (`remote_ipaddr4` LIKE ? OR `remote_asn` LIKE ? OR `P`.`name` LIKE ?)"; + $params[] = "%$searchPhrase%"; + $params[] = "%$searchPhrase%"; + $params[] = "%$searchPhrase%"; } $sql .= ' GROUP BY `bgpPeerIdentifier`, `P`.`name`, `P`.`remote_ipaddr4`, `P`.`peer_id`, `P`.`remote_asn` '; diff --git a/includes/html/table/mempool-edit.inc.php b/includes/html/table/mempool-edit.inc.php index 01c8c51a7b..bd6521df96 100644 --- a/includes/html/table/mempool-edit.inc.php +++ b/includes/html/table/mempool-edit.inc.php @@ -6,7 +6,11 @@ $sql = " FROM `mempools` AS `M` LEFT JOIN `devices` AS `D` ON `M`.`device_id` = $param[] = $device_id; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `M`.`mempool_descr` LIKE '%$searchPhrase%' OR `S`.`mempool_perc` LIKE '%$searchPhrase%' OR `M`.`mempool_perc_warn` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `M`.`mempool_descr` LIKE ? OR `S`.`mempool_perc` LIKE ? OR `M`.`mempool_perc_warn` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`mempool_id`) $sql"; diff --git a/includes/html/table/mempool.inc.php b/includes/html/table/mempool.inc.php index f394fb219f..2c61441b2a 100644 --- a/includes/html/table/mempool.inc.php +++ b/includes/html/table/mempool.inc.php @@ -28,7 +28,9 @@ if (!Auth::user()->hasGlobalRead()) { $sql .= " WHERE $where"; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`hostname` LIKE '%$searchPhrase%' OR `mempool_descr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`hostname` LIKE ? OR `mempool_descr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`mempool_id`) $sql"; diff --git a/includes/html/table/poll-log.inc.php b/includes/html/table/poll-log.inc.php index f3439af02b..3f94458199 100644 --- a/includes/html/table/poll-log.inc.php +++ b/includes/html/table/poll-log.inc.php @@ -2,6 +2,7 @@ use LibreNMS\Config; +$param = []; $sql = ' FROM `devices` AS D '; if (!Auth::user()->hasGlobalAdmin()) { @@ -17,7 +18,11 @@ if (!Auth::user()->hasGlobalAdmin()) { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (hostname LIKE '%$searchPhrase%' OR sysName LIKE '%$searchPhrase%' OR last_polled LIKE '%$searchPhrase%' OR last_polled_timetaken LIKE '%$searchPhrase%')"; + $sql .= " AND (hostname LIKE ? OR sysName LIKE ? OR last_polled LIKE ? OR last_polled_timetaken LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } if ($vars['type'] == "unpolled") { @@ -35,7 +40,7 @@ $count_sql = "SELECT COUNT(`D`.`device_id`) $sql"; $sql .= " ORDER BY $sort"; -$total = dbFetchCell($count_sql); +$total = dbFetchCell($count_sql, $param); if (empty($total)) { $total = 0; } @@ -51,7 +56,7 @@ if ($rowCount != -1) { $sql = "SELECT D.device_id, D.hostname AS `hostname`, D.sysName, D.last_polled AS `last_polled`, `group_name`, D.last_polled_timetaken AS `last_polled_timetaken` $sql"; -foreach (dbFetchRows($sql, array()) as $device) { +foreach (dbFetchRows($sql, $param) as $device) { if (empty($device['group_name'])) { $device['group_name'] = 'General'; } diff --git a/includes/html/table/processor-edit.inc.php b/includes/html/table/processor-edit.inc.php index 298ff5f1fa..80a721bbe9 100644 --- a/includes/html/table/processor-edit.inc.php +++ b/includes/html/table/processor-edit.inc.php @@ -6,7 +6,11 @@ $sql = " FROM `processors` AS `P` LEFT JOIN `devices` AS `D` ON `P`.`device_id` $param[] = $device_id; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `P`.`processor_descr` LIKE '%$searchPhrase%' OR `S`.`processor_usage` LIKE '%$searchPhrase%' OR `P`.`processor_perc_warn` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `P`.`processor_descr` LIKE ? OR `S`.`processor_usage` LIKE ? OR `P`.`processor_perc_warn` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`processor_id`) $sql"; diff --git a/includes/html/table/processor.inc.php b/includes/html/table/processor.inc.php index bb8774c8bf..61e76f1457 100644 --- a/includes/html/table/processor.inc.php +++ b/includes/html/table/processor.inc.php @@ -28,7 +28,9 @@ if (!Auth::user()->hasGlobalRead()) { $sql .= " WHERE $where"; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`hostname` LIKE '%$searchPhrase%' OR `processor_descr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`hostname` LIKE ? OR `processor_descr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`processor_id`) $sql"; diff --git a/includes/html/table/routing-edit.inc.php b/includes/html/table/routing-edit.inc.php index 74bb735729..9c2fc773b8 100644 --- a/includes/html/table/routing-edit.inc.php +++ b/includes/html/table/routing-edit.inc.php @@ -18,7 +18,10 @@ $sql = " FROM `bgpPeers` AS `B` LEFT JOIN `devices` AS `D` ON `B`.`device_id` = $param[] = $device_id; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `B`.`bgpPeerRemoteAs` LIKE '%$searchPhrase%' OR `B`.`bgpPeerIdentifier` LIKE '%$searchPhrase%' OR `B`.`bgpPeerDescr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `B`.`bgpPeerRemoteAs` LIKE ? OR `B`.`bgpPeerIdentifier` LIKE ? OR `B`.`bgpPeerDescr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`bgpPeer_id`) $sql"; diff --git a/includes/html/table/sensors-common.php b/includes/html/table/sensors-common.php index c83f16bc63..59aa40672d 100644 --- a/includes/html/table/sensors-common.php +++ b/includes/html/table/sensors-common.php @@ -33,7 +33,10 @@ if (!Auth::user()->hasGlobalRead()) { } if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `sensor_descr` LIKE '%$searchPhrase%' OR `sensor_current` LIKE '%searchPhrase')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `sensor_descr` LIKE ? OR `sensor_current` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase"; } $count_sql = "SELECT COUNT(`sensor_id`) $sql"; diff --git a/includes/html/table/storage-edit.inc.php b/includes/html/table/storage-edit.inc.php index 368227a506..0838e22ee9 100644 --- a/includes/html/table/storage-edit.inc.php +++ b/includes/html/table/storage-edit.inc.php @@ -6,7 +6,11 @@ $sql = " FROM `storage` AS `S` LEFT JOIN `devices` AS `D` ON `S`.`device_id` = ` $param[] = $device_id; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `S`.`storage_descr` LIKE '%$searchPhrase%' OR `S`.`storage_perc` LIKE '%$searchPhrase%' OR `S`.`storage_perc_warn` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `S`.`storage_descr` LIKE ? OR `S`.`storage_perc` LIKE ? OR `S`.`storage_perc_warn` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`storage_id`) $sql"; diff --git a/includes/html/table/storage.inc.php b/includes/html/table/storage.inc.php index c06f924702..c313409d19 100644 --- a/includes/html/table/storage.inc.php +++ b/includes/html/table/storage.inc.php @@ -31,7 +31,9 @@ if (!Auth::user()->hasGlobalRead()) { $sql .= " WHERE $where"; if (isset($searchPhrase) && !empty($searchPhrase)) { - $sql .= " AND (`hostname` LIKE '%$searchPhrase%' OR `storage_descr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`hostname` LIKE ? OR `storage_descr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(`storage_id`) $sql"; diff --git a/includes/html/table/toner.inc.php b/includes/html/table/toner.inc.php index f35cf479c6..10de34db1c 100644 --- a/includes/html/table/toner.inc.php +++ b/includes/html/table/toner.inc.php @@ -19,10 +19,13 @@ use LibreNMS\Util\StringHelpers; $graph_type = 'toner_usage'; +$param = []; $sql = 'SELECT * FROM `toner` AS S, `devices` AS D WHERE S.device_id = D.device_id'; if (!empty($searchPhrase)) { - $sql .= " AND (`D`.`hostname` LIKE '%$searchPhrase%' OR `toner_descr` LIKE '%$searchPhrase%')"; + $sql .= " AND (`D`.`hostname` LIKE ? OR `toner_descr` LIKE ?)"; + $param[] = "%$searchPhrase%"; + $param[] = "%$searchPhrase%"; } $count_sql = "SELECT COUNT(*) FROM `toner`";