From f0fd2cb8f5b76369a28467c93cc1c5b7c331191a Mon Sep 17 00:00:00 2001 From: bmeeks8 Date: Fri, 28 Feb 2014 20:21:17 -0500 Subject: Add built-in Dashboard Widget for Suricata and make it persistent. --- config/suricata/suricata_alerts.js | 92 +++++++++++++ config/suricata/suricata_alerts.widget.php | 213 +++++++++++++++++++++++++++++ config/suricata/suricata_post_install.php | 10 +- config/suricata/suricata_uninstall.php | 25 ++++ config/suricata/widget-suricata.inc | 8 ++ 5 files changed, 346 insertions(+), 2 deletions(-) create mode 100644 config/suricata/suricata_alerts.js create mode 100644 config/suricata/suricata_alerts.widget.php create mode 100644 config/suricata/widget-suricata.inc diff --git a/config/suricata/suricata_alerts.js b/config/suricata/suricata_alerts.js new file mode 100644 index 00000000..7678656d --- /dev/null +++ b/config/suricata/suricata_alerts.js @@ -0,0 +1,92 @@ + +var suricatalines = Array(); +var suricatatimer; +var suricataisBusy = false; +var suricataisPaused = false; + +function suricata_alerts_fetch_new_rules() { + + //get new alerts from suricata_alerts.widget.php + url = "/widgets/widgets/suricata_alerts.widget.php?getNewAlerts=1" + new Date().getTime(); + + jQuery.ajax(url, { + type: 'GET', + success: function(callback_data) { + var data_split; + var new_data_to_add = Array(); + var data = callback_data; + + data_split = data.split("\n"); + + // Loop through rows and generate replacement HTML + for(var x=0; x' + row_split[1] + ''; + line += '' + row_split[2] + '
' + row_split[3] + ''; + line += '' + 'Priority: ' + row_split[4] + '
' + row_split[5] + ''; + new_data_to_add[new_data_to_add.length] = line; + } + suricata_alerts_update_div_rows(new_data_to_add); + suricataisBusy = false; + } + }); +} +function suricata_alerts_update_div_rows(data) { + if(suricataisPaused) + return; + + var isIE = navigator.appName.indexOf('Microsoft') != -1; + var isSafari = navigator.userAgent.indexOf('Safari') != -1; + var isOpera = navigator.userAgent.indexOf('Opera') != -1; + + var rows = jQuery('#suricata-alert-entries>tr'); + + // Number of rows to move by + var move = rows.length + data.length - nentries; + if (move < 0) + move = 0; + + for (var i = move; i < rows.length; i++) { + jQuery(rows[i - move]).html(jQuery(rows[i]).html()); + } + + var tbody = jQuery('#suricata-alert-entries'); + for (var i = 0; i < data.length; i++) { + var rowIndex = rows.length - move + i; + if (rowIndex < rows.length) { + jQuery(rows[rowIndex]).html(data[i]); + } else { + jQuery(tbody).append('' + data[i] + ''); + } + } + + // Add the even/odd class to each of the rows now + // they have all been added. + rows = jQuery('#suricata-alert-entries>tr'); + for (var i = 0; i < rows.length; i++) { + rows[i].className = i % 2 == 0 ? 'listMRodd' : 'listMReven'; + } +} + +function fetch_new_surialerts() { + if(suricataisPaused) + return; + if(suricataisBusy) + return; + + //get new alerts from suricata_alerts.widget.php + suricataisBusy = true; + suricata_alerts_fetch_new_rules(); +} + +function suricata_alerts_toggle_pause() { + if(suricataisPaused) { + suricataisPaused = false; + fetch_new_surialerts(); + } else { + suricataisPaused = true; + } +} +/* start local AJAX engine */ +suricatatimer = setInterval('fetch_new_surialerts()', suricataupdateDelay); diff --git a/config/suricata/suricata_alerts.widget.php b/config/suricata/suricata_alerts.widget.php new file mode 100644 index 00000000..fabb9314 --- /dev/null +++ b/config/suricata/suricata_alerts.widget.php @@ -0,0 +1,213 @@ + $val){ + $offset = 0; + $found = false; + foreach ($temp_array as $tmp_key => $tmp_val) { + if (!$found and strtolower($val[$subkey]) > strtolower($tmp_val[$subkey])) { + $temp_array = array_merge((array)array_slice($temp_array,0,$offset), array($key => $val), array_slice($temp_array,$offset)); + $found = true; + }; + $offset++; + }; + if (!$found) $temp_array = array_merge($temp_array, array($key => $val)); + }; + + if ($sort_ascending) { + $array = array_reverse($temp_array); + } else $array = $temp_array; + /* below is the complement for empty array test */ + return true; +}; + +/* check if firewall widget variable is set */ +$nentries = $config['widgets']['widget_suricata_display_lines']; +if (!isset($nentries) || $nentries < 0) + $nentries = 5; + +// Called by Ajax to update alerts table contents +if (isset($_GET['getNewAlerts'])) { + $response = ""; + $suri_alerts = suricata_widget_get_alerts(); + $counter = 0; + foreach ($suri_alerts as $a) { + $response .= $a['instanceid'] . " " . $a['dateonly'] . "||" . $a['timeonly'] . "||" . $a['src'] . ":" . $a['srcport'] . "||"; + $response .= $a['dst'] . ":" . $a['dstport'] . "||" . $a['priority'] . "||" . $a['category'] . "\n"; + $counter++; + if($counter >= $nentries) + break; + } + echo $response; + return; +} + +if(isset($_POST['widget_suricata_display_lines'])) { + $config['widgets']['widget_suricata_display_lines'] = $_POST['widget_suricata_display_lines']; + write_config("Saved Suricata Alerts Widget Displayed Lines Parameter via Dashboard"); + header("Location: ../../index.php"); +} + +// Read "$nentries" worth of alerts from the top of the alerts.log file +function suricata_widget_get_alerts() { + + global $config, $a_instance, $nentries; + $suricata_alerts = array(); + + /* read log file(s) */ + $counter=0; + foreach ($a_instance as $instanceid => $instance) { + $suricata_uuid = $a_instance[$instanceid]['uuid']; + $if_real = get_real_interface($a_instance[$instanceid]['interface']); + + // make sure alert file exists, then grab the most recent {$nentries} from it + // and write them to a temp file. + if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log")) { + exec("tail -{$nentries} -r /var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log > /tmp/surialerts_{$suricata_uuid}"); + if (file_exists("/tmp/surialerts_{$suricata_uuid}")) { + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* File format: timestamp,action,sig_generator,sig_id,sig_rev,msg,classification,priority,proto,src,srcport,dst,dstport */ + $fd = fopen("/tmp/surialerts_{$suricata_uuid}", "r"); + while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { + if(count($fields) < 12) + continue; + + // Create a DateTime object from the event timestamp that + // we can use to easily manipulate output formats. + $event_tm = date_create_from_format("m/d/Y-H:i:s.u", $fields[0]); + + // Check the 'CATEGORY' field for the text "(null)" and + // substitute "No classtype defined". + if ($fields[6] == "(null)") + $fields[6] = "No classtype assigned"; + + $suricata_alerts[$counter]['instanceid'] = strtoupper($a_instance[$instanceid]['interface']); + $suricata_alerts[$counter]['timestamp'] = strval(date_timestamp_get($event_tm)); + $suricata_alerts[$counter]['timeonly'] = date_format($event_tm, "H:i:s"); + $suricata_alerts[$counter]['dateonly'] = date_format($event_tm, "M d"); + $suricata_alerts[$counter]['src'] = inet_ntop(inet_pton($fields[9])); + $suricata_alerts[$counter]['srcport'] = $fields[10]; + $suricata_alerts[$counter]['dst'] = inet_ntop(inet_pton($fields[11])); + $suricata_alerts[$counter]['dstport'] = $fields[12]; + $suricata_alerts[$counter]['priority'] = $fields[7]; + $suricata_alerts[$counter]['category'] = $fields[6]; + $counter++; + }; + fclose($fd); + @unlink("/tmp/surialerts_{$suricata_uuid}"); + }; + }; + }; + + // Sort the alerts in descending order + sksort($suricata_alerts, 'timestamp', false); + + return $suricata_alerts; +} + +/* display the result */ +?> + + + + + + + + + + + + + + + + + + + "); + $counter++; + if($counter >= $nentries) + break; + } + } + ?> + +
IF/DateSrc/DstDetails
" . $alert['instanceid'] . " " . $alert['dateonly'] . "
" . $alert['timeonly'] . "
" . $alert['src'] . ":" . $alert['srcport'] . "
" . $alert['dst'] . ":" . $alert['dstport'] . "
Priority: " . $alert['priority'] . "
" . $alert['category'] . "
+ + + + diff --git a/config/suricata/suricata_post_install.php b/config/suricata/suricata_post_install.php index 6603d5ab..72257325 100644 --- a/config/suricata/suricata_post_install.php +++ b/config/suricata/suricata_post_install.php @@ -89,7 +89,7 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = // ## BETA pkg bug fix-up -- be sure default rules enabled ## $rules = explode("||", $value['rulesets']); - foreach (array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules" ) as $r){ + foreach (array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ) as $r){ if (!in_array($r, $rules)) $rules[] = $r; } @@ -117,6 +117,12 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = // Add the recurring jobs created above to crontab configure_cron(); + // Restore the Dashboard Widget if it was previously enabled and saved + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget']) && !empty($config['widgets']['sequence'])) + $config['widgets']['sequence'] .= "," . $config['installedpackages']['suricata']['config'][0]['dashboard_widget']; + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows']) && !empty($config['widgets'])) + $config['widgets']['widget_suricata_display_lines'] = $config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows']; + $rebuild_rules = false; update_output_window(gettext("Finished rebuilding Suricata configuration files...")); log_error(gettext("[Suricata] Finished rebuilding installation from saved settings...")); @@ -132,7 +138,7 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = } // Update Suricata package version in configuration -$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "0.1-BETA"; +$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "v0.2-BETA"; write_config(); // Done with post-install, so clear flag diff --git a/config/suricata/suricata_uninstall.php b/config/suricata/suricata_uninstall.php index 0a7f8d5a..b8ea6097 100644 --- a/config/suricata/suricata_uninstall.php +++ b/config/suricata/suricata_uninstall.php @@ -76,6 +76,31 @@ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') mwexec("/bin/rm -rf /usr/local/pkg/suricata"); mwexec("/bin/rm -rf /usr/local/www/suricata"); +/* Remove our associated Dashboard widget config and files. */ +/* If "save settings" is enabled, then save old widget */ +/* container settings so we can restore them later. */ +$widgets = $config['widgets']['sequence']; +if (!empty($widgets)) { + $widgetlist = explode(",", $widgets); + foreach ($widgetlist as $key => $widget) { + if (strstr($widget, "suricata_alerts-container")) { + if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] == 'on') { + $config['installedpackages']['suricata']['config'][0]['dashboard_widget'] = $widget; + if ($config['widgets']['widget_suricata_display_lines']) { + $config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows'] = $config['widgets']['widget_suricata_display_lines']; + unset($config['widgets']['widget_suricata_display_lines']); + } + } + unset($widgetlist[$key]); + } + } + $config['widgets']['sequence'] = implode(",", $widgetlist); + write_config(); +} +@unlink("/usr/local/www/widgets/include/widget-suricata.inc"); +@unlink("/usr/local/www/widgets/widgets/suricata_alerts.widget.php"); +@unlink("/usr/local/www/widgets/javascript/suricata_alerts.js"); + /* Keep this as a last step */ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] != 'on') { log_error(gettext("Not saving settings... all Suricata configuration info and logs deleted...")); diff --git a/config/suricata/widget-suricata.inc b/config/suricata/widget-suricata.inc new file mode 100644 index 00000000..48424588 --- /dev/null +++ b/config/suricata/widget-suricata.inc @@ -0,0 +1,8 @@ + -- cgit v1.2.3