<?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']; // Set some CSS class variables $alertRowEvenClass = "listMReven"; $alertRowOddClass = "listMRodd"; $alertColClass = "listMRr"; /* 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['msg'] . "\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]['msg'] = trim($fields[4]); $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'] ?>" /> <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("Description");?></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='listMRr'>" . $alert['instanceid'] . " " . $alert['dateonly'] . "<br/>" . $alert['timeonly'] . "</td> <td class='listMRr' 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='listMRr'><div style='display: fixed; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2em; max-height: 2.4em; overflow: hidden; text-overflow: ellipsis;' title='{$alert['msg']}'>" . $alert['msg'] . "</div></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 var snortWidgetRowOddClass = "<?=$alertRowOddClass;?>"; // allows alternating background <!-- needed to display the widget settings menu --> selectIntLink = "snort_alerts-configure"; textlink = document.getElementById(selectIntLink); textlink.style.display = "inline"; //]]> </script>