diff --git a/.gitignore b/.gitignore index eff3ba3..f6b7fd8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ *.swp .DS_Store +.omc/ locales/po/*.mo diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..8228fe0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Supported Versions + +This plugin follows the Cacti project's support policy. Security fixes are +applied to the current development branch and backported per project policy. + +## Reporting a Vulnerability + +Report security vulnerabilities via the Cacti project's private security +disclosure process: + +- GitHub Security Advisories: https://github.com/Cacti/plugin_webseer/security/advisories +- Do NOT open public issues for security vulnerabilities. + +Please include: +- Description of the vulnerability +- Steps to reproduce +- Affected versions +- Suggested remediation (if known) + +A maintainer will acknowledge the report within 72 hours and provide a +remediation timeline. + +## Security Hardening Notes + +See SECURITY-AUDIT.md for the current known finding backlog and remediation status. diff --git a/classes/cURL.php b/classes/cURL.php index d263e71..ddb1878 100644 --- a/classes/cURL.php +++ b/classes/cURL.php @@ -1,4 +1,6 @@ debug('Executing Post Request'); @@ -91,14 +93,14 @@ function post($url, $data = array()) { $process = curl_init($url); $this->headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8'; - $d = array(); + $d = []; foreach ($data as $i => $j) { $d[] = "$i=$j"; } $data = implode('&', $d); - $options = array( + $options = [ CURLOPT_HTTPHEADER => $this->headers, CURLOPT_HEADER => true, CURLOPT_USERAGENT => $this->user_agent, @@ -107,7 +109,7 @@ function post($url, $data = array()) { CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_POST => true, - ); + ]; if (!empty($this->compression)) { $options[CURLOPT_ENCODING] = $httpcompressions[$this->compression]; @@ -175,38 +177,38 @@ function get() { $is_https = (substr(strtolower($url), 0, 5) == 'https'); - $proxy_opts = array( + $proxy_opts = [ CURLOPT_UNRESTRICTED_AUTH => true, CURLOPT_PROXY => $this->proxy_hostname, CURLOPT_PROXYPORT => $is_https ? $port_https : $port_http, - ); + ]; if ($this->proxy_username != '') { $proxy_opts[CURLOPT_PROXYUSERPWD] = $this->proxy_username . ':' . $this->proxy_password; } } else { - $proxy_opts = array(); + $proxy_opts = []; } // Disable Cert checking for now if ($this->host['checkcert'] == '') { - $cert_opts = array( + $cert_opts = [ CURLOPT_SSL_VERIFYPEER => FALSE, CURLOPT_SSL_VERIFYHOST => FALSE, - ); + ]; } else { - $cert_opts = array(); + $cert_opts = []; } $options += $proxy_opts; $options += $cert_opts; $this->debug('cURL options: ' . clean_up_lines(var_export($options, true))); - curl_setopt_array($process,$options); + curl_setopt_array($process, $options); $data = curl_exec($process); - $this->data = str_replace(array("'", "\\"), array(''), $data); + $this->data = str_replace(["'", "\\"], [''], $data); $this->results['options'] = curl_getinfo($process); $this->results['options']['compression'] = $this->compression; @@ -222,7 +224,7 @@ function get() { case 0: break; default: - $this->results['error'] = 'HTTP ERROR: ' . str_replace(array('"', "'"), '', (curl_error($process))); + $this->results['error'] = 'HTTP ERROR: ' . str_replace(['"', "'"], '', (curl_error($process))); break; } diff --git a/classes/index.php b/classes/index.php index 9a6d459..596a8fb 100644 --- a/classes/index.php +++ b/classes/index.php @@ -1,4 +1,6 @@ gdi($this->cIx)); //$this->parse_data($curmx); - //$this->arrMX[] = array('MX_Pref' => $mxPref, 'MX' => $curmx); + //$this->arrMX[] = ['MX_Pref' => $mxPref, 'MX' => $curmx]; //$this->cIx += 3; } } @@ -77,7 +79,7 @@ function __destruct() { } function parse_data(&$retval) { - $arName = array(); + $arName = []; $byte = ord($this->gdi($this->cIx)); while($byte !== 0) { diff --git a/images/index.php b/images/index.php index a16f0e6..52af78f 100644 --- a/images/index.php +++ b/images/index.php @@ -1,4 +1,6 @@ 'HTTP Version Not Supported', ); -$httpcompressions = array( +$httpcompressions = [ 0 => '', 1 => 'aes128gcm', 2 => 'br', @@ -87,7 +89,7 @@ 9 => 'x-compress', 10 => 'x-gzip', 11 => 'zstd', -); +]; $webseer_minutes = array( 1 => __('%d Minute', 1, 'webseer'), @@ -113,10 +115,10 @@ 10 => __('%d Seconds', 10, 'webseer'), ); -$webseer_notify_formats = array( +$webseer_notify_formats = [ WEBSEER_FORMAT_HTML => 'html', WEBSEER_FORMAT_PLAIN => 'plain', -); +]; if (db_table_exists('plugin_webseer_contacts')) { $webseer_contact_users = db_fetch_assoc("SELECT pwc.id, pwc.data, pwc.type, ua.full_name @@ -125,10 +127,10 @@ ON ua.id=pwc.user_id WHERE pwc.data != ''"); } else { - $webseer_contact_users = array(); + $webseer_contact_users = []; } -$webseer_notify_accounts = array(); +$webseer_notify_accounts = []; if (!empty($webseer_contact_users)) { foreach ($webseer_contact_users as $webseer_contact_user) { $webseer_notify_accounts[$webseer_contact_user['id']] = $webseer_contact_user['full_name'] . ' - ' . ucfirst($webseer_contact_user['type']); @@ -211,14 +213,14 @@ 'size' => '40', 'default' => '' ), - 'id' => array( + 'id' => [ 'method' => 'hidden_zero', 'value' => '|arg1:id|' - ), - 'save_component_proxy' => array( + ], + 'save_component_proxy' => [ 'method' => 'hidden', 'value' => '1' - ) + ] ); $webseer_server_fields = array( @@ -275,10 +277,10 @@ 'value' => '|arg1:location|', 'max_length' => '256', ), - 'id' => array( + 'id' => [ 'method' => 'hidden_zero', 'value' => '|arg1:id|' - ), + ], ); $webseer_url_fields = array( @@ -433,8 +435,8 @@ 'description' => __('You may specify here extra Emails to receive alerts for this URL (comma separated)', 'webseer'), 'value' => '|arg1:notify_extra|', ), - 'id' => array( + 'id' => [ 'method' => 'hidden_zero', 'value' => '|arg1:id|' - ), + ], ); diff --git a/includes/constants.php b/includes/constants.php index aa99487..0788041 100644 --- a/includes/constants.php +++ b/includes/constants.php @@ -1,4 +1,6 @@ post($server['url'], $data); @@ -78,9 +80,9 @@ function plugin_webseer_refresh_servers() { foreach ($servers as $save) { db_execute_prepared('REPLACE INTO plugin_webseer_servers (id, enabled, master, name, url, ip, location) VALUES (?,?,?,?,?,?,?)', - array( + [ $save['id'], $save['enabled'], $save['master'], $save['name'], $save['url'], $save['ip'] , $save['location'] - ) + ] ); } } @@ -96,7 +98,7 @@ function plugin_webseer_refresh_urls () { $server['debug_type'] = 'Server'; $cc = new cURL(true, 'cookies.txt', 'gzip', '', $server); - $data = array(); + $data = []; $data['action'] = 'GETURLS'; $results = $cc->post($server['url'], $data); $results = explode("\n", $results); @@ -113,12 +115,12 @@ function plugin_webseer_refresh_urls () { db_execute_prepared('REPLACE INTO plugin_webseer_urls (id, enabled, requiresauth, checkcert, ip, display_name, notify_list, notify_accounts, url, search, search_maint, search_failed, notify_extra, downtrigger) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - array( + [ $save['id'], $save['enabled'], $save['requiresauth'], $save['checkcert'], $save['ip'], $save['display_name'], $save['notify_list'], $save['notify_accounts'], $save['url'], $save['search'], $save['search_maint'], $save['search_failed'], $save['notify_extra'], $save['downtrigger'] - ) + ] ); } } @@ -131,7 +133,7 @@ function plugin_webseer_refresh_urls () { function plugin_webseer_remove_old_users () { $users = db_fetch_assoc('SELECT id FROM user_auth'); - $u = array(); + $u = []; foreach ($users as $user) { $u[] = $user['id']; @@ -141,7 +143,7 @@ function plugin_webseer_remove_old_users () { foreach ($contacts as $c) { if (!in_array($c['user_id'], $u)) { - db_execute_prepared('DELETE FROM plugin_webseer_contacts WHERE user_id = ?', array($c['user_id'])); + db_execute_prepared('DELETE FROM plugin_webseer_contacts WHERE user_id = ?', [$c['user_id']]); } } } @@ -150,7 +152,7 @@ function plugin_webseer_check_dns ($host) { $results = false; if (cacti_sizeof($host)) { - $results = array(); + $results = []; $results['result'] = 0; $results['options']['http_code'] = 0; $results['error'] = ''; @@ -189,12 +191,12 @@ function plugin_webseer_set_remote_masters ($ip) { } db_execute('UPDATE plugin_webseer_servers set master = 0'); - db_execute_prepared('UPDATE plugin_webseer_servers set master = 1 WHERE ip = ?', array($ip)); + db_execute_prepared('UPDATE plugin_webseer_servers set master = 1 WHERE ip = ?', [$ip]); } function plugin_webseer_set_remote_master ($url, $ip) { $cc = new cURL(true, 'cookies.txt', 'gzip', '', $url); - $data = array(); + $data = []; $data['action'] = 'SETMASTER'; $data['ip'] = $ip; $results = $cc->post($url['url'], $data); @@ -205,7 +207,7 @@ function plugin_webseer_enable_remote_hosts ($id, $value = true) { foreach ($servers as $server) { $cc = new cURL(true, 'cookies.txt', 'gzip', '', $server); - $data = array(); + $data = []; $data['action'] = ($value ? 'ENABLEURL' : 'DISABLEURL'); $data['id'] = $id; $results = $cc->post($server['url'], $data); @@ -217,7 +219,7 @@ function plugin_webseer_delete_remote_hosts ($id) { foreach ($servers as $server) { $cc = new cURL(true, 'cookies.txt', 'gzip', '', $server); - $data = array(); + $data = []; $data['action'] = 'DELETEURL'; $data['id'] = $id; $results = $cc->post($server['url'], $data); @@ -281,7 +283,7 @@ function plugin_webseer_enable_remote_server ($id, $value = true) { $server['debug_type'] = 'Server'; $cc = new cURL(true, 'cookies.txt', 'gzip', '', $server); - $data = array(); + $data = []; $data['action'] = ($value ? 'ENABLESERVER' : 'DISABLESERVER'); $data['id'] = $id; $results = $cc->post($server['url'], $data); @@ -295,7 +297,7 @@ function plugin_webseer_delete_remote_server ($id) { $server['debug_type'] = 'Server'; $cc = new cURL(true, 'cookies.txt', 'gzip', '', $server); - $data = array(); + $data = []; $data['action'] = 'DELETESERVER'; $data['id'] = $id; $results = $cc->post($server['url'], $data); @@ -337,7 +339,7 @@ function plugin_webseer_check_debug() { } } -function plugin_webseer_debug($message='', $host=array()) { +function plugin_webseer_debug($message='', $host=[]) { global $debug; if ($debug) { $prefix = (empty($host['id']) && empty($host['debug_type'])) ? '' : '['; diff --git a/includes/index.php b/includes/index.php index a16f0e6..52af78f 100644 --- a/includes/index.php +++ b/includes/index.php @@ -1,4 +1,6 @@ 0) { $url['debug_type'] = 'Url'; @@ -150,7 +152,7 @@ $running = db_fetch_cell_prepared('SELECT COUNT(*) FROM plugin_webseer_processes WHERE poller_id = ?', - array($poller_id)); + [$poller_id]); if ($running == 0) { break; @@ -190,15 +192,15 @@ function plugin_webseer_register_server() { $found = db_fetch_cell_prepared('SELECT id FROM plugin_webseer_servers WHERE ip = ?', - array($ipaddress)); + [$ipaddress]); if (!$found) { - $found = array(); + $found = []; $found['debug_type'] = 'Server'; plugin_webseer_debug('Registering Server ' . $ipaddress, $found); - $save = array(); + $save = []; $save['enabled'] = 'on'; $save['isme'] = 1; $save['lastcheck'] = $lastcheck; @@ -238,9 +240,9 @@ function plugin_webseer_update_servers() { foreach ($servers as $server) { $server['debug_type'] = 'Server'; - $cc = new cURL(true, 'cookies.txt', $server['compression'], '', $server);; + $cc = new cURL(true, 'cookies.txt', $server['compression'], '', $server); - $data = array(); + $data = []; $data['action'] = 'HEARTBEAT'; $results = $cc->post($server['url'], $data); } diff --git a/remote.php b/remote.php index ab3aff6..c7263c0 100644 --- a/remote.php +++ b/remote.php @@ -1,4 +1,6 @@ 0) { - db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "on" WHERE id = ?', array($id)); + db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "on" WHERE id = ?', [$id]); plugin_webseer_enable_remote_hosts($id, true); } @@ -55,7 +57,7 @@ $id = get_filter_request_var('id'); if ($id > 0) { - db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "" WHERE id = ?', array($id)); + db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "" WHERE id = ?', [$id]); plugin_webseer_enable_remote_hosts($id, false); } @@ -110,18 +112,18 @@ function form_actions() { if (cacti_sizeof($urls)) { if ($action == WEBSEER_ACTION_URL_DELETE) { // delete foreach ($urls as $id) { - db_execute_prepared('DELETE FROM plugin_webseer_urls WHERE id = ?', array($id)); - db_execute_prepared('DELETE FROM plugin_webseer_urls_log WHERE url_id = ?', array($id)); + db_execute_prepared('DELETE FROM plugin_webseer_urls WHERE id = ?', [$id]); + db_execute_prepared('DELETE FROM plugin_webseer_urls_log WHERE url_id = ?', [$id]); plugin_webseer_delete_remote_hosts($id); } } elseif ($action == WEBSEER_ACTION_URL_DISABLE) { // disable foreach ($urls as $id) { - db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "" WHERE id = ?', array($id)); + db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "" WHERE id = ?', [$id]); plugin_webseer_enable_remote_hosts($id, false); } } elseif ($action == WEBSEER_ACTION_URL_ENABLE) { // enable foreach ($urls as $id) { - db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "on" WHERE id = ?', array($id)); + db_execute_prepared('UPDATE plugin_webseer_urls SET enabled = "on" WHERE id = ?', [$id]); plugin_webseer_enable_remote_hosts($id, true); } } elseif ($action == WEBSEER_ACTION_URL_DUPLICATE) { // duplicate @@ -129,7 +131,7 @@ function form_actions() { $newid = 1; foreach ($urls as $id) { - $save = db_fetch_row_prepared('SELECT * FROM plugin_webseer_urls WHERE id = ?', array($id)); + $save = db_fetch_row_prepared('SELECT * FROM plugin_webseer_urls WHERE id = ?', [$id]); $save['id'] = 0; $save['poller_id'] = 1; $save['display_name'] = 'New Service Check (' . $newid . ')'; @@ -165,7 +167,7 @@ function form_actions() { /* setup some variables */ $url_list = ''; - $url_array = array(); + $url_array = []; /* loop through each of the graphs selected on the previous page and get more info about them */ foreach ($_POST as $var => $val) { @@ -174,7 +176,7 @@ function form_actions() { input_validate_input_number($matches[1]); /* ==================================================== */ - $url_list .= '
  • ' . db_fetch_cell_prepared('SELECT display_name FROM plugin_webseer_urls WHERE id = ?', array($matches[1])) . '
  • '; + $url_list .= '
  • ' . db_fetch_cell_prepared('SELECT display_name FROM plugin_webseer_urls WHERE id = ?', [$matches[1]]) . '
  • '; $url_array[] = $matches[1]; } } @@ -338,9 +340,9 @@ function purge_log_events($id) { $name = db_fetch_cell_prepared('SELECT display_name FROM plugin_webseer_urls WHERE id = ?', - array($id)); + [$id]); - db_execute_prepared('DELETE FROM plugin_webseer_urls_log WHERE url_id = ?', array($id)); + db_execute_prepared('DELETE FROM plugin_webseer_urls_log WHERE url_id = ?', [$id]); raise_message('url_log_purged', __('The Service Check history was purged for %s', $name, 'webseer'), MESSAGE_LEVEL_INFO); } @@ -352,7 +354,7 @@ function webseer_edit_url() { get_filter_request_var('id'); /* ==================================================== */ - $url = array(); + $url = []; if (!isempty_request_var('id')) { $url = db_fetch_row_prepared('SELECT * FROM plugin_webseer_urls WHERE id = ?', array(get_request_var('id')), false); $header_label = __('Query [edit: %s]', $url['url'], 'webseer'); @@ -371,7 +373,7 @@ function webseer_edit_url() { draw_edit_form( array( - 'config' => array('form_name' => 'chk'), + 'config' => ['form_name' => 'chk'], 'fields' => inject_form_variables($webseer_url_fields, $url) ) ); @@ -455,15 +457,15 @@ function webseer_edit_url() { function webseer_request_validation() { /* ================= input validation and session storage ================= */ $filters = array( - 'rows' => array( + 'rows' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' - ), - 'page' => array( + ], + 'page' => [ 'filter' => FILTER_VALIDATE_INT, 'default' => '1' - ), + ], 'refresh' => array( 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, @@ -473,23 +475,23 @@ function webseer_request_validation() { 'filter' => FILTER_VALIDATE_IS_REGEX, 'default' => '', 'pageset' => true, - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), 'sort_column' => array( 'filter' => FILTER_CALLBACK, 'default' => 'display_name', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), 'sort_direction' => array( 'filter' => FILTER_CALLBACK, 'default' => 'ASC', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), - 'state' => array( + 'state' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' - ) + ] ); validate_store_request_vars($filters, 'sess_webseerurl'); @@ -501,33 +503,33 @@ function webseer_log_request_validation() { /* ================= input validation and session storage ================= */ $filters = array( - 'id' => array( + 'id' => [ 'filter' => FILTER_VALIDATE_INT, 'default' => '-1' - ), - 'rows' => array( + ], + 'rows' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' - ), - 'page' => array( + ], + 'page' => [ 'filter' => FILTER_VALIDATE_INT, 'default' => '1' - ), + ], 'filter' => array( 'filter' => FILTER_CALLBACK, 'default' => '', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), 'sort_column' => array( 'filter' => FILTER_CALLBACK, 'default' => 'lastcheck', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), 'sort_direction' => array( 'filter' => FILTER_CALLBACK, 'default' => 'DESC', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), ); @@ -675,16 +677,16 @@ function list_urls() { /* ================= input validation and session storage ================= */ $filters = array( - 'rows' => array( + 'rows' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' - ), - 'state' => array( + ], + 'state' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' - ), + ], 'refresh' => array( 'filter' => FILTER_VALIDATE_INT, 'default' => read_config_option('log_refresh_interval') @@ -692,12 +694,12 @@ function list_urls() { 'sort_column' => array( 'filter' => FILTER_CALLBACK, 'default' => 'display_name', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ), 'sort_direction' => array( 'filter' => FILTER_CALLBACK, 'default' => 'ASC', - 'options' => array('options' => 'sanitize_search_string') + 'options' => ['options' => 'sanitize_search_string'] ) ); @@ -1014,7 +1016,7 @@ function clearFilter() {