aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/snort/snort_alerts.js115
-rw-r--r--config/snort/snort_alerts.widget.php246
-rw-r--r--config/snort/widget-snort.inc24
3 files changed, 385 insertions, 0 deletions
diff --git a/config/snort/snort_alerts.js b/config/snort/snort_alerts.js
new file mode 100644
index 00000000..647eb1b1
--- /dev/null
+++ b/config/snort/snort_alerts.js
@@ -0,0 +1,115 @@
+
+var snorttimer;
+var snortisBusy = false;
+var snortisPaused = false;
+
+if (typeof getURL == 'undefined') {
+ getURL = function(url, callback) {
+ if (!url)
+ throw 'No URL for getURL';
+ try {
+ if (typeof callback.operationComplete == 'function')
+ callback = callback.operationComplete;
+ } catch (e) {}
+ if (typeof callback != 'function')
+ throw 'No callback function for getURL';
+ var http_request = null;
+ if (typeof XMLHttpRequest != 'undefined') {
+ http_request = new XMLHttpRequest();
+ }
+ else if (typeof ActiveXObject != 'undefined') {
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+ if (!http_request)
+ throw 'Both getURL and XMLHttpRequest are undefined';
+ http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ callback( { success : true,
+ content : http_request.responseText,
+ contentType : http_request.getResponseHeader("Content-Type") } );
+ }
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ }
+}
+
+function snort_alerts_fetch_new_events_callback(callback_data) {
+ var data_split;
+ var new_data_to_add = Array();
+ var data = callback_data.content;
+ data_split = data.split("\n");
+
+ // Loop through rows and generate replacement HTML
+ for(var x=0; x<data_split.length-1; x++) {
+ row_split = data_split[x].split("||");
+ var line = '';
+ line = '<td class="' + snortWidgetColClass + '">' + row_split[0] + '<br/>' + row_split[1] + '</td>';
+ line += '<td class="' + snortWidgetColClass + '" style="overflow: hidden; text-overflow: ellipsis;" nowrap>';
+ line += '<div style="display:inline;" title="' + row_split[2] + '">' + row_split[2] + '</div><br/>';
+ line += '<div style="display:inline;" title="' + row_split[3] + '">' + row_split[3] + '</div></td>';
+ line += '<td class="' + snortWidgetColClass + '">' + 'Priority: ' + row_split[4] + ' ' + row_split[5] + '</td>';
+ new_data_to_add[new_data_to_add.length] = line;
+ }
+ snort_alerts_update_div_rows(new_data_to_add);
+ snortisBusy = false;
+}
+
+function snort_alerts_update_div_rows(data) {
+ if(snortisPaused)
+ return;
+
+ var rows = $$('#snort-alert-entries>tr');
+
+ // Number of rows to move by
+ var move = rows.length + data.length - snort_nentries;
+ if (move < 0)
+ move = 0;
+
+ for (var i = rows.length - 1; i >= move; i--) {
+ rows[i].innerHTML = rows[i - move].innerHTML;
+ }
+
+ var tbody = $$('#snort-alert-entries');
+ for (var i = data.length - 1; i >= 0; i--) {
+ if (i < rows.length) {
+ rows[i].innerHTML = data[i];
+ } else {
+ var newRow = document.getElementById('snort-alert-entries').insertRow(0);
+ newRow.innerHTML = data[i];
+ }
+ }
+
+ // Add the even/odd class to each of the rows now
+ // they have all been added.
+ rows = $$('#snort-alert-entries>tr');
+ for (var i = 0; i < rows.length; i++) {
+ rows[i].className = i % 2 == 0 ? snortWidgetRowOddClass : snortWidgetRowEvenClass;
+ }
+}
+
+function fetch_new_snortalerts() {
+ if(snortisPaused)
+ return;
+ if(snortisBusy)
+ return;
+ snortisBusy = true;
+ getURL('/widgets/widgets/snort_alerts.widget.php?getNewAlerts=' + new Date().getTime(), snort_alerts_fetch_new_events_callback);
+}
+
+function snort_alerts_toggle_pause() {
+ if(snortisPaused) {
+ snortisPaused = false;
+ fetch_new_snortalerts();
+ } else {
+ snortisPaused = true;
+ }
+}
+/* start local AJAX engine */
+snorttimer = setInterval('fetch_new_snortalerts()', snortupdateDelay);
diff --git a/config/snort/snort_alerts.widget.php b/config/snort/snort_alerts.widget.php
new file mode 100644
index 00000000..0700ef2a
--- /dev/null
+++ b/config/snort/snort_alerts.widget.php
@@ -0,0 +1,246 @@
+<?php
+/*
+ snort_alerts.widget.php
+ Copyright (C) 2009 Jim Pingle
+ mod 24-07-2012
+ mod 28-02-2014 by Bill Meeks
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$nocsrf = true;
+
+require_once("guiconfig.inc");
+require_once("/usr/local/www/widgets/include/widget-snort.inc");
+
+global $config, $g;
+
+/* retrieve snort variables */
+if (!is_array($config['installedpackages']['snortglobal']['rule']))
+ $config['installedpackages']['snortglobal']['rule'] = array();
+$a_instance = &$config['installedpackages']['snortglobal']['rule'];
+
+// Test pfSense version and set different CSS class variables
+// depending on version. 2.1 offers enhanced CSS styles.
+$pfs_version=substr(trim(file_get_contents("/etc/version")),0,3);
+if ($pfs_version > '2.0') {
+ $alertRowEvenClass = "listMReven";
+ $alertRowOddClass = "listMRodd";
+ $alertColClass = "listMRr";
+}
+else {
+ $alertRowEvenClass = "listr";
+ $alertRowOddClass = "listr";
+ $alertColClass = "listr";
+}
+
+/* check if Snort widget alert display lines value is set */
+$snort_nentries = $config['widgets']['widget_snort_display_lines'];
+if (!isset($snort_nentries) || $snort_nentries < 0)
+ $snort_nentries = 5;
+
+/* array sorting of the alerts */
+function sksort(&$array, $subkey="id", $sort_ascending=false) {
+ /* an empty array causes sksort to fail - this test alleviates the error */
+ if(empty($array))
+ return false;
+ if (count($array)) {
+ $temp_array[key($array)] = array_shift($array);
+ };
+ foreach ($array as $key => $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;
+};
+
+// Called by Ajax to update the "snort-alert-entries" <tbody> table element's contents
+if (isset($_GET['getNewAlerts'])) {
+ $response = "";
+ $s_alerts = snort_widget_get_alerts();
+ $counter = 0;
+ foreach ($s_alerts as $a) {
+ $response .= $a['instanceid'] . " " . $a['dateonly'] . "||" . $a['timeonly'] . "||" . $a['src'] . "||";
+ $response .= $a['dst'] . "||" . $a['priority'] . "||" . $a['category'] . "\n";
+ $counter++;
+ if($counter >= $snort_nentries)
+ break;
+ }
+ echo $response;
+ return;
+}
+
+// See if saving new display line count value
+if(isset($_POST['widget_snort_display_lines'])) {
+ $config['widgets']['widget_snort_display_lines'] = $_POST['widget_snort_display_lines'];
+ write_config("Saved Snort Alerts Widget Displayed Lines Parameter via Dashboard");
+ header("Location: ../../index.php");
+}
+
+// Read "$snort_nentries" worth of alerts from the top of the alert.log file
+// of each configured interface, and then return the most recent '$snort_entries'
+// alerts in a sorted array (most recent alert first).
+function snort_widget_get_alerts() {
+
+ global $config, $a_instance, $snort_nentries;
+ $snort_alerts = array();
+ /* read log file(s) */
+ $counter=0;
+ foreach ($a_instance as $instanceid => $instance) {
+ $snort_uuid = $a_instance[$instanceid]['uuid'];
+ $if_real = get_real_interface($a_instance[$instanceid]['interface']);
+
+ /* make sure alert file exists, then "tail" the last '$snort_nentries' from it */
+ if (file_exists("/var/log/snort/snort_{$if_real}{$snort_uuid}/alert")) {
+ exec("tail -{$snort_nentries} -r /var/log/snort/snort_{$if_real}{$snort_uuid}/alert > /tmp/alert_snort{$snort_uuid}");
+
+ if (file_exists("/tmp/alert_snort{$snort_uuid}")) {
+
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */
+ /* File format: timestamp,generator_id,sig_id,sig_rev,msg,proto,src,srcport,dst,dstport,id,classification,priority */
+ $fd = fopen("/tmp/alert_snort{$snort_uuid}", "r");
+ while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) {
+ if(count($fields) < 13)
+ continue;
+
+ // Get the Snort interface this alert was received from
+ $snort_alerts[$counter]['instanceid'] = strtoupper($a_instance[$instanceid]['interface']);
+
+ // "fields[0]" is the complete timestamp in ASCII form. Convert
+ // to a UNIX timestamp so we can use it for various date and
+ // time formatting. Also extract the MM/DD/YY component and
+ // reverse its order to YY/MM/DD for proper sorting.
+ $fields[0] = trim($fields[0]); // remove trailing space before comma delimiter
+ $tstamp = strtotime(str_replace("-", " ", $fields[0])); // remove "-" between date and time components
+ $tmp = substr($fields[0],6,2) . '/' . substr($fields[0],0,2) . '/' . substr($fields[0],3,2);
+ $snort_alerts[$counter]['timestamp'] = str_replace(substr($fields[0],0,8),$tmp,$fields[0]);
+
+ $snort_alerts[$counter]['timeonly'] = date("H:i:s", $tstamp);
+ $snort_alerts[$counter]['dateonly'] = date("M d", $tstamp);
+ // Add square brackets around any any IPv6 address
+ if (strpos($fields[6], ":") === FALSE)
+ $snort_alerts[$counter]['src'] = trim($fields[6]);
+ else
+ $snort_alerts[$counter]['src'] = "[" . trim($fields[6]) . "]";
+ // Add the SRC PORT if not null
+ if (!empty($fields[7]))
+ $snort_alerts[$counter]['src'] .= ":" . trim($fields[7]);
+ // Add square brackets around any any IPv6 address
+ if (strpos($fields[8], ":") === FALSE)
+ $snort_alerts[$counter]['dst'] = trim($fields[8]);
+ else
+ $snort_alerts[$counter]['dst'] = "[" . trim($fields[8]) . "]";
+ // Add the DST PORT if not null
+ if (!empty($fields[9]))
+ $snort_alerts[$counter]['dst'] .= ":" . trim($fields[9]);
+ $snort_alerts[$counter]['priority'] = trim($fields[12]);
+ $snort_alerts[$counter]['category'] = trim($fields[11]);
+ $counter++;
+ };
+ fclose($fd);
+ @unlink("/tmp/alert_snort{$snort_uuid}");
+ };
+ };
+ };
+
+ /* sort the alerts array */
+ if (isset($config['syslog']['reverse'])) {
+ sksort($snort_alerts, 'timestamp', false);
+ } else {
+ sksort($snort_alerts, 'timestamp', true);
+ };
+
+ return $snort_alerts;
+}
+?>
+
+<input type="hidden" id="snort_alerts-config" name="snort_alerts-config" value="" />
+<div id="snort_alerts-settings" class="widgetconfigdiv" style="display:none;">
+ <form action="/widgets/widgets/snort_alerts.widget.php" method="post" name="iformd">
+ Enter number of recent alerts to display (default is 5)<br/>
+ <input type="text" size="5" name="widget_snort_display_lines" class="formfld unknown" id="widget_snort_display_lines" value="<?= $config['widgets']['widget_snort_display_lines'] ?>" />
+ &nbsp;&nbsp;<input id="submitd" name="submitd" type="submit" class="formbtn" value="Save" />
+ </form>
+</div>
+
+<table id="snort-alert-tbl" width="100%" border="0" cellspacing="0" cellpadding="0" style="table-layout: fixed;">
+ <colgroup>
+ <col style="width: 24%;" />
+ <col style="width: 38%;" />
+ <col style="width: 38%;" />
+ </colgroup>
+ <thead>
+ <tr>
+ <th class="widgetsubheader"><?=gettext("IF/Date");?></th>
+ <th class="widgetsubheader"><?=gettext("Src/Dst Address");?></th>
+ <th class="widgetsubheader"><?=gettext("Classification");?></th>
+ </tr>
+ </thead>
+ <tbody id="snort-alert-entries">
+ <?php
+ $snort_alerts = snort_widget_get_alerts();
+ $counter=0;
+ if (is_array($snort_alerts)) {
+ foreach ($snort_alerts as $alert) {
+ $alertRowClass = $counter % 2 ? $alertRowEvenClass : $alertRowOddClass;
+ echo(" <tr class='" . $alertRowClass . "'>
+ <td class='" . $alertColClass . "'>" . $alert['instanceid'] . "&nbsp;" . $alert['dateonly'] . "<br/>" . $alert['timeonly'] . "</td>
+ <td class='" . $alertColClass . "' style='overflow: hidden; text-overflow: ellipsis;' nowrap><div style='display:inline;' title='" . $alert['src'] . "'>" . $alert['src'] . "</div><br/><div style='display:inline;' title='" . $alert['dst'] . "'>" . $alert['dst'] . "</div></td>
+ <td class='" . $alertColClass . "'>Priority: " . $alert['priority'] . " " . $alert['category'] . "</td></tr>");
+ $counter++;
+ if($counter >= $snort_nentries)
+ break;
+ }
+ }
+ ?>
+ </tbody>
+</table>
+
+<script type="text/javascript">
+//<![CDATA[
+<!-- needed in the snort_alerts.js file code -->
+ var snortupdateDelay = 10000; // update every 10 seconds
+ var snort_nentries = <?=$snort_nentries;?>; // number of alerts to display (5 is default)
+ var snortWidgetRowEvenClass = "<?=$alertRowEvenClass;?>"; // allows alternating background on 2.1 and higher
+ var snortWidgetRowOddClass = "<?=$alertRowOddClass;?>"; // allows alternating background on 2.1 and higher
+ var snortWidgetColClass = "<?=$alertColClass;?>"; // sets column CSS style (different on 2.1 and higher)
+
+<!-- needed to display the widget settings menu -->
+ selectIntLink = "snort_alerts-configure";
+ textlink = document.getElementById(selectIntLink);
+ textlink.style.display = "inline";
+//]]>
+</script>
+
diff --git a/config/snort/widget-snort.inc b/config/snort/widget-snort.inc
new file mode 100644
index 00000000..3c4d9718
--- /dev/null
+++ b/config/snort/widget-snort.inc
@@ -0,0 +1,24 @@
+<?php
+require_once("config.inc");
+
+//set variables for custom title and link
+$snort_alerts_title = "Snort Alerts";
+$snort_alerts_title_link = "snort/snort_alerts.php";
+
+function widget_snort_uninstall() {
+
+ global $config;
+
+ /* Remove the Snort widget from the Dashboard display list */
+ $widgets = $config['widgets']['sequence'];
+ if (!empty($widgets)) {
+ $widgetlist = explode(",", $widgets);
+ foreach ($widgetlist as $key => $widget) {
+ if (strstr($widget, "snort_alerts-container"))
+ unset($widgetlist[$key]);
+ }
+ $config['widgets']['sequence'] = implode(",", $widgetlist);
+ write_config();
+ }
+}
+?>