diff options
author | Renato Botelho <garga@FreeBSD.org> | 2014-09-06 10:28:55 -0300 |
---|---|---|
committer | Renato Botelho <garga@FreeBSD.org> | 2014-09-06 10:28:55 -0300 |
commit | 81ff18ddc45fff6018e7e052c865aaa4f85cfe14 (patch) | |
tree | 724108d95af058335d078040aca6ec6aeaeb1746 /config/suricata | |
parent | 200641d3d2e8dcaf66bb5c141def1b4ad109df3b (diff) | |
parent | ad7e3dca2b915b9f27ba01bade962305a0dd34bb (diff) | |
download | pfsense-packages-81ff18ddc45fff6018e7e052c865aaa4f85cfe14.tar.gz pfsense-packages-81ff18ddc45fff6018e7e052c865aaa4f85cfe14.tar.bz2 pfsense-packages-81ff18ddc45fff6018e7e052c865aaa4f85cfe14.zip |
Merge pull request #696 from bmeeks8/suricata-2.0.3-v2.0
Diffstat (limited to 'config/suricata')
42 files changed, 5149 insertions, 800 deletions
diff --git a/config/suricata/disablesid-sample.conf b/config/suricata/disablesid-sample.conf new file mode 100644 index 00000000..026f4d94 --- /dev/null +++ b/config/suricata/disablesid-sample.conf @@ -0,0 +1,43 @@ +# example disablesid.conf + +# Example of modifying state for individual rules +# 1:1034,1:9837,1:1270,1:3390,1:710,1:1249,3:13010 + +# Example of modifying state for rule ranges +# 1:220-1:3264,3:13010-3:13013 + +# Comments are allowed in this file, and can also be on the same line +# As the modify state syntax, as long as it is a trailing comment +# 1:1011 # I Disabled this rule because I could! + +# Example of modifying state for MS and cve rules, note the use of the : +# in cve. This will modify MS09-008, cve 2009-0233, bugtraq 21301, +# and all MS00 and all cve 2000 related sids! These support regular expression +# matching only after you have specified what you are looking for, i.e. +# MS00-<regex> or cve:<regex>, the first section CANNOT contain a regular +# expression (MS\d{2}-\d+) will NOT work, use the pcre: keyword (below) +# for this. +# MS09-008,cve:2009-0233,bugtraq:21301,MS00-\d+,cve:2000-\d+ + +# Example of using the pcre: keyword to modify rulestate. the pcre keyword +# allows for full use of regular expression syntax, you do not need to designate +# with / and all pcre searches are treated as case insensitive. For more information +# about regular expression syntax: http://www.regular-expressions.info/ +# The following example modifies state for all MS07 through MS10 +# pcre:MS(0[7-9]|10)-\d+ +# pcre:"Joomla" + +# Example of modifying state for specific categories entirely. +# "snort_" limits to Snort VRT rules, "emerging-" limits to +# Emerging Threats Open rules, "etpro-" limits to ET-PRO rules. +# "shellcode" with no prefix would match in any vendor set. +# snort_web-iis,emerging-shellcode,etpro-imap,shellcode + +# Any of the above values can be on a single line or multiple lines, when +# on a single line they simply need to be separated by a , +# 1:9837,1:220-1:3264,3:13010-3:13013,pcre:MS(0[0-7])-\d+,MS09-008,cve:2009-0233 + +# The modifications in this file are for sample/example purposes only and +# should not actively be used, you need to modify this file to fit your +# environment. + diff --git a/config/suricata/enablesid-sample.conf b/config/suricata/enablesid-sample.conf new file mode 100644 index 00000000..4cccc5dd --- /dev/null +++ b/config/suricata/enablesid-sample.conf @@ -0,0 +1,39 @@ +# example enablesid.conf + +# Example of modifying state for individual rules +# 1:1034,1:9837,1:1270,1:3390,1:710,1:1249,3:13010 + +# Example of modifying state for rule ranges +# 1:220-1:3264,3:13010-3:13013 + +# Comments are allowed in this file, and can also be on the same line +# As the modify state syntax, as long as it is a trailing comment +# 1:1011 # I Disabled this rule because I could! + +# Example of modifying state for MS and cve rules, note the use of the : +# in cve. This will modify MS09-008, cve 2009-0233, bugtraq 21301, +# and all MS00 and all cve 2000 related sids! These support regular expression +# matching only after you have specified what you are looking for, i.e. +# MS00-<regex> or cve:<regex>, the first section CANNOT contain a regular +# expression (MS\d{2}-\d+) will NOT work, use the pcre: keyword (below) +# for this. +# MS09-008,cve:2009-0233,bugtraq:21301,MS00-\d+,cve:2000-\d+ + +# Example of using the pcre: keyword to modify rulestate. the pcre keyword +# allows for full use of regular expression syntax, you do not need to designate +# with / and all pcre searches are treated as case insensitive. For more information +# about regular expression syntax: http://www.regular-expressions.info/ +# The following example modifies state for all MS07 through MS10 +# pcre:MS(0[7-9]|10)-\d+ +# pcre:"Joomla" + +# Example of modifying state for specific categories entirely. +# "snort_" limits to Snort VRT rules, "emerging-" limits to +# Emerging Threats Open rules, "etpro-" limits to ET-PRO rules. +# "shellcode" with no prefix would match in any vendor set. +# snort_web-iis,emerging-shellcode,etpro-imap,shellcode + +# Any of the above values can be on a single line or multiple lines, when +# on a single line they simply need to be separated by a , +# 1:9837,1:220-1:3264,3:13010-3:13013,pcre:MS(0[0-7])-\d+,MS09-008,cve:2009-0233 + diff --git a/config/suricata/modifysid-sample.conf b/config/suricata/modifysid-sample.conf new file mode 100644 index 00000000..d59f84ba --- /dev/null +++ b/config/suricata/modifysid-sample.conf @@ -0,0 +1,23 @@ +# example modifysid.conf +# +# formatting is simple +# <sid or sid list> "what I'm replacing" "what I'm replacing it with" +# +# Note that this will only work with GID:1 rules, simply because modifying +# GID:3 SO stub rules would not actually affect the rule. +# +# If you are attempting to change rulestate (enable,disable) from here +# then you are doing it wrong. Do this from within the respective +# rulestate modification configuration files. + +# the following applies to sid 10010 only and represents what would normally +# be s/to_client/from_server/ +# 10010 "to_client" "from_server" + +# the following would replace HTTP_PORTS with HTTPS_PORTS for ALL GID:1 +# rules +# "HTTP_PORTS" "HTTPS_PORTS" + +# multiple sids can be specified as noted below: +# 302,429,1821 "\$EXTERNAL_NET" "\$HOME_NET" + diff --git a/config/suricata/suricata.inc b/config/suricata/suricata.inc index 89bb572f..ca4ade1c 100644 --- a/config/suricata/suricata.inc +++ b/config/suricata/suricata.inc @@ -47,6 +47,9 @@ require_once("filter.inc"); global $g, $config; +// Suricata GUI needs some extra PHP memory space to manipulate large rules arrays +ini_set("memory_limit", "256M"); + if (!is_array($config['installedpackages']['suricata'])) $config['installedpackages']['suricata'] = array(); @@ -70,11 +73,12 @@ define('SURICATALOGDIR', '/var/log/suricata/'); define('RULES_UPD_LOGFILE', SURICATALOGDIR . 'suricata_rules_update.log'); define('ENFORCING_RULES_FILENAME', 'suricata.rules'); define('FLOWBITS_FILENAME', 'flowbit-required.rules'); +define('SID_MODS_PATH', '/var/db/suricata/sidmods/'); +define('IPREP_PATH', '/var/db/suricata/iprep/'); // Rule set download filenames and prefixes define('ET_DNLD_FILENAME', 'emerging.rules.tar.gz'); define('ETPRO_DNLD_FILENAME', 'etpro.rules.tar.gz'); -define('VRT_DNLD_FILENAME', 'snortrules-snapshot-edge.tar.gz'); define('GPLV2_DNLD_FILENAME', 'community-rules.tar.gz'); define('VRT_FILE_PREFIX', 'snort_'); define('GPL_FILE_PREFIX', 'GPLv2_'); @@ -183,7 +187,6 @@ function suricata_reload_config($suricatacfg, $signal="USR2") { /******************************************************/ if (isvalidpid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) { log_error("[Suricata] Suricata LIVE RULE RELOAD initiated for {$suricatacfg['descr']} ({$if_real})..."); -// sigkillbypid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid", $signal); mwexec_bg("/bin/pkill -{$signal} -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid"); } } @@ -212,7 +215,6 @@ function suricata_barnyard_reload_config($suricatacfg, $signal="HUP") { /******************************************************/ if (isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid")) { log_error("[Suricata] Barnyard2 CONFIG RELOAD initiated for {$suricatacfg['descr']} ({$if_real})..."); -// sigkillbypid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid", $signal); mwexec_bg("/bin/pkill -{$signal} -F {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid"); } } @@ -255,7 +257,7 @@ function suricata_find_list($find_name, $type = 'passlist') { return array(); } -function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { +function suricata_build_list($suricatacfg, $listname = "", $passlist = false, $externallist = false) { /***********************************************************/ /* The default is to build a HOME_NET variable unless */ @@ -265,9 +267,10 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { global $config, $g, $aliastable, $filterdns; $home_net = array(); - if ($listname == 'default' || empty($listname)) { + if (!$externallist && ($listname == 'default' || empty($listname))) { $localnet = 'yes'; $wanip = 'yes'; $wangw = 'yes'; $wandns = 'yes'; $vips = 'yes'; $vpns = 'yes'; - } else { + } + else { $list = suricata_find_list($listname); if (empty($list)) return $list; @@ -281,21 +284,25 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { $home_net = explode(" ", trim(filter_expand_alias($list['address']))); } - // Always add loopback to HOME_NET and passlist (ftphelper) - if (!in_array("127.0.0.1", $home_net)) - $home_net[] = "127.0.0.1"; + // Always add loopback to HOME_NET and passlist + if (!$externallist) { + if (!in_array("127.0.0.1/32", $home_net)) + $home_net[] = "127.0.0.1/32"; + if (!in_array("::1/128", $home_net)) + $home_net[] = "::1/128"; + } /********************************************************************/ /* Always put the interface running Suricata in HOME_NET and */ - /* whitelist unless it's the WAN. WAN options are handled further */ + /* pass list unless it's the WAN. WAN options are handled further */ /* down. If the user specifically chose not to include LOCAL_NETS */ /* in the PASS LIST, then do not include the Suricata interface */ /* subnet in the PASS LIST. We do include the actual LAN interface */ /* IP for Suricata, though, to prevent locking out the firewall. */ /********************************************************************/ $suricataip = get_interface_ip($suricatacfg['interface']); - if (!$whitelist || $localnet == 'yes' || empty($localnet)) { - if (is_ipaddr($suricataip)) { + if (($externallist && $localnet == 'yes') || (!$externallist && (!$passlist || $localnet == 'yes' || empty($localnet)))) { + if (is_ipaddrv4($suricataip)) { if ($suricatacfg['interface'] <> "wan") { $sn = get_interface_subnet($suricatacfg['interface']); $ip = gen_subnet($suricataip, $sn) . "/{$sn}"; @@ -304,15 +311,19 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { } } } - else { - if (is_ipaddr($suricataip)) { - if (!in_array($suricataip, $home_net)) - $home_net[] = $suricataip; + elseif (!$externallist && $localnet != 'yes') { + if (is_ipaddrv4($suricataip)) { + if (!in_array($suricataip . "/32", $home_net)) + $home_net[] = $suricataip . "/32"; } } + // Grab the IPv6 address if we have one assigned $suricataip = get_interface_ipv6($suricatacfg['interface']); - if (!$whitelist || $localnet == 'yes' || empty($localnet)) { + // Trim off the interface designation (e.g., %em1) if present + if (strpos($suricataip, "%") !== FALSE) + $suricataip = substr($suricataip, 0, strpos($suricataip, "%")); + if (($externallist && $localnet == 'yes') || (!$externallist && (!$passlist || $localnet == 'yes' || empty($localnet)))) { if (is_ipaddrv6($suricataip)) { if ($suricatacfg['interface'] <> "wan") { $sn = get_interface_subnetv6($suricatacfg['interface']); @@ -322,14 +333,24 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { } } } - else { + elseif (!$externallist && $localnet != 'yes') { if (is_ipaddrv6($suricataip)) { - if (!in_array($suricataip, $home_net)) - $home_net[] = $suricataip; + if (!in_array($suricataip . "/128", $home_net)) + $home_net[] = $suricataip . "/128"; } } - if (!$whitelist || $localnet == 'yes' || empty($localnet)) { + // Add link-local address if user included locally-attached networks + $suricataip = get_interface_linklocal($suricatacfg['interface']); + if (!empty($suricataip) && $localnet == 'yes') { + // Trim off the interface designation (e.g., %em1) if present + if (strpos($suricataip, "%") !== FALSE) + $suricataip = substr($suricataip, 0, strpos($suricataip, "%")); + if (!in_array($suricataip . "/128", $home_net)) + $home_net[] = $suricataip . "/128"; + } + + if (($$externallist && $localnet == 'yes') || (!$externallist && (!$passlist || $localnet == 'yes' || empty($localnet)))) { /*************************************************************************/ /* Iterate through the interface list and write out pass list items and */ /* also compile a HOME_NET list of all local interfaces for suricata. */ @@ -341,58 +362,89 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { if ($int == "wan") continue; $subnet = get_interface_ip($int); - if (is_ipaddr($subnet)) { + if (is_ipaddrv4($subnet)) { $sn = get_interface_subnet($int); $ip = gen_subnet($subnet, $sn) . "/{$sn}"; if (!in_array($ip, $home_net)) $home_net[] = $ip; } - if ($int == "wan") - continue; + $subnet = get_interface_ipv6($int); + // Trim off the interface designation (e.g., %em1) if present + if (strpos($subnet, "%") !== FALSE) + $subnet = substr($subnet, 0, strpos($subnet, "%")); if (is_ipaddrv6($subnet)) { $sn = get_interface_subnetv6($int); $ip = gen_subnetv6($subnet, $sn). "/{$sn}"; if (!in_array($ip, $home_net)) $home_net[] = $ip; } + + // Add link-local address + $suricataip = get_interface_linklocal($int); + if (!empty($suricataip)) { + // Trim off the interface designation (e.g., %em1) if present + if (strpos($suricataip, "%") !== FALSE) + $suricataip = substr($suricataip, 0, strpos($suricataip, "%")); + if (!in_array($suricataip . "/128", $home_net)) + $home_net[] = $suricataip . "/128"; + } } } if ($wanip == 'yes') { $ip = get_interface_ip("wan"); - if (is_ipaddr($ip)) { - if (!in_array($ip, $home_net)) - $home_net[] = $ip; + if (is_ipaddrv4($ip)) { + if (!in_array($ip . "/32", $home_net)) + $home_net[] = $ip . "/32"; } $ip = get_interface_ipv6("wan"); + // Trim off the interface designation (e.g., %em1) if present + if (strpos($ip, "%") !== FALSE) + $ip = substr($ip, 0, strpos($ip, "%")); if (is_ipaddrv6($ip)) { - if (!in_array($ip, $home_net)) - $home_net[] = $ip; + if (!in_array($ip . "/128", $home_net)) + $home_net[] = $ip . "/128"; + } + // Explicitly grab the WAN Link-Local address + $ip = get_interface_linklocal("wan"); + if (!empty($ip)) { + // Trim off the interface designation (e.g., %em1) if present + if (strpos($ip, "%") !== FALSE) + $ip = substr($ip, 0, strpos($ip, "%")); + if (!in_array($ip . "/128", $home_net)) + $home_net[] = $ip . "/128"; } } if ($wangw == 'yes') { // Grab the default gateway if set $default_gw = exec("/sbin/route -n get default |grep 'gateway:' | /usr/bin/awk '{ print $2 }'"); - if (is_ipaddr($default_gw) && !in_array($default_gw, $home_net)) - $home_net[] = $default_gw; - if (is_ipaddrv6($default_gw) && !in_array($default_gw, $home_net)) - $home_net[] = $default_gw; + if (is_ipaddrv4($default_gw) && !in_array($default_gw . "/32", $home_net)) + $home_net[] = $default_gw . "/32"; + if (is_ipaddrv6($default_gw) && !in_array($default_gw . "/128", $home_net)) + $home_net[] = $default_gw . "/128"; // Get any other interface gateway and put in $HOME_NET if not there already $gw = get_interface_gateway($suricatacfg['interface']); - if (is_ipaddr($gw) && !in_array($gw, $home_net)) - $home_net[] = $gw; + if (is_ipaddrv4($gw) && !in_array($gw . "/32", $home_net)) + $home_net[] = $gw . "/32"; $gw = get_interface_gateway_v6($suricatacfg['interface']); - if (is_ipaddrv6($gw) && !in_array($gw, $home_net)) - $home_net[] = $gw; + // Trim off the interface designation (e.g., %em1) if present + if (strpos($gw, "%") !== FALSE) + $gw = substr($gw, 0, strpos($gw, "%")); + if (is_ipaddrv6($gw) && !in_array($gw . "/128", $home_net)) + $home_net[] = $gw . "/128"; } if ($wandns == 'yes') { - // Add DNS server for WAN interface to whitelist + // Add DNS server for WAN interface to Pass List $dns_servers = get_dns_servers(); foreach ($dns_servers as $dns) { + if (is_ipaddrv4($dns)) + $dns .= "/32"; + elseif (is_addrv6($dns)) + $dns .= "/128"; if ($dns && !in_array($dns, $home_net)) $home_net[] = $dns; } @@ -410,7 +462,7 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { } } - // grab a list of vpns and whitelist if user desires + // Grab a list of vpns enabled - these come back as CIDR mask networks if ($vpns == 'yes') { $vpns_list = filter_get_vpns_list(); if (!empty($vpns_list)) { @@ -443,7 +495,14 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { function suricata_rules_up_install_cron($should_install=true) { global $config, $g; - $command = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/www/suricata/suricata_check_for_rule_updates.php"; + // Remove any existing job first + install_cron_job("suricata_check_for_rule_updates.php", false); + + // If called with FALSE as argument, then we're done + if ($should_install == FALSE) + return; + + $command = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_for_rule_updates.php"; // Get auto-rule update parameter from configuration $suricata_rules_up_info_ck = $config['installedpackages']['suricata']['config'][0]['autoruleupdate']; @@ -606,12 +665,12 @@ function suricata_rm_blocked_install_cron($should_install) { } // First, remove any existing cron task for "rm_blocked" hosts - install_cron_job("pfctl -t {$suri_pf_table} -T expire" , false); + install_cron_job("{$suri_pf_table}", false); // Now add or update the cron task for "rm_blocked" hosts // if enabled. if ($should_install) { - $command = "/usr/bin/nice -n20 /sbin/pfctl -t {$suri_pf_table} -T expire {$suricata_rm_blocked_expire}"; + $command = "/usr/bin/nice -n20 /sbin/pfctl -q -t {$suri_pf_table} -T expire {$suricata_rm_blocked_expire}"; install_cron_job($command, $should_install, $suricata_rm_blocked_min, $suricata_rm_blocked_hr, $suricata_rm_blocked_mday, $suricata_rm_blocked_month, $suricata_rm_blocked_wday, "root"); } } @@ -626,7 +685,7 @@ function sync_suricata_package_config() { // Do not start config build if there are no Suricata-configured interfaces if (!is_array($config['installedpackages']['suricata']) || !is_array($config['installedpackages']['suricata']['rule'])) { - @unlink("{$rcdir}/suricata.sh"); + @unlink("{$rcdir}suricata.sh"); conf_mount_ro(); return; } @@ -646,7 +705,6 @@ function sync_suricata_package_config() { // create suricata bootup file suricata.sh suricata_create_rc(); - $suricataglob = $config['installedpackages']['suricata']['config'][0]; // setup the log directory size check job if enabled suricata_loglimit_install_cron(true); // setup the suricata rules update job if enabled @@ -654,12 +712,11 @@ function sync_suricata_package_config() { // set the suricata blocked hosts time suricata_rm_blocked_install_cron($config['installedpackages']['suricata']['config'][0]['rm_blocked'] != "never_b" ? true : false); - write_config(); configure_cron(); // Do not attempt package sync if reinstalling package or booting -// if (!$g['suricata_postinstall'] && !$g['booting']) -// suricata_sync_on_changes(); + if (!isset($g['suricata_postinstall']) && !$g['booting']) + suricata_sync_on_changes(); conf_mount_ro(); } @@ -1052,11 +1109,11 @@ function suricata_load_rules_map($rules_path) { if (empty($rules_path)) return $map_ref; - /*************************************************************** + /************************************************************************************ * Read all the rules into the map array. * The structure of the map array is: * - * map[gid][sid]['rule']['category']['disabled']['flowbits'] + * map[gid][sid]['rule']['category']['action']['disabled']['managed']['flowbits'] * * where: * gid = Generator ID from rule, or 1 if general text @@ -1067,9 +1124,11 @@ function suricata_load_rules_map($rules_path) { * action = alert, drop, reject or pass * disabled = 1 if rule is disabled (commented out), 0 if * rule is enabled + * managed = 1 if rule is auto-managed by SID MGMT process, + * 0 if not auto-managed * flowbits = Array of applicable flowbits if rule contains * flowbits options - ***************************************************************/ + ************************************************************************************/ // First check if we were passed a directory, a single file // or an array of filenames to read. Set our $rule_files @@ -1542,6 +1601,854 @@ function suricata_load_vrt_policy($policy, $all_rules=null) { return $vrt_policy_rules; } +function suricata_parse_sidconf_file($sidconf_file) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by '$sidconf_file'. The file is */ + /* assumed to contain valid instructions for */ + /* matching rule SIDs as supported by the */ + /* Oinkmaster and PulledPork utilities. */ + /* */ + /* $sidconf_file ==> full path and name of */ + /* file to process */ + /* */ + /* Returns ==> an array containing */ + /* SID modifier tokens */ + /**********************************************/ + + $buf = ""; + $sid_mods = array(); + + $fd = fopen("{$sidconf_file}", "r"); + if ($fd == FALSE) { + log_error("[Suricata] Failed to open SID MGMT file '{$sidconf_file}' for processing."); + return $sid_mods; + } + + // Read and parse the conf file line-by-line + while (($buf = fgets($fd)) !== FALSE) { + $line = array(); + + // Skip any lines that may be just spaces. + if (trim($buf, " \r\n") == "") + continue; + + // Skip line with leading "#" since it's a comment + if (preg_match('/^\s*#/', $buf)) + continue; + + // Trim off any trailing comment + $line = explode("#", $buf); + + // Trim leading and trailing spaces plus newline and any carriage returns + $buf = trim($line[0], ' \r\n'); + + // Now split the SID mod arguments at the commas, if more than one + // per line, and add to our $sid_mods array. + $line = explode(",", $buf); + foreach ($line as $ent) + $sid_mods[] = trim($ent); + } + + // Close the file, release unneeded memory and return + // the array of SID mod tokens parsed from the file. + fclose($fd); + unset($line, $buf); + return $sid_mods; +} + +function suricata_sid_mgmt_auto_categories($suricatacfg, $log_results = FALSE) { + + /****************************************************/ + /* This function parses any auto-SID conf files */ + /* configured for the interface and returns an */ + /* array of rule categories adjusted from the */ + /* ['enabled_rulesets'] element in the config for */ + /* the interface in accordance with the contents */ + /* of the SID Mgmt conf files. */ + /* */ + /* The returned array shows which files should be */ + /* removed and which should be added to the list */ + /* used when building the enforcing ruleset. */ + /* */ + /* $suricatacfg ==> pointer to interface */ + /* configuration info */ + /* $log_results ==> [optional] log results to */ + /* 'sid_changes.log' in the */ + /* interface directory in */ + /* /var/log/suricata when TRUE */ + /* */ + /* Returns ==> array of category file names */ + /* for the interface. The keys */ + /* are category file names and */ + /* the corresponding values show */ + /* if the file should be added */ + /* or removed from the enabled */ + /* rulesets list. */ + /* */ + /* Example - */ + /* $changes[file] = 'enabled' */ + /* */ + /****************************************************/ + + global $config; + $suricata_sidmods_dir = SID_MODS_PATH; + $sid_mods = array(); + $enables = array(); + $disables = array(); + + // Check if auto-mgmt of SIDs is enabled, exit if not + if ($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] != 'on') + return array(); + if (empty($suricatacfg['disable_sid_file']) && empty($suricatacfg['enable_sid_file'])) + return array(); + + // Configure the interface's logging subdirectory if log results is enabled + if ($log_results == TRUE) + $log_file = SURICATALOGDIR . $suricatalogdir . "suricata_" . get_real_interface($suricatacfg['interface']) . "{$suricatacfg['uuid']}/sid_changes.log"; + else + $log_file = NULL; + + // Get the list of currently enabled categories for the interface + if (!empty($suricatacfg['rulesets'])) + $enabled_cats = explode("||", $suricatacfg['rulesets']); + + if ($log_results == TRUE) { + error_log(gettext("********************************************************\n"), 3, $log_file); + error_log(gettext("Starting auto RULE CATEGORY management for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) ."\n"), 3, $log_file); + error_log(gettext("Start Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + } + + switch ($suricatacfg['sid_state_order']) { + case "disable_enable": + if (!empty($suricatacfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$suricatacfg['disable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'disable_sid_file' \"{$suricatacfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open disable_sid file \"{$suricatacfg['disable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + $disables = suricata_get_auto_category_mods($enabled_cats, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['disable_sid_file']}\".\n"), 3, $log_file); + } + } + if (!empty($suricatacfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$suricatacfg['enable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'enable_sid_file' \"{$suricatacfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open enable_sid file \"{$suricatacfg['enable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + $enables = suricata_get_auto_category_mods($enabled_cats, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['enable_sid_file']}\".\n"), 3, $log_file); + } + } + break; + + case "enable_disable": + if (!empty($suricatacfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$suricatacfg['enable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'enable_sid_file' \"{$suricatacfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open enable_sid file \"{$suricatacfg['enable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + $enables = suricata_get_auto_category_mods($enabled_cats, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['enable_sid_file']}\".\n"), 3, $log_file); + } + } + if (!empty($suricatacfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$suricatacfg['disable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'disable_sid_file' \"{$suricatacfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open disable_sid file \"{$suricatacfg['disable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + $disables = suricata_get_auto_category_mods($enabled_cats, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['disable_sid_file']}\".\n"), 3, $log_file); + } + } + break; + + default: + log_error(gettext("[Suricata] Unrecognized 'sid_state_order' value. Skipping auto CATEGORY mgmt step for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) { + error_log(gettext("ERROR: unrecognized 'sid_state_order' value. Skipping auto CATEGORY mgmt step for ") . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']). ".\n", 3, $log_file); + } + } + + if ($log_results == TRUE) { + error_log(gettext("End Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + error_log(gettext("********************************************************\n\n"), 3, $log_file); + } + + // Return the required rule category modifications as an array; + return array_merge($enables, $disables); +} + +function suricata_get_auto_category_mods($categories, $sid_mods, $action, $log_results = FALSE, $log_file = NULL) { + + /****************************************************/ + /* This function parses the provided SID mod tokens */ + /* in $sid_mods and returns an array of category */ + /* files that must be added ('enabled') or removed */ + /* ('disabled') from the provided $categories list */ + /* of enabled rule categories as determined by the */ + /* content of the SID Mgmt tokens in $sid_mods. */ + /* */ + /* The returned array shows which files should be */ + /* removed and which should be added to the list */ + /* used when building the enforcing ruleset. */ + /* */ + /* $categories ==> array of currently enabled */ + /* ruleset categories */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $action ==> modification action for */ + /* matching category targets: */ + /* 'enable' or 'disable' */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename of log */ + /* file to write to */ + /* */ + /* Returns ==> array of category file names */ + /* for the interface. The keys */ + /* are category file names and */ + /* the corresponding values show */ + /* if the file should be added */ + /* or removed from the enabled */ + /* rulesets list. */ + /* */ + /* Example - */ + /* $changes[file] = 'enabled' */ + /* */ + /****************************************************/ + + $suricatadir = SURICATADIR; + $all_cats = array(); + $changes = array(); + $counter = 0; + $matchcount = 0; + + // Get a list of all possible categories by loading all rules files + foreach (array( VRT_FILE_PREFIX, ET_OPEN_FILE_PREFIX, ET_PRO_FILE_PREFIX, GPL_FILE_PREFIX ) as $prefix) { + $files = glob("{$suricatadir}rules/{$prefix}*.rules"); + foreach ($files as $file) + $all_cats[] = basename($file); + } + + // Walk the SID mod tokens and decode looking for rule + // category enable/disable changes. + foreach ($sid_mods as $tok) { + $matches = array(); + // Test the SID token for a GID:SID range and skip if true + if (preg_match('/^(\d+):(\d+)-\1:(\d+)/', $tok)) + continue; + // Test the token for a single GID:SID and skip if true + elseif (preg_match('/^(\d+):(\d+)$/', $tok)) + continue; + // Test the token for the PCRE: keyword and skip if true + elseif (preg_match('/(^pcre\:)(.+)/i', $tok)) + continue; + // Test the token for the MS reference keyword and skip if true + elseif (preg_match('/^MS\d+-.+/i', $tok)) + continue; + // Test the token for other keywords delimited with a colon and skip if true + elseif (preg_match('/^[a-xA-X]+\:.+/', $tok)) + continue; + // Test the SID token for a rule category name. Anything that + // failed to match above is considered a potential category name. + elseif (preg_match('/[a-xA-X]+(-|\w).*/', $tok, $matches)) { + $counter++; + $regex = "/" . preg_quote(trim($matches[0]), '/') . "/i"; + // Search through the $all_cats array for any matches to the regex + $matches = preg_grep($regex, $all_cats); + + // See if any matches are in the $categories array + foreach ($matches as $cat) { + switch ($action) { + case 'enable': + if (!isset($changes[$cat])) { + $changes[$cat] = 'enabled'; + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Enabled rule category: {$cat}\n"), 3, $log_file); + $matchcount++; + } + break; + + case 'disable': + if (!isset($changes[$cat])) { + $changes[$cat] = 'disabled'; + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Disabled rule category: {$cat}\n"), 3, $log_file); + $matchcount++; + } + break; + + default: + break; + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Parsed {$counter} potential Rule Categories to match from the list of tokens.\n"), 3, $log_file); + error_log(gettext(" " . ucfirst($action) . "d {$matchcount} matching Rule Categories.\n"), 3, $log_file); + } + + // Release memory no longer needed + unset($all_cats, $matches); + + // Return array of rule category file changes + return $changes; +} + +function suricata_modify_sid_state(&$rule_map, $sid_mods, $action, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function walks the provided array of */ + /* SID modification tokens and locates the */ + /* target SID or SIDs in the $rule_map array. */ + /* It then performs the change specified by */ + /* $action on the target SID or SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $action ==> modification action for */ + /* matching SID targets: */ + /* 'enable' or 'disable' */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> $rule_map array modified */ + /* by changing state for */ + /* matching SIDs. */ + /* */ + /* Returns a two-dimension */ + /* array of matching GID:SID */ + /* pairs. */ + /**********************************************/ + + $sids = array(); + + // If no rules in $rule_map or mods in $sid_mods, + // then nothing to do. + if (empty($rule_map) || empty($sid_mods)) + return $sids; + + // Validate the action keyword as we only accept + // 'enable' and 'disable' as valid. + switch ($action) { + + case "enable": + break; + + case "disable": + break; + + default: + log_error(gettext("[Suricata] Error - unknown action '{$action}' supplied to suricata_modify_sid_state() function...no SIDs modified.")); + return $sids; + } + + // Walk the SID mod tokens and decode each one + foreach ($sid_mods as $tok) { + $matches = array(); + // Test the SID token for a GID:SID range + if (preg_match('/^(\d+):(\d+)-\1:(\d+)/', $tok, $matches)) { + // It was a range, so find all the intervening SIDs + $gid = trim($matches[1]); + $lsid = trim($matches[2]); + $usid = trim($matches[3]); + $sids[$gid][$lsid] = $action; + while ($lsid < $usid) { + $lsid++; + $sids[$gid][$lsid] = $action; + } + } + // Test the SID token for a single GID:SID + elseif (preg_match('/^(\d+):(\d+)$/', $tok, $matches)) { + // It's a single GID:SID, so grab it + $sids[$matches[1]][$matches[2]] = $action; + } + // Test the SID token for the PCRE: keyword + elseif (preg_match('/(^pcre\:)(.+)/i', $tok, $matches)) { + $regex = '/' . preg_quote($matches[2], '/') . '/i'; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for the MS reference keyword + elseif (preg_match('/^MS\d+-.+/i', $tok, $matches)) { + $regex = "/" . preg_quote($matches[0], '/') . "/i"; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for other keywords delimited with a colon + elseif (preg_match('/^[a-xA-X]+\:.+/', $tok, $matches)) { + $regex = "/" . str_replace(':', ",", preg_quote($matches[0], '/')) . "/i"; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for a rule category name. Anything that + // failed to match above is considered a potential category name. + elseif (preg_match('/[a-xA-X]+(-|\w).*/', $tok, $matches)) { + $regex = "/" . preg_quote(trim($matches[0]), '/') . "/i"; + // Now search through the $rule_map in the 'category' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['category'] . ".rules")) { + $sids[$k1][$k2] = $action; + } + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + // Change state of all the matching GID:SID pairs we found + // above in the $rule_map array passed to us. + $modcount = $changecount = 0; + $counter = count($sids, COUNT_RECURSIVE) - count($sids); + + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Parsed {$counter} potential SIDs to match from the provided list of tokens.\n"), 3, $log_file); + + foreach (array_keys($sids) as $k1) { + foreach (array_keys($sids[$k1]) as $k2) { + if (isset($rule_map[$k1][$k2])) { + if ($action == 'enable' && $rule_map[$k1][$k2]['disabled'] == 1) { + $rule_map[$k1][$k2]['rule'] = ltrim($rule_map[$k1][$k2]['rule'], " \t#"); + $rule_map[$k1][$k2]['disabled'] = 0; + $rule_map[$k1][$k2]['managed'] = 1; + $changecount++; + $modcount++; + } + elseif ($action == 'disable' && $rule_map[$k1][$k2]['disabled'] == 0) { + $rule_map[$k1][$k2]['rule'] = "# " . $rule_map[$k1][$k2]['rule']; + $rule_map[$k1][$k2]['disabled'] = 1; + $rule_map[$k1][$k2]['managed'] = 1; + $changecount++; + $modcount++; + } + } + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Found {$modcount} matching SIDs in the active rules.\n"), 3, $log_file); + error_log(gettext(" Changed state for {$changecount} SIDs to '{$action}d'.\n"), 3, $log_file); + } + + // Return the array of matching SIDs + return $sids; +} + +function suricata_modify_sid_content(&$rule_map, $sid_mods, $log_results = FALSE, $log_file = NULL) { + + /************************************************/ + /* This function walks the provided array of */ + /* SID modification tokens and locates the */ + /* target SID or SIDs in the $rule_map array. */ + /* It then modifies the content of the target */ + /* SID or SIDs. Modifications are only valid */ + /* for normal GID=1 text rules. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> $rule_map array modified */ + /* by changing content for */ + /* matching SIDs. */ + /* */ + /* Returns a two-dimension */ + /* array of matching */ + /* GID:SID pairs. */ + /************************************************/ + + $sids = array(); + $tokencounter = $modcount = $modifiedcount = 0; + + // If no rules in $rule_map or mods in $sid_mods, + // then nothing to do. + if (empty($rule_map) || empty($sid_mods)) + return $sids; + + // Walk the SID mod tokens and decode each one + foreach ($sid_mods as $tok) { + $matches = array(); + if (preg_match('/([\d+|,|\*]*)\s+"(.+)"\s+"(.*)"/', $tok, $matches)) { + $tokencounter++; + $sidlist = explode(",", $matches[1]); + $from = '/' . preg_quote($matches[2], '/') . '/'; + $to = $matches[3]; + $count = 0; + + // Now walk the provided rule map and make the modifications + if ($matches[1] == "*") { + // If wildcard '*' provided for SID, then check them all + foreach ($rule_map[1] as $rulem) { + foreach ($rulem as $k2 => $v) { + $modcount++; + $rule_map[1][$k2]['rule'] = preg_replace($from, $to, $v['rule'], -1, $count); + if ($count > 0) { + $rule_map[1][$k2]['managed'] = 1; + $sids[1][$k2] = 'modify'; + $modifiedcount++; + } + } + } + } + else { + // Otherwise just check the provided SIDs + foreach ($sidlist as $sid) { + if (isset($rule_map[1][$sid])) { + $modcount++; + $rule_map[1][$sid]['rule'] = preg_replace($from, $to, $rule_map[1][$sid]['rule'], -1, $count); + if ($count > 0) { + $rule_map[1][$sid]['managed'] = 1; + $sids[1][$sid] = 'modify'; + $modifiedcount++; + } + } + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Parsed {$tokencounter} potential SIDs to match from the provided list of tokens.\n"), 3, $log_file); + error_log(gettext(" Found {$modcount} matching SIDs in the active rules.\n"), 3, $log_file); + error_log(gettext(" Modified rule text for {$modifiedcount} SIDs.\n"), 3, $log_file); + } + + // Return the array of matching SIDs + return $sids; +} + +function suricata_process_enablesid(&$rule_map, $suricatacfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'enable_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid enablesid.conf file containing */ + /* instructions for enabling matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $suricatacfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $suricata_sidmods_dir = SID_MODS_PATH; + $suricatalogdir = SURICATALOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'enable_sid_file' \"{$suricatacfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + return; + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + suricata_modify_sid_state($rule_map, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['enable_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function suricata_process_disablesid(&$rule_map, $suricatacfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'disable_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid disablesid.conf file containing */ + /* instructions for disabling matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $suricatacfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $suricata_sidmods_dir = SID_MODS_PATH; + $suricatalogdir = SURICATALOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'disable_sid_file' \"{$suricatacfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + return; + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + suricata_modify_sid_state($rule_map, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['disable_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function suricata_process_modifysid(&$rule_map, $suricatacfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'modify_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid modifysid.conf file containing */ + /* instructions for modifying matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $suricatacfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $suricata_sidmods_dir = SID_MODS_PATH; + $suricatalogdir = SURICATALOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'modify_sid_file' for the interface + if (!file_exists("{$suricata_sidmods_dir}{$suricatacfg['modify_sid_file']}")) { + log_error(gettext("[Suricata] Error - unable to open 'modify_sid_file' \"{$suricatacfg['modify_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + return; + } + else + $sid_mods = suricata_parse_sidconf_file("{$suricata_sidmods_dir}{$suricatacfg['modify_sid_file']}"); + + if (!empty($sid_mods)) + suricata_modify_sid_content($rule_map, $sid_mods, $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$suricatacfg['modify_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function suricata_auto_sid_mgmt(&$rule_map, $suricatacfg, $log_results = FALSE) { + + /**************************************************/ + /* This function modifies the rules in the */ + /* passed rule_map array based on values in the */ + /* files 'enable_sid_file', 'disable_sid_file' */ + /* and 'modify_sid_file' for the interface. */ + /* */ + /* If auto-mgmt of SIDs is enabled via the */ + /* settings on the UPDATE RULES tab, then the */ + /* rules are processed against these settings. */ + /* */ + /* $rule_map ==> array of current rules */ + /* $suricatacfg ==> interface config settings */ + /* $log_results ==> [optional] log results to */ + /* 'sid_changes.log' in the */ + /* interface directory in */ + /* /var/log/suricata when TRUE */ + /* */ + /* Returns ==> TRUE if rules were changed; */ + /* otherwise FALSE */ + /**************************************************/ + + global $config; + $result = FALSE; + + // Configure the interface's logging subdirectory if log results is enabled + if ($log_results == TRUE) + $log_file = SURICATALOGDIR . $suricatalogdir . "suricata_" . get_real_interface($suricatacfg['interface']) . "{$suricatacfg['uuid']}/sid_changes.log"; + else + $log_file = NULL; + + // Check if auto-mgmt of SIDs is enabled and files are specified + // for the interface. + if ($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] == 'on' && + (!empty($suricatacfg['disable_sid_file']) || !empty($suricatacfg['enable_sid_file']) || + !empty($suricatacfg['modify_sid_file']))) { + if ($log_results == TRUE) { + error_log(gettext("********************************************************\n"), 3, $log_file); + error_log(gettext("Starting auto SID management for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) ."\n"), 3, $log_file); + error_log(gettext("Start Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + } + + switch ($suricatacfg['sid_state_order']) { + case "disable_enable": + if (!empty($suricatacfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$suricatacfg['disable_sid_file']}\n"), 3, $log_file); + suricata_process_disablesid($rule_map, $suricatacfg, $log_results, $log_file); + } + if (!empty($suricatacfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$suricatacfg['enable_sid_file']}\n"), 3, $log_file); + suricata_process_enablesid($rule_map, $suricatacfg, $log_results, $log_file); + } + if (!empty($suricatacfg['modify_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing modify_sid file: {$suricatacfg['modify_sid_file']}\n"), 3, $log_file); + suricata_process_modifysid($rule_map, $suricatacfg, $log_results, $log_file); + } + $result = TRUE; + break; + + case "enable_disable": + if (!empty($suricatacfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$suricatacfg['enable_sid_file']}\n"), 3, $log_file); + suricata_process_enablesid($rule_map, $suricatacfg, $log_results, $log_file); + } + if (!empty($suricatacfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$suricatacfg['disable_sid_file']}\n"), 3, $log_file); + suricata_process_disablesid($rule_map, $suricatacfg, $log_results, $log_file); + } + if (!empty($suricatacfg['modify_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing modify_sid file: {$suricatacfg['modify_sid_file']}\n"), 3, $log_file); + suricata_process_modifysid($rule_map, $suricatacfg, $log_results, $log_file); + } + $result = TRUE; + break; + + default: + log_error(gettext("[Suricata] Unrecognized 'sid_state_order' value. Skipping auto SID mgmt step for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']))); + if ($log_results == TRUE) { + error_log(gettext("ERROR: unrecognized 'sid_state_order' value. Skipping auto SID mgmt step for ") . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']). ".\n", 3, $log_file); + } + $result = FALSE; + } + + if ($log_results == TRUE) { + error_log(gettext("End Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + error_log(gettext("********************************************************\n\n"), 3, $log_file); + } + } + return $result; +} + function suricata_load_sid_mods($sids) { /*****************************************/ @@ -1577,15 +2484,15 @@ function suricata_load_sid_mods($sids) { function suricata_modify_sids(&$rule_map, $suricatacfg) { - /*****************************************/ - /* This function modifies the rules in */ - /* the passed rules_map array based on */ - /* values in the enablesid/disablesid */ - /* configuration parameters. */ - /* */ - /* $rule_map = array of current rules */ - /* $suricatacfg = config settings */ - /*****************************************/ + /***********************************************/ + /* This function modifies the rules in the */ + /* passed rules_map array based on values in */ + /* the enablesid/disablesid configuration */ + /* parameters for the interface. */ + /* */ + /* $rule_map = array of current rules */ + /* $suricatacfg = interface config settings */ + /***********************************************/ if (!isset($suricatacfg['rule_sid_on']) && !isset($suricatacfg['rule_sid_off'])) @@ -1639,11 +2546,15 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { /* to be written. */ /***********************************************************/ - global $rebuild_rules; + global $config, $rebuild_rules; $suricatadir = SURICATADIR; $flowbit_rules_file = FLOWBITS_FILENAME; $suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; + $enabled_rules = array(); + $enabled_files = array(); + $all_rules = array(); + $cat_mods = array(); $no_rules_defined = true; // If there is no reason to rebuild the rules, exit to save time. @@ -1653,11 +2564,12 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { // Log a message for rules rebuild in progress log_error(gettext("[Suricata] Updating rules configuration for: " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . " ...")); + // Get any automatic rule category enable/disable modifications + // if auto-SID Mgmt is enabled and conf files exist for the interface. + $cat_mods = suricata_sid_mgmt_auto_categories($suricatacfg, TRUE); + // Only rebuild rules if some are selected or an IPS Policy is enabled - if (!empty($suricatacfg['rulesets']) || $suricatacfg['ips_policy_enable'] == 'on') { - $enabled_rules = array(); - $enabled_files = array(); - $all_rules = array(); + if (!empty($suricatacfg['rulesets']) || $suricatacfg['ips_policy_enable'] == 'on' || !empty($cat_mods)) { $no_rules_defined = false; // Load up all the rules into a Rules Map array. @@ -1665,12 +2577,37 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { // Create an array with the filenames of the enabled // rule category files if we have any. - if (!empty($suricatacfg['rulesets'])) { - foreach (explode("||", $suricatacfg['rulesets']) as $file){ - $category = basename($file, ".rules"); - if (!is_array($enabled_files[$category])) - $enabled_files[$category] = array(); - $enabled_files[$category] = $file; + if (!empty($suricatacfg['rulesets']) || !empty($cat_mods)) { + // First get all the user-enabled category files + if (!empty($suricatacfg['rulesets'])) { + foreach (explode("||", $suricatacfg['rulesets']) as $file){ + $category = basename($file, ".rules"); + if (!is_array($enabled_files[$category])) + $enabled_files[$category] = array(); + $enabled_files[$category] = $file; + } + } + + // Now adjust the list using any required changes as + // determined by auto-SID Mgmt policy files. + if (!empty($cat_mods)) { + foreach ($cat_mods as $k => $action) { + $key = basename($k, ".rules"); + switch ($action) { + case 'enabled': + if (!isset($enabled_files[$key])) + $enabled_files[$key] = $k; + break; + + case 'disabled': + if (isset($enabled_files[$key])) + unset($enabled_files[$key]); + break; + + default: + break; + } + } } /****************************************************/ @@ -1694,7 +2631,7 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { } // Release memory we no longer need. - unset($enabled_files, $rulem, $v); + unset($enabled_files, $cat_mods, $rulem, $v); } // Check if a pre-defined Snort VRT policy is selected. If so, @@ -1717,6 +2654,8 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { } // Process any enablesid or disablesid modifications for the selected rules. + // Do the auto-SID managment first, if enabled, then do any manual SID state changes. + suricata_auto_sid_mgmt($enabled_rules, $suricatacfg, TRUE); suricata_modify_sids($enabled_rules, $suricatacfg); // Write the enforcing rules file to the Suricata interface's "rules" directory. @@ -1735,7 +2674,45 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { } else // Just put an empty file to always have the file present suricata_write_flowbit_rules_file(array(), "{$suricatacfgdir}/rules/{$flowbit_rules_file}"); - } else { + unset($all_rules); + } + // If no rule categories were enabled, then use auto-SID management if enabled, since it may enable some rules + elseif ($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] == 'on' && + (!empty($suricatacfg['disable_sid_file']) || !empty($suricatacfg['enable_sid_file']) || + !empty($suricatacfg['modify_sid_file']))) { + + suricata_auto_sid_mgmt($enabled_rules, $suricatacfg, TRUE); + if (!empty($enabled_rules)) { + // Auto-SID management generated some rules, so use them + $no_rules_defined = false; + suricata_modify_sids($enabled_rules, $suricatacfg); + + // Write the enforcing rules file to the Suricata interface's "rules" directory. + suricata_write_enforcing_rules_file($enabled_rules, "{$suricatacfgdir}/rules/{$suricata_enforcing_rules_file}"); + + // If auto-flowbit resolution is enabled, generate the dependent flowbits rules file. + if ($suricatacfg['autoflowbitrules'] == 'on') { + log_error('[Suricata] Enabling any flowbit-required rules for: ' . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . '...'); + + // Load up all rules into a Rules Map array for flowbits assessment + $all_rules = suricata_load_rules_map("{$suricatadir}rules/"); + $fbits = suricata_resolve_flowbits($all_rules, $enabled_rules); + + // Check for and disable any flowbit-required rules the + // user has manually forced to a disabled state. + suricata_modify_sids($fbits, $suricatacfg); + suricata_write_flowbit_rules_file($fbits, "{$suricatacfgdir}/rules/{$flowbit_rules_file}"); + unset($all_rules, $fbits); + } else + // Just put an empty file to always have the file present + suricata_write_flowbit_rules_file(array(), "{$suricatacfgdir}/rules/{$flowbit_rules_file}"); + } + else { + suricata_write_enforcing_rules_file(array(), "{$suricatacfgdir}/rules/{$suricata_enforcing_rules_file}"); + suricata_write_flowbit_rules_file(array(), "{$suricatacfgdir}/rules/{$flowbit_rules_file}"); + } + } + else { suricata_write_enforcing_rules_file(array(), "{$suricatacfgdir}/rules/{$suricata_enforcing_rules_file}"); suricata_write_flowbit_rules_file(array(), "{$suricatacfgdir}/rules/{$flowbit_rules_file}"); } @@ -1753,7 +2730,7 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { // Build a new sid-msg.map file from the enabled // rules and copy it to the interface directory. - log_error(gettext("[Suricata] Building new sig-msg.map file for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . "...")); + log_error(gettext("[Suricata] Building new sid-msg.map file for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . "...")); suricata_build_sid_msg_map("{$suricatacfgdir}/rules/", "{$suricatacfgdir}/sid-msg.map"); } @@ -1994,8 +2971,8 @@ esac EOD; // Write out the suricata.sh script file - @file_put_contents("{$rcdir}/suricata.sh", $suricata_sh_text); - @chmod("{$rcdir}/suricata.sh", 0755); + @file_put_contents("{$rcdir}suricata.sh", $suricata_sh_text); + @chmod("{$rcdir}suricata.sh", 0755); unset($suricata_sh_text); } @@ -2056,7 +3033,7 @@ function suricata_generate_barnyard2_conf($suricatacfg, $if_real) { $suricatabarnyardlog_output_plugins .= "# syslog_full: log to a syslog receiver\n"; $suricatabarnyardlog_output_plugins .= "output alert_syslog_full: sensor_name {$suricatabarnyardlog_hostname_info_chk}, "; if ($suricatacfg['barnyard_syslog_local'] == 'on') - $suricatabarnyardlog_output_plugins .= "local, log_facility LOG_AUTH, log_priority LOG_INFO\n\n"; + $suricatabarnyardlog_output_plugins .= "local, log_facility {$suricatacfg['barnyard_syslog_facility']}, log_priority {$suricatacfg['barnyard_syslog_priority']}\n\n"; else { $suricatabarnyardlog_output_plugins .= "server {$suricatacfg['barnyard_syslog_rhost']}, protocol {$suricatacfg['barnyard_syslog_proto']}, "; $suricatabarnyardlog_output_plugins .= "port {$suricatacfg['barnyard_syslog_dport']}, operation_mode {$suricatacfg['barnyard_syslog_opmode']}, "; @@ -2136,25 +3113,289 @@ function suricata_generate_yaml($suricatacfg) { $suricata_uuid = $suricatacfg['uuid']; $suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; - conf_mount_rw(); - if (!is_array($config['installedpackages']['suricata']['rule'])) return; // Pull in the PHP code that generates the suricata.yaml file // variables that will be substitued further down below. - include("/usr/local/www/suricata/suricata_generate_yaml.php"); + include("/usr/local/pkg/suricata/suricata_generate_yaml.php"); // Pull in the boilerplate template for the suricata.yaml // configuration file. The contents of the template along - // with substituted variables is stored in $suricata_conf_text + // with substituted variables are stored in $suricata_conf_text // (which is defined in the included file). include("/usr/local/pkg/suricata/suricata_yaml_template.inc"); // Now write out the conf file using $suricata_conf_text contents @file_put_contents("{$suricatacfgdir}/suricata.yaml", $suricata_conf_text); unset($suricata_conf_text); - conf_mount_ro(); +} + +/* Uses XMLRPC to synchronize the changes to a remote node */ +function suricata_sync_on_changes() { + global $config, $g; + + /* Do not attempt a package sync while booting up or installing package */ + if ($g['booting'] || $g['suricata_postinstall'] == TRUE) { + log_error("[suricata] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + return; + } + + if (is_array($config['installedpackages']['suricatasync']['config'])){ + $suricata_sync=$config['installedpackages']['suricatasync']['config'][0]; + $synconchanges = $suricata_sync['varsynconchanges']; + $synctimeout = $suricata_sync['varsynctimeout']; + $syncdownloadrules = $suricata_sync['vardownloadrules']; + switch ($synconchanges){ + case "manual": + if (is_array($suricata_sync[row])){ + $rs=$suricata_sync[row]; + } + else{ + log_error("[suricata] xmlrpc CARP sync is enabled but there are no hosts configured as replication targets."); + return; + } + break; + case "auto": + if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ + $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + $rs[0]['varsyncipaddress']=$system_carp['synchronizetoip']; + $rs[0]['varsyncusername']=$system_carp['username']; + $rs[0]['varsyncpassword']=$system_carp['password']; + $rs[0]['varsyncsuricatastart']="no"; + if ($system_carp['synchronizetoip'] ==""){ + log_error("[suricata] xmlrpc CARP sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } + } + else{ + log_error("[suricata] xmlrpc CARP sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } + break; + default: + return; + break; + } + if (is_array($rs)){ + log_error("[suricata] Suricata pkg xmlrpc CARP sync is starting."); + foreach($rs as $sh){ + if ($sh['varsyncsuricatastart']) + $syncstartsuricata = $sh['varsyncsuricatastart']; + else + $syncstartsuricata = "OFF"; + $sync_to_ip = $sh['varsyncipaddress']; + $port = $sh['varsyncport']; + $password = $sh['varsyncpassword']; + if($sh['varsyncusername']) + $username = $sh['varsyncusername']; + else + $username = 'admin'; + if($password && $sync_to_ip) + suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout, $syncstartsuricata); + } + log_error("[suricata] Suricata pkg xmlrpc CARP sync completed."); + } + } +} + +/* Do the actual XMLRPC sync */ +function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout = 150, $syncstartsuricata) { + global $config, $g; + + /* Do not attempt a package sync while booting up or installing package */ + if ($g['booting'] || isset($g['suricata_postinstall'])) { + log_error("[suricata] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + return; + } + + if($username == "" || $password == "" || $sync_to_ip == "") { + log_error("[suricata] A required XMLRPC CARP sync parameter (user, host IP or password) is empty ... aborting pkg sync"); + return; + } + + /* Test key variables and set defaults if empty */ + if(!$synctimeout) + $synctimeout=150; + + $xmlrpc_sync_neighbor = $sync_to_ip; + if($config['system']['webgui']['protocol'] != "") { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if($port == "") { + if($config['system']['webgui']['protocol'] == "http") + $port = "80"; + else + $port = "443"; + } + $synchronizetoip .= $sync_to_ip; + $url = $synchronizetoip; + + /*************************************************/ + /* Send over any auto-SID management files */ + /*************************************************/ + $sid_files = glob(SID_MODS_PATH . '*'); + foreach ($sid_files as $file) { + $content = base64_encode(file_get_contents($file)); + $payload = "@file_put_contents('{$file}', base64_decode('{$content}'));"; + + /* assemble xmlrpc payload */ + $method = 'pfsense.exec_php'; + $params = array( XML_RPC_encode($password), XML_RPC_encode($payload) ); + + log_error("[suricata] Suricata XMLRPC CARP sync sending auto-SID conf files to {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $synctimeout); + $error = ""; + if(!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file); + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } elseif($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } + } + + if (!empty($sid_files) && $error == "") + log_error("[suricata] Suricata pkg XMLRPC CARP sync auto-SID conf files success with {$url}:{$port} (pfsense.exec_php)."); + + /**************************************************/ + /* Send over the <suricata> portion of config.xml */ + /* $xml will hold the section to sync. */ + /**************************************************/ + $xml = array(); + $xml['suricata'] = $config['installedpackages']['suricata']; + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + log_error("[suricata] Beginning Suricata pkg configuration XMLRPC sync to {$url}:{$port}."); + $method = 'pfsense.merge_installedpackages_section_xmlrpc'; + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + + /* send our XMLRPC message and timeout after defined sync timeout value*/ + $resp = $cli->send($msg, $synctimeout); + if(!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } elseif($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } else { + log_error("[suricata] Suricata pkg configuration XMLRPC CARP sync successfully completed with {$url}:{$port}."); + } + + $downloadrulescmd = ""; + if ($syncdownloadrules == "yes") { + $downloadrulescmd = "log_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Update of downloaded rule sets requested...\"));\n"; + $downloadrulescmd .= "\tinclude_once(\"/usr/local/pkg/suricata/suricata_check_for_rule_updates.php\");\n"; + } + $suricatastart = ""; + if ($syncstartsuricata == "ON") { + $suricatastart = "log_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Checking Suricata status...\"));\n"; + $suricatastart .= "\tif (!is_process_running(\"suricata\")) {\n"; + $suricatastart .= "\t\tlog_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Suricata not running. Sending a start command...\"));\n"; + $suricatastart .= "\t\t\$sh_script = RCFILEPREFIX . \"suricata.sh\";\n"; + $suricatastart .= "\t\tmwexec_bg(\"{\$sh_script} start\");\n\t}\n"; + $suricatastart .= "\telse {\n\t\tlog_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Suricata is running...\"));\n\t}\n"; + } + + /*************************************************/ + /* Build a series of commands as a PHP file for */ + /* the secondary host to execute to load the new */ + /* settings. */ + /*************************************************/ + $suricata_sync_cmd = <<<EOD + <?php + require_once("/usr/local/pkg/suricata/suricata.inc"); + require_once("service-utils.inc"); + global \$g, \$rebuild_rules, \$suricata_gui_include, \$pkg_interface; + \$orig_pkg_interface = \$pkg_interface; + \$g["suricata_postinstall"] = true; + \$g["suricata_sync_in_progress"] = true; + \$suricata_gui_include = false; + \$pkg_interface = "console"; + {$downloadrulescmd} + unset(\$g["suricata_postinstall"]); + log_error(gettext("[suricata] XMLRPC pkg CARP sync: Generating suricata.yaml file using Master Host settings...")); + \$rebuild_rules = true; + sync_suricata_package_config(); + \$rebuild_rules = false; + {$suricatastart} + log_error(gettext("[suricata] XMLRPC pkg CARP sync process on this host is complete...")); + \$pkg_interface = \$orig_pkg_interface; + unset(\$g["suricata_sync_in_progress"]); + return true; + ?> + +EOD; + + /*************************************************/ + /* First, have target host write the commands */ + /* to a PHP file in the /tmp directory. */ + /*************************************************/ + $execcmd = "file_put_contents('/tmp/suricata_sync_cmds.php', '{$suricata_sync_cmd}');"; + + /* assemble xmlrpc payload */ + $method = 'pfsense.exec_php'; + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($execcmd) + ); + + log_error("[suricata] Suricata XMLRPC CARP sync sending reload configuration cmd set as a file to {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $synctimeout); + if(!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port} (pfsense.exec_php)."; + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } elseif($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } else { + log_error("[suricata] Suricata pkg XMLRPC CARP sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + } + + /*************************************************/ + /* Now assemble a command to execute the */ + /* previously sent PHP file in the background. */ + /*************************************************/ + $execcmd = "exec(\"/usr/local/bin/php -f '/tmp/suricata_sync_cmds.php' > /dev/null 2>&1 &\");"; + $params2 = array( + XML_RPC_encode($password), + XML_RPC_encode($execcmd) + ); + log_error("[suricata] Suricata XMLRPC CARP sync sending {$url}:{$port} cmd to execute configuration reload."); + $msg2 = new XML_RPC_Message($method, $params2); + $resp = $cli->send($msg2, $synctimeout); + if(!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port} (pfsense.exec_php)."; + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } elseif($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Suricata Settings Sync", ""); + } else { + log_error("[suricata] Suricata pkg XMLRPC CARP sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + } } ?> diff --git a/config/suricata/suricata.priv.inc b/config/suricata/suricata.priv.inc index 3bbee55a..efa71366 100644 --- a/config/suricata/suricata.priv.inc +++ b/config/suricata/suricata.priv.inc @@ -25,6 +25,7 @@ $priv_list['page-services-suricata']['match'][] = "suricata/suricata_select_alia $priv_list['page-services-suricata']['match'][] = "suricata/suricata_list_view.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_logs_browser.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_logs_mgmt.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_sid_mgmt.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_passlist.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_passlist_edit.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_post_install.php*"; diff --git a/config/suricata/suricata.xml b/config/suricata/suricata.xml index 6aae2d93..d5ea59ad 100644 --- a/config/suricata/suricata.xml +++ b/config/suricata/suricata.xml @@ -9,49 +9,40 @@ /* suricata.xml part of the Suricata package for pfSense + Copyright (C) 2014 Bill meeks - Significant portions are based on original work done for the Snort - package for pfSense from the following contributors: - - Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. - Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. - Copyright (C) 2006 Scott Ullrich - Copyright (C) 2009 Robert Zelaya Sr. Developer - Copyright (C) 2012 Ermal Luci - All rights reserved. - - Adapted for Suricata by: - Copyright (C) 2014 Bill Meeks - All rights reserved. - - 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. + All rights reserved. */ /* ========================================================================== */ +/* + 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. + */ +/* ========================================================================== */ ]]> </copyright> <description>Suricata IDS/IPS Package</description> <requirements>None</requirements> <name>suricata</name> - <version>1.4.6 pkg v1.0.6</version> + <version>2.0.3 pkg v2.0</version> <title>Services: Suricata IDS</title> <include_file>/usr/local/pkg/suricata/suricata.inc</include_file> <menu> @@ -77,18 +68,43 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_sync.xml</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> <item>https://packages.pfsense.org/packages/config/suricata/suricata_check_cron_misc.inc</item> <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_check_for_rule_updates.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> <item>https://packages.pfsense.org/packages/config/suricata/suricata_yaml_template.inc</item> <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> <item>https://packages.pfsense.org/packages/config/suricata/suricata_generate_yaml.php</item> - <prefix>/usr/local/www/suricata/</prefix> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_migrate_config.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_post_install.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_uninstall.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> @@ -122,11 +138,6 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_check_for_rule_updates.php</item> - <prefix>/usr/local/www/suricata/</prefix> - <chmod>0755</chmod> - </additional_files_needed> - <additional_files_needed> <item>https://packages.pfsense.org/packages/config/suricata/suricata_rules.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> @@ -182,22 +193,22 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_list_view.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_sid_mgmt.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_app_parsers.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_list_view.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_libhtp_policy_engine.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_app_parsers.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_uninstall.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_libhtp_policy_engine.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> @@ -212,9 +223,19 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_post_install.php</item> - <prefix>/usr/local/www/suricata/</prefix> - <chmod>0755</chmod> + <prefix>/usr/local/www/widgets/javascript/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.js</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/widgets/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.widget.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/include/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/widget-suricata.inc</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/www/suricata/</prefix> @@ -237,19 +258,19 @@ <item>https://packages.pfsense.org/packages/config/suricata/suricata_select_alias.php</item> </additional_files_needed> <additional_files_needed> - <prefix>/usr/local/www/widgets/javascript/</prefix> + <prefix>/var/db/suricata/sidmods/</prefix> <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.js</item> + <item>https://packages.pfsense.org/packages/config/suricata/disablesid-sample.conf</item> </additional_files_needed> <additional_files_needed> - <prefix>/usr/local/www/widgets/widgets/</prefix> + <prefix>/var/db/suricata/sidmods/</prefix> <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.widget.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/enablesid-sample.conf</item> </additional_files_needed> <additional_files_needed> - <prefix>/usr/local/www/widgets/include/</prefix> + <prefix>/var/db/suricata/sidmods/</prefix> <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/suricata/widget-suricata.inc</item> + <item>https://packages.pfsense.org/packages/config/suricata/modifysid-sample.conf</item> </additional_files_needed> <!-- configpath gets expanded out automatically and config items will be stored in that location --> <configpath>['installedpackages']['suricata']</configpath> @@ -259,12 +280,12 @@ </fields> <custom_php_install_command> <![CDATA[ - include_once("/usr/local/www/suricata/suricata_post_install.php"); + include_once("/usr/local/pkg/suricata/suricata_post_install.php"); ]]> </custom_php_install_command> <custom_php_deinstall_command> <![CDATA[ - include_once("/usr/local/www/suricata/suricata_uninstall.php"); + include_once("/usr/local/pkg/suricata/suricata_uninstall.php"); ]]> </custom_php_deinstall_command> <custom_php_resync_config_command> diff --git a/config/suricata/suricata_alerts.php b/config/suricata/suricata_alerts.php index 2f0f114f..eab2a1d5 100644 --- a/config/suricata/suricata_alerts.php +++ b/config/suricata/suricata_alerts.php @@ -11,6 +11,7 @@ * Copyright (C) 2006 Scott Ullrich * Copyright (C) 2009 Robert Zelaya Sr. Developer * Copyright (C) 2012 Ermal Luci + * Copyright (C) 2014 Jim Pingle jim@pingle.org * All rights reserved. * * Adapted for Suricata by: @@ -44,6 +45,7 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); $supplist = array(); $suri_pf_table = SURICATA_PF_TABLE; +$filterlogentries = FALSE; function suricata_is_alert_globally_suppressed($list, $gid, $sid) { @@ -132,6 +134,31 @@ function suricata_add_supplist_entry($suppress) { return false; } +function suricata_escape_filter_regex($filtertext) { + /* If the caller (user) has not already put a backslash before a slash, to escape it in the regex, */ + /* then this will do it. Take out any "\/" already there, then turn all ordinary "/" into "\/". */ + return str_replace('/', '\/', str_replace('\/', '/', $filtertext)); +} + +function suricata_match_filter_field($flent, $fields) { + foreach ($fields as $key => $field) { + if ($field == null) + continue; + if ((strpos($field, '!') === 0)) { + $field = substr($field, 1); + $field_regex = suricata_escape_filter_regex($field); + if (@preg_match("/{$field_regex}/i", $flent[$key])) + return false; + } + else { + $field_regex = suricata_escape_filter_regex($field); + if (!@preg_match("/{$field_regex}/i", $flent[$key])) + return false; + } + } + return true; +} + if (isset($_POST['instance']) && is_numericint($_POST['instance'])) $instanceid = $_POST['instance']; // This is for the auto-refresh so we can stay on the same interface @@ -164,6 +191,49 @@ if (empty($pconfig['arefresh'])) $pconfig['arefresh'] = 'off'; $anentries = $pconfig['alertnumber']; +# --- AJAX REVERSE DNS RESOLVE Start --- +if (isset($_POST['resolve'])) { + $ip = strtolower($_POST['resolve']); + $res = (is_ipaddr($ip) ? gethostbyaddr($ip) : ''); + + if ($res && $res != $ip) + $response = array('resolve_ip' => $ip, 'resolve_text' => $res); + else + $response = array('resolve_ip' => $ip, 'resolve_text' => gettext("Cannot resolve")); + + echo json_encode(str_replace("\\","\\\\", $response)); // single escape chars can break JSON decode + exit; +} +# --- AJAX REVERSE DNS RESOLVE End --- + +if ($_POST['filterlogentries_submit']) { + // Set flag for filtering alert entries + $filterlogentries = TRUE; + + // -- IMPORTANT -- + // Note the order of these fields must match the order decoded from the alerts log + $filterfieldsarray = array(); + $filterfieldsarray['time'] = $_POST['filterlogentries_time'] ? $_POST['filterlogentries_time'] : null; + $filterfieldsarray['action'] = null; + $filterfieldsarray['gid'] = $_POST['filterlogentries_gid'] ? $_POST['filterlogentries_gid'] : null; + $filterfieldsarray['sid'] = $_POST['filterlogentries_sid'] ? $_POST['filterlogentries_sid'] : null; + $filterfieldsarray['rev'] = null; + $filterfieldsarray['msg'] = $_POST['filterlogentries_description'] ? $_POST['filterlogentries_description'] : null; + $filterfieldsarray['class'] = $_POST['filterlogentries_classification'] ? $_POST['filterlogentries_classification'] : null; + $filterfieldsarray['priority'] = $_POST['filterlogentries_priority'] ? $_POST['filterlogentries_priority'] : null; + $filterfieldsarray['proto'] = $_POST['filterlogentries_protocol'] ? $_POST['filterlogentries_protocol'] : null; + // Remove any zero-length spaces added to the IP address that could creep in from a copy-paste operation + $filterfieldsarray['src'] = $_POST['filterlogentries_sourceipaddress'] ? str_replace("\xE2\x80\x8B", "", $_POST['filterlogentries_sourceipaddress']) : null; + $filterfieldsarray['sport'] = $_POST['filterlogentries_sourceport'] ? $_POST['filterlogentries_sourceport'] : null; + // Remove any zero-length spaces added to the IP address that could creep in from a copy-paste operation + $filterfieldsarray['dst'] = $_POST['filterlogentries_destinationipaddress'] ? str_replace("\xE2\x80\x8B", "", $_POST['filterlogentries_destinationipaddress']) : null; + $filterfieldsarray['dport'] = $_POST['filterlogentries_destinationport'] ? $_POST['filterlogentries_destinationport'] : null; +} + +if ($_POST['filterlogentries_clear']) { + $filterfieldsarray = array(); +} + if ($_POST['save']) { if (!is_array($config['installedpackages']['suricata']['alertsblocks'])) $config['installedpackages']['suricata']['alertsblocks'] = array(); @@ -277,7 +347,9 @@ if ($_POST['togglesid'] && is_numeric($_POST['sidid']) && is_numeric($_POST['gen /* rules for this interface. */ /*************************************************/ $rebuild_rules = true; + conf_mount_rw(); suricata_generate_yaml($a_instance[$instanceid]); + conf_mount_ro(); $rebuild_rules = false; /* Signal Suricata to live-load the new rules */ @@ -334,7 +406,6 @@ include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<script src="/javascript/filter_log.js" type="text/javascript"></script> <?php include_once("fbegin.inc"); @@ -359,24 +430,28 @@ if ($savemsg) { <input type="hidden" name="descr" id="descr" value=""/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), true, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td></tr> <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6"> + <tbody> <tr> <td colspan="2" class="listtopic"><?php echo gettext("Alert Log View Settings"); ?></td> </tr> @@ -417,9 +492,97 @@ if ($savemsg) { </td> </tr> <tr> + <td colspan="2" class="listtopic"><?php echo gettext("Alert Log View Filter"); ?></td> + </tr> + <tr id="filter_enable_row" style="display:<?php if (!$filterlogentries) {echo "table-row;";} else {echo "none;";} ?>"> + <td width="22%" class="vncell"><?php echo gettext('Alert Log Filter Options'); ?></td> + <td width="78%" class="vtable"> + <input name="show_filter" id="show_filter" type="button" class="formbtns" value="<?=gettext("Show Filter");?>" onclick="enable_showFilter();" /> + <?=gettext("Click to display advanced filtering options dialog");?> + </td> + </tr> + <tr id="filter_options_row" style="display:<?php if (!$filterlogentries) {echo "none;";} else {echo "table-row;";} ?>"> + <td colspan="2"> + <table width="100%" border="0" cellpadding="0" cellspacing="1" summary="action"> + <tr> + <td valign="top"> + <div align="center"><?=gettext("Date");?></div> + <div align="center"><input id="filterlogentries_time" name="filterlogentries_time" class="formfld search" type="text" size="10" value="<?= $filterfieldsarray['time'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Source IP Address");?></div> + <div align="center"><input id="filterlogentries_sourceipaddress" name="filterlogentries_sourceipaddress" class="formfld search" type="text" size="28" value="<?= $filterfieldsarray['src'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Source Port");?></div> + <div align="center"><input id="filterlogentries_sourceport" name="filterlogentries_sourceport" class="formfld search" type="text" size="5" value="<?= $filterfieldsarray['sport'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Description");?></div> + <div align="center"><input id="filterlogentries_description" name="filterlogentries_description" class="formfld search" type="text" size="28" value="<?= $filterfieldsarray['msg'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("GID");?></div> + <div align="center"><input id="filterlogentries_gid" name="filterlogentries_gid" class="formfld search" type="text" size="6" value="<?= $filterfieldsarray['gid'] ?>" /></div> + </td> + </tr> + <tr> + <td valign="top"> + <div align="center"><?=gettext("Priority");?></div> + <div align="center"><input id="filterlogentries_priority" name="filterlogentries_priority" class="formfld search" type="text" size="10" value="<?= $filterfieldsarray['priority'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Destination IP Address");?></div> + <div align="center"><input id="filterlogentries_destinationipaddress" name="filterlogentries_destinationipaddress" class="formfld search" type="text" size="28" value="<?= $filterfieldsarray['dst'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Destination Port");?></div> + <div align="center"><input id="filterlogentries_destinationport" name="filterlogentries_destinationport" class="formfld search" type="text" size="5" value="<?= $filterfieldsarray['dport'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("Classification");?></div> + <div align="center"><input id="filterlogentries_classification" name="filterlogentries_classification" class="formfld search" type="text" size="28" value="<?= $filterfieldsarray['class'] ?>" /></div> + </td> + <td valign="top"> + <div align="center"><?=gettext("SID");?></div> + <div align="center"><input id="filterlogentries_sid" name="filterlogentries_sid" class="formfld search" type="text" size="6" value="<?= $filterfieldsarray['sid'] ?>" /></div> + </td> + </tr> + <tr> + <td valign="top"> + <div align="center"><?=gettext("Protocol");?></div> + <div align="center"><input id="filterlogentries_protocol" name="filterlogentries_protocol" class="formfld search" type="text" size="10" value="<?= $filterfieldsarray['proto'] ?>" /></div> + </td> + <td valign="top"> + </td> + <td valign="top"> + </td> + <td colspan="2" style="vertical-align:bottom"> + <div align="right"><input id="filterlogentries_submit" name="filterlogentries_submit" type="submit" class="formbtns" value="<?=gettext("Filter");?>" title="<?=gettext("Apply filter"); ?>" /> + <input id="filterlogentries_clear" name="filterlogentries_clear" type="submit" class="formbtns" value="<?=gettext("Clear");?>" title="<?=gettext("Remove filter");?>" /> + <input id="filterlogentries_hide" name="filterlogentries_hide" type="button" class="formbtns" value="<?=gettext("Hide");?>" onclick="enable_hideFilter();" title="<?=gettext("Hide filter options");?>" /></div> + </td> + </tr> + <tr> + <td colspan="5" style="vertical-align:bottom"> + <?printf(gettext('Matches %1$s regular expression%2$s.'), '<a target="_blank" href="http://www.php.net/manual/en/book.pcre.php">', '</a>');?> + <?=gettext("Precede with exclamation (!) as first character to exclude match.");?> + </td> + </tr> + </table> + </td> + </tr> + <?php if ($filterlogentries) : ?> + <tr> + <td colspan="2" class="listtopic"><?php printf(gettext("Last %s Alert Entries"), $anentries); ?> + <?php echo gettext("(Most recent listed first) ** FILTERED VIEW ** clear filter to see all entries"); ?></td> + </tr> + <?php else: ?> + <tr> <td colspan="2" class="listtopic"><?php printf(gettext("Last %s Alert Entries"), $anentries); ?> <?php echo gettext("(Most recent entries are listed first)"); ?></td> </tr> + <?php endif; ?> <tr> <td width="100%" colspan="2"> <table id="myTable" style="table-layout: fixed;" width="100%" class="sortable" border="0" cellpadding="0" cellspacing="0"> @@ -436,7 +599,7 @@ if ($savemsg) { <col axis="string"> </colgroup> <thead> - <tr> + <tr class="sortableHeaderRowIdentifier"> <th class="listhdrr" axis="date"><?php echo gettext("Date"); ?></th> <th class="listhdrr" axis="number"><?php echo gettext("Pri"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Proto"); ?></th> @@ -445,7 +608,7 @@ if ($savemsg) { <th class="listhdrr" axis="string"><?php echo gettext("SPort"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Dst"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("DPort"); ?></th> - <th class="listhdrr" axis="number"><?php echo gettext("SID"); ?></th> + <th class="listhdrr" axis="number"><?php echo gettext("GID:SID"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Description"); ?></th> </tr> </thead> @@ -458,95 +621,175 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo if (file_exists("/tmp/alerts_suricata{$suricata_uuid}")) { $tmpblocked = array_flip(suricata_get_blocked_ips()); $counter = 0; - /* 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 */ + + /*************** FORMAT without CSV patch -- ALERT -- ***********************************************************************************/ + /* Line format: timestamp action[**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] {proto} src:srcport -> dst:dstport */ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /****************************************************************************************************************************************/ + + /**************** FORMAT without CSV patch -- DECODER EVENT -- **************************************************************************/ + /* Line format: timestamp action[**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] [**] [Raw pkt: ...] */ + /* 0 1 2 3 4 5 6 7 */ + /************** *************************************************************************************************************************/ + $fd = fopen("/tmp/alerts_suricata{$suricata_uuid}", "r"); - while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { - if(count($fields) < 13) - continue; + $buf = ""; + while (($buf = fgets($fd)) !== FALSE) { + $fields = array(); + $tmp = array(); + $decoder_event = FALSE; + + /**************************************************************/ + /* Parse alert log entry to find the parts we want to display */ + /**************************************************************/ + + // Field 0 is the event timestamp + $fields['time'] = substr($buf, 0, strpos($buf, ' ')); + + // Field 1 is currently not used, so set to NULL + $fields['action'] = null; + + // The regular expression match below returns an array as follows: + // [2] => GID, [3] => SID, [4] => REV, [5] => MSG, [6] => CLASSIFICATION, [7] = PRIORITY + preg_match('/\[\*{2}\]\s\[((\d+):(\d+):(\d+))\]\s(.*)\[\*{2}\]\s\[Classification:\s(.*)\]\s\[Priority:\s(\d+)\]\s/', $buf, $tmp); + $fields['gid'] = trim($tmp[2]); + $fields['sid'] = trim($tmp[3]); + $fields['rev'] = trim($tmp[4]); + $fields['msg'] = trim($tmp[5]); + $fields['class'] = trim($tmp[6]); + $fields['priority'] = trim($tmp[7]); + + // The regular expression match below looks for the PROTO, SRC and DST fields + // and returns an array as follows: + // [1] = PROTO, [2] => SRC:SPORT [3] => DST:DPORT + if (preg_match('/\{(.*)\}\s(.*)\s->\s(.*)/', $buf, $tmp)) { + // Get PROTO + $fields['proto'] = trim($tmp[1]); + + // Get SRC + $fields['src'] = trim(substr($tmp[2], 0, strrpos($tmp[2], ':'))); + if (is_ipaddrv6($fields['src'])) + $fields['src'] = inet_ntop(inet_pton($fields['src'])); + + // Get SPORT + $fields['sport'] = trim(substr($tmp[2], strrpos($tmp[2], ':') + 1)); + + // Get DST + $fields['dst'] = trim(substr($tmp[3], 0, strrpos($tmp[3], ':'))); + if (is_ipaddrv6($fields['dst'])) + $fields['dst'] = inet_ntop(inet_pton($fields['dst'])); + + // Get DPORT + $fields['dport'] = trim(substr($tmp[3], strrpos($tmp[3], ':') + 1)); + } + else { + // If no PROTO nor IP ADDR, then this is a DECODER EVENT + $decoder_event = TRUE; + $fields['proto'] = gettext("n/a"); + $fields['sport'] = gettext("n/a"); + $fields['dport'] = gettext("n/a"); + } // 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]); + $event_tm = date_create_from_format("m/d/Y-H:i:s.u", $fields['time']); // Check the 'CATEGORY' field for the text "(null)" and // substitute "Not Assigned". - if ($fields[6] == "(null)") - $fields[6] = "Not Assigned"; + if ($fields['class'] == "(null)") + $fields['class'] = gettext("Not Assigned"); + + $fields['time'] = date_format($event_tm, "m/d/Y") . " " . date_format($event_tm, "H:i:s"); + if ($filterlogentries && !suricata_match_filter_field($fields, $filterfieldsarray)) { + continue; + } /* Time */ $alert_time = date_format($event_tm, "H:i:s"); /* Date */ $alert_date = date_format($event_tm, "m/d/Y"); /* Description */ - $alert_descr = $fields[5]; - $alert_descr_url = urlencode($fields[5]); + $alert_descr = $fields['msg']; + $alert_descr_url = urlencode($fields['msg']); /* Priority */ - $alert_priority = $fields[7]; + $alert_priority = $fields['priority']; /* Protocol */ - $alert_proto = $fields[8]; + $alert_proto = $fields['proto']; + /* IP SRC */ - $alert_ip_src = $fields[9]; - /* Add zero-width space as soft-break opportunity after each colon if we have an IPv6 address */ - $alert_ip_src = str_replace(":", ":​", $alert_ip_src); - /* Add Reverse DNS lookup icons */ - $alert_ip_src .= "<br/><a onclick=\"javascript:getURL('/diag_dns.php?host={$fields[9]}&dialog_output=true', outputrule);\">"; - $alert_ip_src .= "<img src='../themes/{$g['theme']}/images/icons/icon_log_d.gif' width='11' height='11' border='0' "; - $alert_ip_src .= "title='" . gettext("Resolve host via reverse DNS lookup (quick pop-up)") . "' style=\"cursor: pointer;\"></a> "; - $alert_ip_src .= "<a href='/diag_dns.php?host={$fields[9]}&instance={$instanceid}'>"; - $alert_ip_src .= "<img src='../themes/{$g['theme']}/images/icons/icon_log.gif' width='11' height='11' border='0' "; - $alert_ip_src .= "title='" . gettext("Resolve host via reverse DNS lookup") . "'></a>"; - /* Add icons for auto-adding to Suppress List if appropriate */ - if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3]) && - !isset($supplist[$fields[2]][$fields[3]]['by_src'][$fields[9]])) { - $alert_ip_src .= " <input type='image' name='addsuppress_srcip[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','{$fields[9]}','{$alert_descr}');\" "; - $alert_ip_src .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; - $alert_ip_src .= "title='" . gettext("Add this alert to the Suppress List and track by_src IP") . "'/>"; - } - elseif (isset($supplist[$fields[2]][$fields[3]]['by_src'][$fields[9]])) { - $alert_ip_src .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; - $alert_ip_src .= "title='" . gettext("This alert track by_src IP is already in the Suppress List") . "'/>"; + if ($decoder_event == FALSE) { + $alert_ip_src = $fields['src']; + /* Add zero-width space as soft-break opportunity after each colon if we have an IPv6 address */ + $alert_ip_src = str_replace(":", ":​", $alert_ip_src); + /* Add Reverse DNS lookup icon */ + $alert_ip_src .= "<br/><img onclick=\"javascript:resolve_with_ajax('{$fields['src']}');\" title=\""; + $alert_ip_src .= gettext("Resolve host via reverse DNS lookup") . "\" border=\"0\" src=\"/themes/{$g['theme']}/images/icons/icon_log.gif\" alt=\"Icon Reverse Resolve with DNS\" "; + $alert_ip_src .= " style=\"cursor: pointer;\"/>"; + /* Add icons for auto-adding to Suppress List if appropriate */ + if (!suricata_is_alert_globally_suppressed($supplist, $fields['gid'], $fields['sid']) && + !isset($supplist[$fields['gid']][$fields['sid']]['by_src'][$fields['src']])) { + $alert_ip_src .= " <input type='image' name='addsuppress_srcip[]' onClick=\"encRuleSig('{$fields['gid']}','{$fields['sid']}','{$fields['src']}','{$alert_descr}');\" "; + $alert_ip_src .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; + $alert_ip_src .= "title='" . gettext("Add this alert to the Suppress List and track by_src IP") . "'/>"; + } + elseif (isset($supplist[$fields['gid']][$fields['sid']]['by_src'][$fields['src']])) { + $alert_ip_src .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; + $alert_ip_src .= "title='" . gettext("This alert track by_src IP is already in the Suppress List") . "'/>"; + } + /* Add icon for auto-removing from Blocked Table if required */ + if (isset($tmpblocked[$fields['src']])) { + $alert_ip_src .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields['src']}';\" "; + $alert_ip_src .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; + } } - /* Add icon for auto-removing from Blocked Table if required */ - if (isset($tmpblocked[$fields[9]])) { - $alert_ip_src .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields[9]}';\" "; - $alert_ip_src .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; + else { + if (preg_match('/\s\[Raw pkt:(.*)\]/', $buf, $tmp)) + $alert_ip_src = "<div title='[Raw pkt: {$tmp[1]}]'>" . gettext("Decoder Event") . "</div>"; + else + $alert_ip_src = gettext("Decoder Event"); } + /* IP SRC Port */ - $alert_src_p = $fields[10]; - /* IP Destination */ - $alert_ip_dst = $fields[11]; - /* Add zero-width space as soft-break opportunity after each colon if we have an IPv6 address */ - $alert_ip_dst = str_replace(":", ":​", $alert_ip_dst); - /* Add Reverse DNS lookup icons */ - $alert_ip_dst .= "<br/><a onclick=\"javascript:getURL('/diag_dns.php?host={$fields[11]}&dialog_output=true', outputrule);\">"; - $alert_ip_dst .= "<img src='../themes/{$g['theme']}/images/icons/icon_log_d.gif' width='11' height='11' border='0' "; - $alert_ip_dst .= "title='" . gettext("Resolve host via reverse DNS lookup (quick pop-up)") . "' style=\"cursor: pointer;\"></a> "; - $alert_ip_dst .= "<a href='/diag_dns.php?host={$fields[11]}&instance={$instanceid}'>"; - $alert_ip_dst .= "<img src='../themes/{$g['theme']}/images/icons/icon_log.gif' width='11' height='11' border='0' "; - $alert_ip_dst .= "title='" . gettext("Resolve host via reverse DNS lookup") . "'></a>"; - /* Add icons for auto-adding to Suppress List if appropriate */ - if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3]) && - !isset($supplist[$fields[2]][$fields[3]]['by_dst'][$fields[11]])) { - $alert_ip_dst .= " <input type='image' name='addsuppress_dstip[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','{$fields[11]}','{$alert_descr}');\" "; - $alert_ip_dst .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; - $alert_ip_dst .= "title='" . gettext("Add this alert to the Suppress List and track by_dst IP") . "'/>"; - } - elseif (isset($supplist[$fields[2]][$fields[3]]['by_dst'][$fields[11]])) { - $alert_ip_dst .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; - $alert_ip_dst .= "title='" . gettext("This alert track by_dst IP is already in the Suppress List") . "'/>"; + $alert_src_p = $fields['sport']; + + /* IP DST */ + if ($decoder_event == FALSE) { + $alert_ip_dst = $fields['dst']; + /* Add zero-width space as soft-break opportunity after each colon if we have an IPv6 address */ + $alert_ip_dst = str_replace(":", ":​", $alert_ip_dst); + /* Add Reverse DNS lookup icons */ + $alert_ip_dst .= "<br/><img onclick=\"javascript:resolve_with_ajax('{$fields['dst']}');\" title=\""; + $alert_ip_dst .= gettext("Resolve host via reverse DNS lookup") . "\" border=\"0\" src=\"/themes/{$g['theme']}/images/icons/icon_log.gif\" alt=\"Icon Reverse Resolve with DNS\" "; + $alert_ip_dst .= " style=\"cursor: pointer;\"/>"; + /* Add icons for auto-adding to Suppress List if appropriate */ + if (!suricata_is_alert_globally_suppressed($supplist, $fields['gid'], $fields['sid']) && + !isset($supplist[$fields['gid']][$fields['sid']]['by_dst'][$fields['dst']])) { + $alert_ip_dst .= " <input type='image' name='addsuppress_dstip[]' onClick=\"encRuleSig('{$fields['gid']}','{$fields['sid']}','{$fields['dst']}','{$alert_descr}');\" "; + $alert_ip_dst .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; + $alert_ip_dst .= "title='" . gettext("Add this alert to the Suppress List and track by_dst IP") . "'/>"; + } + elseif (isset($supplist[$fields['gid']][$fields['sid']]['by_dst'][$fields['dst']])) { + $alert_ip_dst .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; + $alert_ip_dst .= "title='" . gettext("This alert track by_dst IP is already in the Suppress List") . "'/>"; + } + + /* Add icon for auto-removing from Blocked Table if required */ + if (isset($tmpblocked[$fields['dst']])) { + $alert_ip_dst .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields['dst']}';\" "; + $alert_ip_dst .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; + } } - /* Add icon for auto-removing from Blocked Table if required */ - if (isset($tmpblocked[$fields[11]])) { - $alert_ip_dst .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields[11]}';\" "; - $alert_ip_dst .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; + else { + $alert_ip_dst = gettext("n/a"); } + /* IP DST Port */ - $alert_dst_p = $fields[12]; + $alert_dst_p = $fields['dport']; + /* SID */ - $alert_sid_str = "{$fields[2]}:{$fields[3]}"; - if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3])) { - $sidsupplink = "<input type='image' name='addsuppress[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','{$alert_descr}');\" "; + $alert_sid_str = "{$fields['gid']}:{$fields['sid']}"; + if (!suricata_is_alert_globally_suppressed($supplist, $fields['gid'], $fields['sid'])) { + $sidsupplink = "<input type='image' name='addsuppress[]' onClick=\"encRuleSig('{$fields['gid']}','{$fields['sid']}','','{$alert_descr}');\" "; $sidsupplink .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; $sidsupplink .= "title='" . gettext("Add this alert to the Suppress List") . "'/>"; } @@ -555,34 +798,35 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo $sidsupplink .= "title='" . gettext("This alert is already in the Suppress List") . "'/>"; } /* Add icon for toggling rule state */ - if (isset($disablesid[$fields[2]][$fields[3]])) { - $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','');\" "; + if (isset($disablesid[$fields['gid']][$fields['sid']])) { + $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields['gid']}','{$fields['sid']}','','');\" "; $sid_dsbl_link .= "src='../themes/{$g['theme']}/images/icons/icon_reject.gif' width='11' height='11' border='0' "; $sid_dsbl_link .= "title='" . gettext("Rule is forced to a disabled state. Click to remove the force-disable action from this rule.") . "'/>"; } else { - $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','');\" "; + $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields['gid']}','{$fields['sid']}','','');\" "; $sid_dsbl_link .= "src='../themes/{$g['theme']}/images/icons/icon_block.gif' width='11' height='11' border='0' "; $sid_dsbl_link .= "title='" . gettext("Force-disable this rule and remove it from current rules set.") . "'/>"; } /* DESCRIPTION */ - $alert_class = $fields[6]; + $alert_class = $fields['class']; echo "<tr> <td class='listr' align='center'>{$alert_date}<br/>{$alert_time}</td> <td class='listr' align='center'>{$alert_priority}</td> <td class='listr' align='center'>{$alert_proto}</td> <td class='listr' style=\"word-wrap:break-word;\">{$alert_class}</td> - <td class='listr' align='center' sorttable_customkey='{$fields[9]}'>{$alert_ip_src}</td> + <td class='listr' style=\"sorttable_customkey:{$fields['src']};\" sorttable_customkey=\"{$fields['src']}\" align='center'>{$alert_ip_src}</td> <td class='listr' align='center'>{$alert_src_p}</td> - <td class='listr' align='center' sorttable_customkey='{$fields[11]}'>{$alert_ip_dst}</td> + <td class='listr' align='center' style=\"sorttable_customkey:{$fields['dst']};\" sorttable_customkey=\"{$fields['dst']}\">{$alert_ip_dst}</td> <td class='listr' align='center'>{$alert_dst_p}</td> - <td class='listr' align='center' sorttable_customkey='{$fields[3]}'>{$alert_sid_str}<br/>{$sidsupplink} {$sid_dsbl_link}</td> + <td class='listr' align='center' style=\"sorttable_customkey:{$fields['sid']};\" sorttable_customkey=\"{$fields['sid']}\">{$alert_sid_str}<br/>{$sidsupplink} {$sid_dsbl_link}</td> <td class='listbg' style=\"word-wrap:break-word;\">{$alert_descr}</td> </tr>\n"; $counter++; } + unset($fields, $buf, $tmp); fclose($fd); @unlink("/tmp/alerts_suricata{$suricata_uuid}"); } @@ -591,10 +835,10 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo </tbody> </table> </td> -</tr> +</tr></tbody> </table> </div> -</td></tr> +</td></tr></tbody> </table> </form> <?php @@ -615,6 +859,50 @@ function encRuleSig(rulegid,rulesid,srcip,ruledescr) { document.getElementById("ip").value = srcip; document.getElementById("descr").value = ruledescr; } + +function enable_showFilter() { + document.getElementById("filter_enable_row").style.display="none"; + document.getElementById("filter_options_row").style.display="table-row"; +} + +function enable_hideFilter() { + document.getElementById("filter_enable_row").style.display="table-row"; + document.getElementById("filter_options_row").style.display="none"; +} + +</script> + +<!-- The following AJAX code was borrowed from the diag_logs_filter.php --> +<!-- file in pfSense. See copyright info at top of this page. --> +<script type="text/javascript"> +//<![CDATA[ +function resolve_with_ajax(ip_to_resolve) { + var url = "/suricata/suricata_alerts.php"; + + jQuery.ajax( + url, + { + type: 'post', + dataType: 'json', + data: { + resolve: ip_to_resolve, + }, + complete: resolve_ip_callback + }); +} + +function resolve_ip_callback(transport) { + var response = jQuery.parseJSON(transport.responseText); + var msg = 'IP address "' + response.resolve_ip + '" resolves to\n'; + alert(msg + 'host "' + htmlspecialchars(response.resolve_text) + '"'); +} + +// From http://stackoverflow.com/questions/5499078/fastest-method-to-escape-html-tags-as-html-entities +function htmlspecialchars(str) { + return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); +} +//]]> </script> + </body> </html> diff --git a/config/suricata/suricata_alerts.widget.php b/config/suricata/suricata_alerts.widget.php index 21fad03d..bc7a0e2a 100644 --- a/config/suricata/suricata_alerts.widget.php +++ b/config/suricata/suricata_alerts.widget.php @@ -42,8 +42,8 @@ if (!is_array($config['installedpackages']['suricata']['rule'])) $a_instance = &$config['installedpackages']['suricata']['rule']; /* array sorting */ -function sksort(&$array, $subkey="id", $sort_ascending=false) { - /* an empty array causes sksort to fail - this test alleviates the error */ +function suricata_sksort(&$array, $subkey="id", $sort_ascending=false) { + /* an empty array causes suricata_sksort to fail - this test alleviates the error */ if(empty($array)) return false; if (count($array)){ @@ -114,12 +114,58 @@ function suricata_widget_get_alerts() { exec("tail -{$suri_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 */ + /*************** FORMAT without CSV patch -- ALERT -- ***********************************************************************************/ + /* Line format: timestamp action[**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] {proto} src:srcport -> dst:dstport */ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /****************************************************************************************************************************************/ + + /**************** FORMAT without CSV patch -- DECODER EVENT -- **************************************************************************/ + /* Line format: timestamp action[**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] [**] [Raw pkt: ...] */ + /* 0 1 2 3 4 5 6 7 */ + /************** *************************************************************************************************************************/ + $fd = fopen("/tmp/surialerts_{$suricata_uuid}", "r"); - while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { - if(count($fields) < 13) - continue; + $buf = ""; + while (($buf = fgets($fd)) !== FALSE) { + $fields = array(); + $tmp = array(); + + // Parse alert log entry to find the parts we want to display + $fields[0] = substr($buf, 0, strpos($buf, ' ')); + + // The regular expression match below returns an array as follows: + // [1] => CLASSIFICATION, [2] = PRIORITY + preg_match('/\s\[Classification:\s(.*)\]\s\[Priority:\s(\d+)\]\s/', $buf, $tmp); + $fields[6] = trim($tmp[1]); + $fields[7] = trim($tmp[2]); + + // The regular expression match below looks for the PROTO, SRC and DST fields + // and returns an array as follows: + // [1] = PROTO, [2] => SRC:SPORT [3] => DST:DPORT + if (preg_match('/\{(.*)\}\s(.*)\s->\s(.*)/', $buf, $tmp)) { + // Get SRC + $fields[9] = trim(substr($tmp[2], 0, strrpos($tmp[2], ':'))); + if (is_ipaddrv6($fields[9])) + $fields[9] = inet_ntop(inet_pton($fields[9])); + + // Get SPORT + $fields[10] = trim(substr($tmp[2], strrpos($tmp[2], ':') + 1)); + + // Get DST + $fields[11] = trim(substr($tmp[3], 0, strrpos($tmp[3], ':'))); + if (is_ipaddrv6($fields[11])) + $fields[11] = inet_ntop(inet_pton($fields[11])); + + // Get DPORT + $fields[12] = trim(substr($tmp[3], strrpos($tmp[3], ':') + 1)); + } + else { + // If no PROTO and IP ADDR, then this is a DECODER EVENT + $fields[9] = gettext("Decoder Event"); + $fields[10] = ""; + $fields[11] = ""; + $fields[12] = ""; + } // Create a DateTime object from the event timestamp that // we can use to easily manipulate output formats. @@ -130,7 +176,7 @@ function suricata_widget_get_alerts() { if ($fields[6] == "(null)") $fields[6] = "No classtype assigned"; - $suricata_alerts[$counter]['instanceid'] = strtoupper($a_instance[$instanceid]['interface']); + $suricata_alerts[$counter]['instanceid'] = strtoupper(convert_friendly_interface_to_friendly_descr($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"); @@ -140,15 +186,15 @@ function suricata_widget_get_alerts() { else $suricata_alerts[$counter]['src'] = $fields[9]; // Add the SRC PORT if not null - if (!empty($fields[10])) + if (!empty($fields[10]) || $fields[10] == '0') $suricata_alerts[$counter]['src'] .= ":" . $fields[10]; // Add square brackets around any IPv6 address if (is_ipaddrv6($fields[11])) $suricata_alerts[$counter]['dst'] = "[" . $fields[11] . "]"; else $suricata_alerts[$counter]['dst'] = $fields[11]; - // Add the SRC PORT if not null - if (!empty($fields[12])) + // Add the DST PORT if not null + if (!empty($fields[12]) || $fields[12] == '0') $suricata_alerts[$counter]['dst'] .= ":" . $fields[12]; $suricata_alerts[$counter]['priority'] = $fields[7]; $suricata_alerts[$counter]['category'] = $fields[6]; @@ -162,9 +208,9 @@ function suricata_widget_get_alerts() { // Sort the alerts array if (isset($config['syslog']['reverse'])) { - sksort($suricata_alerts, 'timestamp', false); + suricata_sksort($suricata_alerts, 'timestamp', false); } else { - sksort($suricata_alerts, 'timestamp', true); + suricata_sksort($suricata_alerts, 'timestamp', true); } return $suricata_alerts; @@ -192,7 +238,7 @@ function suricata_widget_get_alerts() { <tr> <th class="listhdrr"><?=gettext("IF/Date");?></th> <th class="listhdrr"><?=gettext("Src/Dst Address");?></th> - <th class="listhdrr"><?=gettext("Classification");?></th> + <th class="listhdrr"><?=gettext("Priority/Class");?></th> </tr> </thead> <tbody id="suricata-alert-entries"> diff --git a/config/suricata/suricata_app_parsers.php b/config/suricata/suricata_app_parsers.php index c28b99d1..16927092 100644 --- a/config/suricata/suricata_app_parsers.php +++ b/config/suricata/suricata_app_parsers.php @@ -86,13 +86,14 @@ if (isset($id) && $a_nat[$id]) { if (empty($pconfig['libhtp_policy']['item'])) { $default = array( "name" => "default", "bind_to" => "all", "personality" => "IDS", "request-body-limit" => 4096, "response-body-limit" => 4096, - "double-decode-path" => "no", "double-decode-query" => "no" ); + "double-decode-path" => "no", "double-decode-query" => "no", + "uri-include-all" => "no" ); $pconfig['libhtp_policy']['item'] = array(); $pconfig['libhtp_policy']['item'][] = $default; if (!is_array($a_nat[$id]['libhtp_policy']['item'])) $a_nat[$id]['libhtp_policy']['item'] = array(); $a_nat[$id]['libhtp_policy']['item'][] = $default; - write_config(); + write_config("Suricata pkg: created a new default HTTP server configuration for " . convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface'])); $libhtp_engine_next_id++; } else @@ -121,6 +122,7 @@ elseif ($_POST['select_alias']) { $eng_resp_body_limit = $_POST['resp_body_limit']; $eng_enable_double_decode_path = $_POST['enable_double_decode_path']; $eng_enable_double_decode_query = $_POST['enable_double_decode_query']; + $eng_enable_uri_include_all = $_POST['enable_uri_include_all']; $mode = "add_edit_libhtp_policy"; } if ($_POST['save_libhtp_policy']) { @@ -161,6 +163,7 @@ if ($_POST['save_libhtp_policy']) { if ($_POST['enable_double_decode_path']) { $engine['double-decode-path'] = 'yes'; }else{ $engine['double-decode-path'] = 'no'; } if ($_POST['enable_double_decode_query']) { $engine['double-decode-query'] = 'yes'; }else{ $engine['double-decode-query'] = 'no'; } + if ($_POST['enable_uri_include_all']) { $engine['uri-include-all'] = 'yes'; }else{ $engine['uri-include-all'] = 'no'; } // Can only have one "all" Bind_To address if ($engine['bind_to'] == "all" && $engine['name'] <> "default") @@ -196,7 +199,7 @@ if ($_POST['save_libhtp_policy']) { } // Now write the new engine array to conf - write_config(); + write_config("Suricata pkg: saved updated HTTP server configuration for " . convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface'])); $pconfig['libhtp_policy']['item'] = $a_nat[$id]['libhtp_policy']['item']; } else { @@ -209,7 +212,7 @@ elseif ($_POST['add_libhtp_policy']) { $add_edit_libhtp_policy = true; $pengcfg = array( "name" => "engine_{$libhtp_engine_next_id}", "bind_to" => "", "personality" => "IDS", "request-body-limit" => "4096", "response-body-limit" => "4096", - "double-decode-path" => "no", "double-decode-query" => "no" ); + "double-decode-path" => "no", "double-decode-query" => "no", "uri-include-all" => "no" ); $eng_id = $libhtp_engine_next_id; } elseif ($_POST['edit_libhtp_policy']) { @@ -229,7 +232,7 @@ elseif ($_POST['del_libhtp_policy']) { } if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; - write_config(); + write_config("Suricata pkg: deleted a HTTP server configuration for " . convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface'])); } } elseif ($_POST['cancel_libhtp_policy']) { @@ -239,9 +242,24 @@ elseif ($_POST['ResetAll']) { /* Reset all the settings to defaults */ $pconfig['asn1_max_frames'] = "256"; + $pconfig['dns_global_memcap'] = "16777216"; + $pconfig['dns_state_memcap'] = "524288"; + $pconfig['dns_request_flood_limit'] = "500"; + $pconfig['http_parser_memcap'] = "67108864"; + $pconfig['dns_parser_udp'] = "yes"; + $pconfig['dns_parser_tcp'] = "yes"; + $pconfig['http_parser'] = "yes"; + $pconfig['tls_parser'] = "yes"; + $pconfig['smtp_parser'] = "yes"; + $pconfig['imap_parser'] = "detection-only"; + $pconfig['ssh_parser'] = "yes"; + $pconfig['ftp_parser'] = "yes"; + $pconfig['dcerpc_parser'] = "yes"; + $pconfig['smb_parser'] = "yes"; + $pconfig['msn_parser'] = "detection-only"; /* Log a message at the top of the page to inform the user */ - $savemsg = gettext("All flow and stream settings have been reset to their defaults."); + $savemsg = gettext("All flow and stream settings on this page have been reset to their defaults. Click APPLY if you wish to keep these new settings."); } elseif ($_POST['save_import_alias']) { // If saving out of "select alias" mode, @@ -257,6 +275,7 @@ elseif ($_POST['save_import_alias']) { $pengcfg['response-body-limit'] = $_POST['eng_resp_body_limit']; $pengcfg['double-decode-path'] = $_POST['eng_enable_double_decode_path']; $pengcfg['double-decode-query'] = $_POST['eng_enable_double_decode_query']; + $pengcfg['uri-include-all'] = $_POST['eng_enable_uri_include_all']; $add_edit_libhtp_policy = true; $mode = "add_edit_libhtp_policy"; @@ -277,12 +296,13 @@ elseif ($_POST['save_import_alias']) { $eng_resp_body_limit = $_POST['eng_resp_body_limit']; $eng_enable_double_decode_path = $_POST['eng_enable_double_decode_path']; $eng_enable_double_decode_query = $_POST['eng_enable_double_decode_query']; + $eng_enable_uri_include_all = $_POST['eng_enable_uri_include_all']; } } else { $engine = array( "name" => "", "bind_to" => "", "personality" => "IDS", "request-body-limit" => "4096", "response-body-limit" => "4096", - "double-decode-path" => "no", "double-decode-query" => "no" ); + "double-decode-path" => "no", "double-decode-query" => "no", "uri-include-all" => "no" ); // See if anything was checked to import if (is_array($_POST['aliastoimport']) && count($_POST['aliastoimport']) > 0) { @@ -322,7 +342,7 @@ elseif ($_POST['save_import_alias']) { } // Write the new engine array to config file - write_config(); + write_config("Suricata pkg: saved an updated HTTP server configuration for " . convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface'])); $importalias = false; } } @@ -344,10 +364,11 @@ elseif ($_POST['cancel_import_alias']) { $pengcfg['response-body-limit'] = $_POST['eng_resp_body_limit']; $pengcfg['double-decode-path'] = $_POST['eng_enable_double_decode_path']; $pengcfg['double-decode-query'] = $_POST['eng_enable_double_decode_query']; + $pengcfg['uri-include-all'] = $_POST['eng_enable_uri_include_all']; $add_edit_libhtp_policy = true; } } -elseif ($_POST['save']) { +elseif ($_POST['save'] || $_POST['apply']) { $natent = array(); $natent = $pconfig; @@ -355,9 +376,37 @@ elseif ($_POST['save']) { if (!is_numeric($_POST['asn1_max_frames'] ) || $_POST['asn1_max_frames'] < 1) $input_errors[] = gettext("The value for 'ASN1 Max Frames' must be all numbers and greater than 0."); + if (!is_numeric($_POST['dns_global_memcap'] ) || $_POST['dns_global_memcap'] < 1) + $input_errors[] = gettext("The value for 'DNS Global Memcap' must be all numbers and greater than 0."); + + if (!is_numeric($_POST['dns_state_memcap'] ) || $_POST['dns_state_memcap'] < 1) + $input_errors[] = gettext("The value for 'DNS Flow/State Memcap' must be all numbers and greater than 0."); + + if (!is_numeric($_POST['dns_request_flood_limit'] ) || $_POST['dns_request_flood_limit'] < 1) + $input_errors[] = gettext("The value for 'DNS Request Flood Limit' must be all numbers and greater than 0."); + + if (!is_numeric($_POST['http_parser_memcap'] ) || $_POST['http_parser_memcap'] < 1) + $input_errors[] = gettext("The value for 'HTTP Memcap' must be all numbers and greater than 0."); + /* if no errors write to conf */ if (!$input_errors) { if ($_POST['asn1_max_frames'] != "") { $natent['asn1_max_frames'] = $_POST['asn1_max_frames']; }else{ $natent['asn1_max_frames'] = "256"; } + if ($_POST['dns_global_memcap'] != ""){ $natent['dns_global_memcap'] = $_POST['dns_global_memcap']; }else{ $natent['dns_global_memcap'] = "16777216"; } + if ($_POST['dns_state_memcap'] != ""){ $natent['dns_state_memcap'] = $_POST['dns_state_memcap']; }else{ $natent['dns_state_memcap'] = "524288"; } + if ($_POST['dns_request_flood_limit'] != ""){ $natent['dns_request_flood_limit'] = $_POST['dns_request_flood_limit']; }else{ $natent['dns_request_flood_limit'] = "500"; } + if ($_POST['http_parser_memcap'] != ""){ $natent['http_parser_memcap'] = $_POST['http_parser_memcap']; }else{ $natent['http_parser_memcap'] = "67108864"; } + + $natent['dns_parser_udp'] = $_POST['dns_parser_udp']; + $natent['dns_parser_tcp'] = $_POST['dns_parser_tcp']; + $natent['http_parser'] = $_POST['http_parser']; + $natent['tls_parser'] = $_POST['tls_parser']; + $natent['smtp_parser'] = $_POST['smtp_parser']; + $natent['imap_parser'] = $_POST['imap_parser']; + $natent['ssh_parser'] = $_POST['ssh_parser']; + $natent['ftp_parser'] = $_POST['ftp_parser']; + $natent['dcerpc_parser'] = $_POST['dcerpc_parser']; + $natent['smb_parser'] = $_POST['smb_parser']; + $natent['msn_parser'] = $_POST['msn_parser']; /**************************************************/ /* If we have a valid rule ID, save configuration */ @@ -366,9 +415,11 @@ elseif ($_POST['save']) { /**************************************************/ if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; - write_config(); + write_config("Suricata pkg: saved updated app-layer parser configuration for " . convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface'])); $rebuild_rules = false; + conf_mount_rw(); suricata_generate_yaml($natent); + conf_mount_ro(); } header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -382,37 +433,45 @@ elseif ($_POST['save']) { } $if_friendly = convert_friendly_interface_to_friendly_descr($pconfig['interface']); -$pgtitle = gettext("Suricata: Interface {$if_friendly} - Layer 7 Application Parsers"); +$pgtitle = gettext("Suricata: Interface {$if_friendly} - Application Layer Parsers"); include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); - /* Display error or save message */ + /* Display error message */ if ($input_errors) { print_input_errors($input_errors); } - if ($savemsg) { - print_info_box($savemsg); - } ?> <form action="suricata_app_parsers.php" method="post" name="iform" id="iform"> <input name="id" type="hidden" value="<?=$id;?>"/> <input type="hidden" name="eng_id" id="eng_id" value="<?=$eng_id;?>"/> + +<?php +if ($savemsg) { + /* Display save message */ + print_info_box($savemsg); +} +?> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; @@ -440,6 +499,7 @@ include_once("head.inc"); echo '<input type="hidden" name="eng_resp_body_limit" value="' . $eng_resp_body_limit . '"/>'; echo '<input type="hidden" name="eng_enable_double_decode_path" value="' . $eng_enable_double_decode_path . '"/>'; echo '<input type="hidden" name="eng_enable_double_decode_query" value="' . $eng_enable_double_decode_query . '"/>'; + echo '<input type="hidden" name="eng_enable_uri_include_all" value="' . $eng_enable_uri_include_all . '"/>'; } ?> @@ -449,6 +509,7 @@ include_once("head.inc"); <?php else: ?> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Abstract Syntax One Settings"); ?></td> @@ -465,11 +526,103 @@ include_once("head.inc"); gettext("H.323 (VoIP), and SNMP, use ASN.1 to describe the protocol data units (PDUs) they exchange."); ?> </td> </tr> + + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("DNS App-Layer Parser Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Global Memcap"); ?></td> + <td width="78%" class="vtable"> + <input name="dns_global_memcap" type="text" class="formfld unknown" id="dns_global_memcap" size="9" + value="<?=htmlspecialchars($pconfig['dns_global_memcap']);?>"> + <?php echo gettext("Sets the global memcap limit for the DNS parser. Default is ") . + "<strong>" . gettext("16777216") . "</strong>" . gettext(" bytes (16MB)."); ?> + </td> + </tr> <tr> - <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Host-Specific HTTP Server Settings"); ?></td> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Flow/State Memcap"); ?></td> + <td width="78%" class="vtable"> + <input name="dns_state_memcap" type="text" class="formfld unknown" id="dns_state_memcap" size="9" + value="<?=htmlspecialchars($pconfig['dns_state_memcap']);?>"> + <?php echo gettext("Sets per flow/state memcap limit for the DNS parser. Default is ") . + "<strong>" . gettext("524288") . "</strong>" . gettext(" bytes (512KB)."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Request Flood Limit"); ?></td> + <td width="78%" class="vtable"> + <input name="dns_request_flood_limit" type="text" class="formfld unknown" id="dns_request_flood_limit" size="9" + value="<?=htmlspecialchars($pconfig['dns_request_flood_limit']);?>"> + <?php echo gettext("How many unreplied DNS requests are considered a flood. Default is ") . + "<strong>" . gettext("500") . "</strong>" . gettext(" requests."); ?><br/> + <?php echo gettext("If this limit is reached, 'app-layer-event:dns.flooded' will match and alert. "); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("UDP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="dns_parser_udp" id="dns_parser_udp" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['dns_parser_udp']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for UDP. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("TCP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="dns_parser_tcp" id="dns_parser_tcp" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['dns_parser_tcp']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for TCP. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("HTTP App-Layer Parser Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Memcap"); ?></td> + <td width="78%" class="vtable"> + <input name="http_parser_memcap" type="text" class="formfld unknown" id="http_parser_memcap" size="9" + value="<?=htmlspecialchars($pconfig['http_parser_memcap']);?>"> + <?php echo gettext("Sets the memcap limit for the HTTP parser. Default is ") . + "<strong>" . gettext("67108864") . "</strong>" . gettext(" bytes (64MB)."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("HTTP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="http_parser" id="http_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['http_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for HTTP. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> </tr> <tr> - <td width="22%" valign="top" class="vncell"><?php echo gettext("Server Configuration"); ?></td> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Server Configurations"); ?></td> <td width="78%" class="vtable"> <table width="95%" align="left" id="libhtpEnginesTable" style="table-layout: fixed;" border="0" cellspacing="0" cellpadding="0"> <colgroup> @@ -487,6 +640,7 @@ include_once("head.inc"); height="17" border="0" title="<?php echo gettext("Add a new server configuration");?>"></th> </tr> </thead> + <tbody> <?php foreach ($pconfig['libhtp_policy']['item'] as $f => $v): ?> <tr> <td class="listlr" align="left"><?=gettext($v['name']);?></td> @@ -505,19 +659,159 @@ include_once("head.inc"); </td> </tr> <?php endforeach; ?> + </tbody> </table> </td> </tr> <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Other App-Layer Parser Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("TLS Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="tls_parser" id="tls_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['tls_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for TLS. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("SMTP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="smtp_parser" id="smtp_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['smtp_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for SMTP. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("IMAP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="imap_parser" id="imap_parser" class="formselect"> + <?php + $opt = array( "detection-only", "yes", "no" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['imap_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for IMAP. Default is ") . "<strong>" . gettext("detection-only") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("SSH Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="ssh_parser" id="ssh_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['ssh_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for SSH. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("FTP Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="ftp_parser" id="ftp_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['ftp_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for FTP. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("DCERPC Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="dcerpc_parser" id="dcerpc_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['dcerpc_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for DCERPC. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("SMB Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="smb_parser" id="smb_parser" class="formselect"> + <?php + $opt = array( "yes", "no", "detection-only" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['smb_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for SMB. Default is ") . "<strong>" . gettext("yes") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("MSN Parser"); ?></td> + <td width="78%" class="vtable"> + <select name="msn_parser" id="msn_parser" class="formselect"> + <?php + $opt = array( "detection-only", "yes", "no" ); + foreach ($opt as $val) { + $selected = ""; + if ($val == $pconfig['msn_parser']) + $selected = " selected"; + echo "<option value='{$val}'{$selected}>" . $val . "</option>\n"; + } + ?></select> + <?php echo gettext("Choose the parser/detection setting for MSN. Default is ") . "<strong>" . gettext("detection-only") . "</strong>" . gettext("."); ?><br/> + <?php echo gettext("Selecting \"yes\" enables detection and parser, \"no\" disables both and \"detection-only\" disables parser."); ?> + </td> + </tr> + <tr> <td width="22%" valign="top"> </td> <td width="78%"> <input name="save" type="submit" class="formbtn" value="Save" title="<?php echo - gettext("Save flow and stream settings"); ?>"> + gettext("Save flow and stream settings"); ?>"/> <input name="ResetAll" type="submit" class="formbtn" value="Reset" title="<?php echo gettext("Reset all settings to defaults") . "\" onclick=\"return confirm('" . gettext("WARNING: This will reset ALL App Parsers settings to their defaults. Click OK to continue or CANCEL to quit.") . - "');\""; ?>></td> + "');\""; ?>/></td> </tr> <tr> <td width="22%" valign="top"> </td> @@ -525,12 +819,13 @@ include_once("head.inc"); <?php echo gettext("Please save your settings before you exit. Changes will rebuild the rules file. This "); ?> <?php echo gettext("may take several seconds. Suricata must also be restarted to activate any changes made on this screen."); ?></td> </tr> + </tbody> </table> <?php endif; ?> </div> -</td></tr></table> +</td></tr></tbody></table> </form> <?php include("fend.inc"); ?> </body> diff --git a/config/suricata/suricata_barnyard.php b/config/suricata/suricata_barnyard.php index c7488fe4..cd233b5e 100644 --- a/config/suricata/suricata_barnyard.php +++ b/config/suricata/suricata_barnyard.php @@ -79,7 +79,7 @@ if (isset($id) && $a_nat[$id]) { if (empty($a_nat[$id]['barnyard_syslog_opmode'])) $pconfig['barnyard_syslog_opmode'] = "default"; if (empty($a_nat[$id]['barnyard_syslog_facility'])) - $pconfig['barnyard_syslog_facility'] = "LOG_USER"; + $pconfig['barnyard_syslog_facility'] = "LOG_LOCAL1"; if (empty($a_nat[$id]['barnyard_syslog_priority'])) $pconfig['barnyard_syslog_priority'] = "LOG_INFO"; if (empty($a_nat[$id]['barnyard_bro_ids_dport'])) @@ -94,6 +94,12 @@ if ($_POST['save']) { $_POST['barnyard_bro_ids_enable'] != 'on' && $_POST['barnyard_enable'] == "on") $input_errors[] = gettext("You must enable at least one output option when using Barnyard2."); + // Validate Sensor Name contains no spaces + if ($_POST['barnyard_enable'] == 'on') { + if (!empty(trim($_POST['barnyard_sensor_name'])) && strpos(trim($_POST['barnyard_sensor_name']), " ") !== FALSE) + $input_errors[] = gettext("The value for 'Sensor Name' cannot contain spaces."); + } + // Validate Sensor ID is a valid integer if ($_POST['barnyard_enable'] == 'on') { if (!is_numericint($_POST['barnyard_sensor_id']) || $_POST['barnyard_sensor_id'] < 0) @@ -147,7 +153,7 @@ if ($_POST['save']) { $natent['barnyard_syslog_proto'] = $_POST['barnyard_syslog_proto']; if ($_POST['barnyard_sensor_id']) $natent['barnyard_sensor_id'] = $_POST['barnyard_sensor_id']; else $natent['barnyard_sensor_id'] = '0'; - if ($_POST['barnyard_sensor_name']) $natent['barnyard_sensor_name'] = $_POST['barnyard_sensor_name']; else unset($natent['barnyard_sensor_name']); + if ($_POST['barnyard_sensor_name']) $natent['barnyard_sensor_name'] = trim($_POST['barnyard_sensor_name']); else unset($natent['barnyard_sensor_name']); if ($_POST['barnyard_dbhost']) $natent['barnyard_dbhost'] = $_POST['barnyard_dbhost']; else unset($natent['barnyard_dbhost']); if ($_POST['barnyard_dbname']) $natent['barnyard_dbname'] = $_POST['barnyard_dbname']; else unset($natent['barnyard_dbname']); if ($_POST['barnyard_dbuser']) $natent['barnyard_dbuser'] = $_POST['barnyard_dbuser']; else unset($natent['barnyard_dbuser']); @@ -158,7 +164,7 @@ if ($_POST['save']) { if ($_POST['barnyard_syslog_priority']) $natent['barnyard_syslog_priority'] = $_POST['barnyard_syslog_priority']; else $natent['barnyard_syslog_priority'] = 'LOG_INFO'; if ($_POST['barnyard_bro_ids_rhost']) $natent['barnyard_bro_ids_rhost'] = $_POST['barnyard_bro_ids_rhost']; else unset($natent['barnyard_bro_ids_rhost']); if ($_POST['barnyard_bro_ids_dport']) $natent['barnyard_bro_ids_dport'] = $_POST['barnyard_bro_ids_dport']; else $natent['barnyard_bro_ids_dport'] = '47760'; - if ($_POST['barnconfigpassthru']) $natent['barnconfigpassthru'] = base64_encode($_POST['barnconfigpassthru']); else unset($natent['barnconfigpassthru']); + if ($_POST['barnconfigpassthru']) $natent['barnconfigpassthru'] = base64_encode(str_replace("\r\n", "\n", $_POST['barnconfigpassthru'])); else unset($natent['barnconfigpassthru']); $a_nat[$id] = $natent; write_config(); @@ -213,18 +219,21 @@ include_once("head.inc"); <form action="suricata_barnyard.php" method="post" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -243,6 +252,7 @@ include_once("head.inc"); <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Barnyard2 " . "Settings"); ?></td> @@ -380,7 +390,7 @@ include_once("head.inc"); <input name="barnyard_syslog_local" type="checkbox" value="on" <?php if ($pconfig['barnyard_syslog_local'] == "on") echo "checked"; ?> onClick="toggle_local_syslog()"/> <?php echo gettext("Enable logging of alerts to the local system only"); ?><br/> - <?php echo gettext("This will send alert data to the local system only and overrides the host, port, protocol, facility and priority values below."); ?></td> + <?php echo gettext("This will send alert data to the local system only and overrides the host, port and protocol values below."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Remote Host"); ?></td> @@ -414,8 +424,8 @@ include_once("head.inc"); <td width="78%" class="vtable"> <select name="barnyard_syslog_facility" id="barnyard_syslog_facility" class="formselect"> <?php - $log_facility = array( "LOG_AUTH", "LOG_AUTHPRIV", "LOG_DAEMON", "LOG_KERN", "LOG_SYSLOG", "LOG_USER", "LOG_LOCAL1", - "LOG_LOCAL2", "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7" ); + $log_facility = array( "LOG_AUTH", "LOG_AUTHPRIV", "LOG_DAEMON", "LOG_KERN", "LOG_SYSLOG", "LOG_USER", "LOG_LOCAL0", + "LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7" ); foreach ($log_facility as $facility) { $selected = ""; if ($facility == $pconfig['barnyard_syslog_facility']) @@ -423,7 +433,7 @@ include_once("head.inc"); echo "<option value='{$facility}'{$selected}>" . $facility . "</option>\n"; } ?></select> - <?php echo gettext("Select Syslog Facility to use for remote reporting. Default is ") . "<strong>" . gettext("LOG_USER") . "</strong>."; ?> + <?php echo gettext("Select Syslog Facility to use for remote reporting. Default is ") . "<strong>" . gettext("LOG_LOCAL1") . "</strong>."; ?> </td> </tr> <tr> @@ -431,7 +441,7 @@ include_once("head.inc"); <td width="78%" class="vtable"> <select name="barnyard_syslog_priority" id="barnyard_syslog_priority" class="formselect"> <?php - $log_priority = array( "LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR", "LOG_WARNING", "LOG_NOTICE", "LOG_INFO" ); + $log_priority = array( "LOG_EMERG", "LOG_CRIT", "LOG_ALERT", "LOG_ERR", "LOG_WARNING", "LOG_NOTICE", "LOG_INFO" ); foreach ($log_priority as $priority) { $selected = ""; if ($priority == $pconfig['barnyard_syslog_priority']) @@ -496,10 +506,12 @@ include_once("head.inc"); <br/> <?php echo gettext("Please save your settings before you click start."); ?> </td> </tr> + </tbody> </table> </div> </td> </tr> + </tbody> </table> </form> @@ -547,8 +559,6 @@ function toggle_local_syslog() { document.iform.barnyard_syslog_dport.disabled = endis; document.iform.barnyard_syslog_proto_udp.disabled = endis; document.iform.barnyard_syslog_proto_tcp.disabled = endis; - document.iform.barnyard_syslog_facility.disabled = endis; - document.iform.barnyard_syslog_priority.disabled = endis; } } diff --git a/config/suricata/suricata_blocked.php b/config/suricata/suricata_blocked.php index 96171c1e..c29d5745 100644 --- a/config/suricata/suricata_blocked.php +++ b/config/suricata/suricata_blocked.php @@ -10,6 +10,7 @@ * Copyright (C) 2006 Scott Ullrich * Copyright (C) 2009 Robert Zelaya Sr. Developer * Copyright (C) 2012 Ermal Luci + * Copyright (C) 2014 Jim Pingle jim@pingle.org * All rights reserved. * * Adapted for Suricata by: @@ -55,6 +56,21 @@ if (empty($pconfig['blertnumber'])) else $bnentries = $pconfig['blertnumber']; +# --- AJAX REVERSE DNS RESOLVE Start --- +if (isset($_POST['resolve'])) { + $ip = strtolower($_POST['resolve']); + $res = (is_ipaddr($ip) ? gethostbyaddr($ip) : ''); + + if ($res && $res != $ip) + $response = array('resolve_ip' => $ip, 'resolve_text' => $res); + else + $response = array('resolve_ip' => $ip, 'resolve_text' => gettext("Cannot resolve")); + + echo json_encode(str_replace("\\","\\\\", $response)); // single escape chars can break JSON decode + exit; +} +# --- AJAX REVERSE DNS RESOLVE End --- + if ($_POST['todelete']) { $ip = ""; if ($_POST['ip']) @@ -138,8 +154,6 @@ include_once("head.inc"); ?> <body link="#000000" vlink="#000000" alink="#000000"> -<script src="/javascript/filter_log.js" type="text/javascript"></script> - <?php include_once("fbegin.inc"); @@ -161,19 +175,22 @@ if ($savemsg) { <input type="hidden" name="ip" id="ip" value=""/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr> <td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), true, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), true, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> @@ -181,6 +198,7 @@ if ($savemsg) { <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" class="listtopic"><?php echo gettext("Blocked Hosts Log View Settings"); ?></td> </tr> @@ -219,11 +237,11 @@ if ($savemsg) { <col width="10%" align="center"> </colgroup> <thead> - <tr> + <tr class="sortableHeaderRowIdentifier"> <th class="listhdrr" axis="number">#</th> <th class="listhdrr" axis="string"><?php echo gettext("IP"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Alert Description"); ?></th> - <th class="listhdrr"><?php echo gettext("Remove"); ?></th> + <th class="listhdrr sorttable_nosort"><?php echo gettext("Remove"); ?></th> </tr> </thead> <tbody> @@ -274,18 +292,15 @@ if ($savemsg) { $tmp_ip = str_replace(":", ":​", $block_ip_str); /* Add reverse DNS lookup icons */ $rdns_link = ""; - $rdns_link .= "<a onclick=\"javascript:getURL('/diag_dns.php?host={$block_ip_str}&dialog_output=true', outputrule);\">"; - $rdns_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_log_d.gif' width='11' height='11' border='0' "; - $rdns_link .= "title='" . gettext("Resolve host via reverse DNS lookup (quick pop-up)") . "' style=\"cursor: pointer;\"></a> "; - $rdns_link .= "<a href='/diag_dns.php?host={$block_ip_str}'>"; - $rdns_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_log.gif' width='11' height='11' border='0' "; - $rdns_link .= "title='" . gettext("Resolve host via reverse DNS lookup") . "'></a>"; + $rdns_link .= "<img onclick=\"javascript:resolve_with_ajax('{$block_ip_str}');\" title=\""; + $rdns_link .= gettext("Resolve host via reverse DNS lookup") . "\" border=\"0\" src=\"/themes/{$g['theme']}/images/icons/icon_log.gif\" alt=\"Icon Reverse Resolve with DNS\" "; + $rdns_link.= " style=\"cursor: pointer;\"/>"; /* use one echo to do the magic*/ echo "<tr> <td align=\"center\" valign=\"middle\" class=\"listr\">{$counter}</td> <td align=\"center\" valign=\"middle\" class=\"listr\">{$tmp_ip}<br/>{$rdns_link}</td> <td valign=\"middle\" class=\"listr\">{$blocked_desc}</td> - <td align=\"center\" valign=\"middle\" class=\"listr\" sorttable_customkey=\"\"> + <td align=\"center\" valign=\"middle\" class=\"listr\"> <input type=\"image\" name=\"todelete[]\" onClick=\"document.getElementById('ip').value='{$block_ip_str}';\" src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" title=\"" . gettext("Delete host from Blocked Table") . "\" border=\"0\" /></td> </tr>\n"; @@ -310,14 +325,49 @@ if ($savemsg) { ?> </td> </tr> + </tbody> </table> </div> </td> </tr> +</tbody> </table> </form> <?php include("fend.inc"); ?> + +<!-- The following AJAX code was borrowed from the diag_logs_filter.php --> +<!-- file in pfSense. See copyright info at top of this page. --> +<script type="text/javascript"> +//<![CDATA[ +function resolve_with_ajax(ip_to_resolve) { + var url = "/suricata/suricata_blocked.php"; + + jQuery.ajax( + url, + { + type: 'post', + dataType: 'json', + data: { + resolve: ip_to_resolve, + }, + complete: resolve_ip_callback + }); +} + +function resolve_ip_callback(transport) { + var response = jQuery.parseJSON(transport.responseText); + var msg = 'IP address "' + response.resolve_ip + '" resolves to\n'; + alert(msg + 'host "' + htmlspecialchars(response.resolve_text) + '"'); +} + +// From http://stackoverflow.com/questions/5499078/fastest-method-to-escape-html-tags-as-html-entities +function htmlspecialchars(str) { + return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); +} +//]]> +</script> + </body> </html> diff --git a/config/suricata/suricata_check_cron_misc.inc b/config/suricata/suricata_check_cron_misc.inc index f750c530..70394a23 100644 --- a/config/suricata/suricata_check_cron_misc.inc +++ b/config/suricata/suricata_check_cron_misc.inc @@ -72,7 +72,7 @@ function suricata_check_dir_size_limit($suricataloglimitsize) { } // Initialize an array of the log files we want to prune - $logs = array ( "alerts.log", "http.log", "files-json.log", "tls.log", "stats.log" ); + $logs = array ( "alerts.log", "block.log", "dns.log", "eve.json", "http.log", "files-json.log", "sid_changes.log", "stats.log", "tls.log" ); // Clean-up the logs for each configured Suricata instance foreach ($config['installedpackages']['suricata']['rule'] as $value) { @@ -126,8 +126,10 @@ function suricata_check_rotate_log($log_file, $log_limit, $retention) { // Check the current log to see if it needs rotating. // If it does, rotate it and put the current time // on the end of the filename as UNIX timestamp. + if (!file_exists($log_file)) + return; if (($log_limit > 0) && (filesize($log_file) >= $log_limit)) { - $newfile = $log_file . "." . strval(time()); + $newfile = $log_file . "." . date('Y_md_Hi'); try { copy($log_file, $newfile); file_put_contents($log_file, ""); @@ -168,10 +170,18 @@ $logs = array (); // Build an arry of files to check and limits to check them against from our saved configuration $logs['alerts.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['alert_log_limit_size']; $logs['alerts.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['alert_log_retention']; +$logs['block.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['block_log_limit_size']; +$logs['block.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['block_log_retention']; +$logs['dns.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['dns_log_limit_size']; +$logs['dns.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['dns_log_retention']; +$logs['eve.json']['limit'] = $config['installedpackages']['suricata']['config'][0]['eve_log_limit_size']; +$logs['eve.json']['retention'] = $config['installedpackages']['suricata']['config'][0]['eve_log_retention']; $logs['files-json.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_limit_size']; $logs['files-json.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_retention']; $logs['http.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['http_log_limit_size']; $logs['http.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['http_log_retention']; +$logs['sid_changes.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size']; +$logs['sid_changes.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention']; $logs['stats.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['stats_log_limit_size']; $logs['stats.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['stats_log_retention']; $logs['tls.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['tls_log_limit_size']; @@ -190,12 +200,17 @@ if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] > 0) { $now = time(); $files = glob("{$suricata_log_dir}/barnyard2/archive/unified2.alert.*"); + $prune_count = 0; foreach ($files as $f) { - if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] * 3600)) + if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] * 3600)) { + $prune_count++; unlink_if_exists($f); + } } + if ($prune_count > 0) + log_error(gettext("[Suricata] Barnyard2 archived logs cleanup job removed {$prune_count} file(s) from {$suricata_log_dir}/barnyard2/archive/...")); + unset($files); } - unset($files); // Prune aged-out File Store files if any exist if (is_dir("{$suricata_log_dir}/files") && @@ -203,11 +218,15 @@ if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == $now = time(); $files = glob("{$suricata_log_dir}/files/file.*"); foreach ($files as $f) { - if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['file_store_retention'] * 3600)) + if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['file_store_retention'] * 3600)) { + $prune_count++; unlink_if_exists($f); + } } + if ($prune_count > 0) + log_error(gettext("[Suricata] File Store cleanup job removed {$prune_count} file(s) from {$suricata_log_dir}/files/...")); + unset($files); } - unset($files); } } diff --git a/config/suricata/suricata_check_for_rule_updates.php b/config/suricata/suricata_check_for_rule_updates.php index bb29078f..eeb7be6c 100644 --- a/config/suricata/suricata_check_for_rule_updates.php +++ b/config/suricata/suricata_check_for_rule_updates.php @@ -45,7 +45,7 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $pkg_interface, $suricata_gui_include, $rebuild_rules; if (!defined("VRT_DNLD_URL")) - define("VRT_DNLD_URL", "https://www.snort.org/reg-rules/"); + define("VRT_DNLD_URL", "https://www.snort.org/rules/"); if (!defined("ET_VERSION")) define("ET_VERSION", "2.9.0"); if (!defined("ET_BASE_DNLD_URL")) @@ -56,8 +56,6 @@ if (!defined("ET_DNLD_FILENAME")) define("ET_DNLD_FILENAME", "emerging.rules.tar.gz"); if (!defined("ETPRO_DNLD_FILENAME")) define("ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); -if (!defined("VRT_DNLD_FILENAME")) - define("VRT_DNLD_FILENAME", "snortrules-snapshot-edge.tar.gz"); if (!defined("GPLV2_DNLD_FILENAME")) define("GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); if (!defined("GPLV2_DNLD_URL")) @@ -86,6 +84,7 @@ else /* define checks */ $oinkid = $config['installedpackages']['suricata']['config'][0]['oinkcode']; +$snort_filename = $config['installedpackages']['suricata']['config'][0]['snort_rules_file']; $etproid = $config['installedpackages']['suricata']['config'][0]['etprocode']; $snortdownload = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules'] == 'on' ? 'on' : 'off'; $etpro = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules'] == 'on' ? 'on' : 'off'; @@ -96,8 +95,7 @@ $snortcommunityrules = $config['installedpackages']['suricata']['config'][0]['sn /* Working directory for downloaded rules tarballs */ $tmpfname = "/tmp/suricata_rules_up"; -/* Snort Edge VRT Rules filenames and URL */ -$snort_filename = VRT_DNLD_FILENAME; +/* Snort VRT Rules filenames and URL */ $snort_filename_md5 = "{$snort_filename}.md5"; $snort_rule_url = VRT_DNLD_URL; @@ -439,10 +437,15 @@ if ($emergingthreats == 'on') { /* Check for and download any new Snort VRT sigs */ if ($snortdownload == 'on') { - if (suricata_check_rule_md5("{$snort_rule_url}{$snort_filename_md5}/{$oinkid}/", "{$tmpfname}/{$snort_filename_md5}", "Snort VRT rules")) { + if (empty($snort_filename)) { + log_error(gettext("No snortrules-snapshot filename has been set on Snort pkg GLOBAL SETTINGS tab. Snort VRT rules cannot be updated.")); + error_log(gettext("\tWARNING-- No snortrules-snapshot filename set on GLOBAL SETTINGS tab. Snort VRT rules cannot be updated!\n"), 3, $suricata_rules_upd_log); + $snortdownload = 'off'; + } + elseif (suricata_check_rule_md5("{$snort_rule_url}{$snort_filename_md5}?oinkcode={$oinkid}", "{$tmpfname}/{$snort_filename_md5}", "Snort VRT rules")) { /* download snortrules file */ $file_md5 = trim(file_get_contents("{$tmpfname}/{$snort_filename_md5}")); - if (!suricata_fetch_new_rules("{$snort_rule_url}{$snort_filename}/{$oinkid}/", "{$tmpfname}/{$snort_filename}", $file_md5, "Snort VRT rules")) + if (!suricata_fetch_new_rules("{$snort_rule_url}{$snort_filename}?oinkcode={$oinkid}", "{$tmpfname}/{$snort_filename}", $file_md5, "Snort VRT rules")) $snortdownload = 'off'; } else @@ -483,7 +486,7 @@ if ($emergingthreats == 'on') { // The code below renames ET files with a prefix, so we // skip renaming the Suricata default events rule files // that are also bundled in the ET rules. - $default_rules = array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ); + $default_rules = array( "decoder-events.rules", "dns-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ); $files = glob("{$tmpfname}/emerging/rules/*.rules"); // Determine the correct prefix to use based on which // Emerging Threats rules package is enabled. @@ -759,7 +762,11 @@ if ($pkg_interface <> "console") { } log_error(gettext("[Suricata] The Rules update has finished.")); error_log(gettext("The Rules update has finished. Time: " . date("Y-m-d H:i:s"). "\n\n"), 3, $suricata_rules_upd_log); -conf_mount_ro(); + +// Remount filesystem read-only unless we are in package post-install. +// The post-install code will remount read-only when it completes. +if (!$g['suricata_postinstall']) + conf_mount_ro(); // Restore the state of $pkg_interface $pkg_interface = $pkg_interface_orig; @@ -770,6 +777,6 @@ if ($update_errors) else $config['installedpackages']['suricata']['config'][0]['last_rule_upd_status'] = gettext("success"); $config['installedpackages']['suricata']['config'][0]['last_rule_upd_time'] = time(); -write_config(); +write_config("Suricata pkg: updated status for updated rules package(s) check."); ?> diff --git a/config/suricata/suricata_define_vars.php b/config/suricata/suricata_define_vars.php index d072ff42..3fe5de0d 100644 --- a/config/suricata/suricata_define_vars.php +++ b/config/suricata/suricata_define_vars.php @@ -64,7 +64,7 @@ $suricata_servers = array ( "dns_servers" => "\$HOME_NET", "smtp_servers" => "\$HOME_NET", "http_servers" => "\$HOME_NET", "sql_servers" => "\$HOME_NET", "telnet_servers" => "\$HOME_NET", "dnp3_server" => "\$HOME_NET", "dnp3_client" => "\$HOME_NET", "modbus_server" => "\$HOME_NET", "modbus_client" => "\$HOME_NET", - "enip_server" => "\$HOME_NET", "enip_client" => "\$HOME_NET", + "enip_server" => "\$HOME_NET", "enip_client" => "\$HOME_NET", "ftp_servers" => "\$HOME_NET", "ssh_servers" => "\$HOME_NET", "aim_servers" => "64.12.24.0/23,64.12.28.0/23,64.12.161.0/24,64.12.163.0/24,64.12.200.0/24,205.188.3.0/24,205.188.5.0/24,205.188.7.0/24,205.188.9.0/24,205.188.153.0/24,205.188.179.0/24,205.188.248.0/24" ); @@ -74,6 +74,7 @@ if(is_array($config['system']['ssh']) && isset($config['system']['ssh']['port']) else $ssh_port = "22"; $suricata_ports = array( + "ftp_ports" => "21", "http_ports" => "80", "oracle_ports" => "1521", "ssh_ports" => $ssh_port, @@ -127,7 +128,9 @@ if ($_POST) { /* Update the suricata.yaml file for this interface. */ $rebuild_rules = false; + conf_mount_rw(); suricata_generate_yaml($a_nat[$id]); + conf_mount_ro(); /* Soft-restart Suricaa to live-load new variables. */ suricata_reload_config($a_nat[$id]); @@ -166,18 +169,21 @@ if ($savemsg) </script> <form action="suricata_define_vars.php" method="post" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -196,6 +202,7 @@ if ($savemsg) <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Define Servers (IP variables)"); ?></td> </tr> @@ -254,9 +261,10 @@ if ($savemsg) <input name="id" type="hidden" value="<?=$id;?>"> </td> </tr> + </tbody> </table> </div> -</td></tr> +</td></tr></tbody> </table> </form> <script type="text/javascript"> diff --git a/config/suricata/suricata_download_rules.php b/config/suricata/suricata_download_rules.php index 2de286ba..f0fbffeb 100644 --- a/config/suricata/suricata_download_rules.php +++ b/config/suricata/suricata_download_rules.php @@ -101,7 +101,7 @@ include("head.inc"); <?php $suricata_gui_include = true; -include("/usr/local/www/suricata/suricata_check_for_rule_updates.php"); +include("/usr/local/pkg/suricata/suricata_check_for_rule_updates.php"); /* hide progress bar and lets end this party */ echo "\n<script type=\"text/javascript\">document.progressbar.style.visibility='hidden';\n</script>"; diff --git a/config/suricata/suricata_download_updates.php b/config/suricata/suricata_download_updates.php index b5377351..89e959c9 100644 --- a/config/suricata/suricata_download_updates.php +++ b/config/suricata/suricata_download_updates.php @@ -50,6 +50,7 @@ $snortdownload = $config['installedpackages']['suricata']['config'][0]['enable_v $emergingthreats = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; $etpro = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; $snortcommunityrules = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; +$snort_rules_file = $config['installedpackages']['suricata']['config'][0]['snort_rules_file']; /* Get last update information if available */ if (!empty($config['installedpackages']['suricata']['config'][0]['last_rule_upd_time'])) @@ -61,7 +62,6 @@ if (!empty($config['installedpackages']['suricata']['config'][0]['last_rule_upd_ else $last_rule_upd_status = gettext("Unknown"); -$snort_rules_file = VRT_DNLD_FILENAME; $snort_community_rules_filename = GPLV2_DNLD_FILENAME; if ($etpro == "on") { @@ -82,7 +82,7 @@ else { $snort_org_sig_chk_local = 'Not Enabled'; $snort_org_sig_date = 'Not Enabled'; } -if (file_exists("{$suricatadir}{$snort_rules_file}.md5")){ +if ($snortdownload == 'on' && file_exists("{$suricatadir}{$snort_rules_file}.md5")){ $snort_org_sig_chk_local = file_get_contents("{$suricatadir}{$snort_rules_file}.md5"); $snort_org_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$snort_rules_file}.md5")); } @@ -95,7 +95,7 @@ else { $emergingt_net_sig_chk_local = 'Not Enabled'; $emergingt_net_sig_date = 'Not Enabled'; } -if (file_exists("{$suricatadir}{$emergingthreats_filename}.md5")) { +if (($etpro == "on" || $emergingthreats == "on") && file_exists("{$suricatadir}{$emergingthreats_filename}.md5")) { $emergingt_net_sig_chk_local = file_get_contents("{$suricatadir}{$emergingthreats_filename}.md5"); $emergingt_net_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$emergingthreats_filename}.md5")); } @@ -108,7 +108,7 @@ else { $snort_community_sig_chk_local = 'Not Enabled'; $snort_community_sig_sig_date = 'Not Enabled'; } -if (file_exists("{$suricatadir}{$snort_community_rules_filename}.md5")) { +if ($snortcommunityrules == 'on' && file_exists("{$suricatadir}{$snort_community_rules_filename}.md5")) { $snort_community_sig_chk_local = file_get_contents("{$suricatadir}{$snort_community_rules_filename}.md5"); $snort_community_sig_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$snort_community_rules_filename}.md5")); } @@ -119,7 +119,7 @@ if ($_POST['clear']) { mwexec("/bin/rm -f {$suricata_rules_upd_log}"); } -if ($_POST['check']) { +if ($_POST['update']) { // Go see if new updates for rule sets are available header("Location: /suricata/suricata_download_rules.php"); exit; @@ -177,21 +177,24 @@ include_once("head.inc"); print_info_box($savemsg); } ?> -<form action="suricata_download_updates.php" method="post" name="iform" id="iform"> +<form action="suricata_download_updates.php" enctype="multipart/form-data" method="post" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), true, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), true, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -199,6 +202,7 @@ include_once("head.inc"); <td> <div id="mainarea"> <table id="maintable4" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr> <td valign="top" class="listtopic" align="center"><?php echo gettext("INSTALLED RULE SET MD5 SIGNATURE");?></td> </tr> @@ -212,6 +216,7 @@ include_once("head.inc"); <th class="listhdrr"><?=gettext("MD5 Signature Date");?></th> </tr> </thead> + <tbody> <tr> <td align="center" class="vncell vexpl"><b><?=$et_name;?></b></td> <td align="center" class="vncell vexpl"><? echo trim($emergingt_net_sig_chk_local);?></td> @@ -227,6 +232,7 @@ include_once("head.inc"); <td align="center" class="vncell vexpl"><? echo trim($snort_community_sig_chk_local);?></td> <td align="center" class="vncell vexpl"><?php echo gettext($snort_community_sig_sig_date);?></td> </tr> + </tbody> </table><br/> </td> </tr> @@ -262,8 +268,8 @@ include_once("head.inc"); <br/></p> <?php else: ?> <br/> - <input type="submit" value="<?=gettext("Check");?>" name="check" id="check" class="formbtn" - title="<?php echo gettext("Check for new updates to enabled rule sets"); ?>"/> + <input type="submit" value="<?=gettext("Update");?>" name="update" id="update" class="formbtn" + title="<?php echo gettext("Check for and apply new update to enabled rule sets"); ?>"/> <input type="submit" value="<?=gettext("Force");?>" name="force" id="force" class="formbtn" title="<?=gettext("Force an update of all enabled rule sets");?>" onclick="return confirm('<?=gettext("This will zero-out the MD5 hashes to force a fresh download of all enabled rule sets. Click OK to continue or CANCEL to quit");?>');"/> @@ -271,7 +277,6 @@ include_once("head.inc"); <?php endif; ?> </td> </tr> - <tr> <td valign="top" class="listtopic" align="center"><?php echo gettext("MANAGE RULE SET LOG");?></td> </tr> @@ -318,10 +323,12 @@ include_once("head.inc"); gettext(" will go down from time to time. Please be patient."); ?></span><br/> </td> </tr> + </tbody> </table> </div> </td> </tr> +</tbody> </table> <!-- end of final table --> </form> diff --git a/config/suricata/suricata_flow_stream.php b/config/suricata/suricata_flow_stream.php index ba594d55..fa9edc16 100644 --- a/config/suricata/suricata_flow_stream.php +++ b/config/suricata/suricata_flow_stream.php @@ -251,7 +251,6 @@ elseif ($_POST['ResetAll']) { $pconfig['flow_icmp_emerg_established_timeout'] = '100'; $pconfig['stream_memcap'] = '33554432'; - $pconfig['stream_max_sessions'] = '262144'; $pconfig['stream_prealloc_sessions'] = '32768'; $pconfig['reassembly_memcap'] = '67108864'; $pconfig['reassembly_depth'] = '1048576'; @@ -261,9 +260,9 @@ elseif ($_POST['ResetAll']) { $pconfig['enable_async_sessions'] = 'off'; /* Log a message at the top of the page to inform the user */ - $savemsg = gettext("All flow and stream settings have been reset to their defaults."); + $savemsg = gettext("All flow and stream settings have been reset to their defaults. Click APPLY to save the changes."); } -elseif ($_POST['save']) { +elseif ($_POST['save'] || $_POST['apply']) { $natent = array(); $natent = $pconfig; @@ -300,7 +299,6 @@ elseif ($_POST['save']) { if ($_POST['flow_icmp_emerg_established_timeout'] != "") { $natent['flow_icmp_emerg_established_timeout'] = $_POST['flow_icmp_emerg_established_timeout']; }else{ $natent['flow_icmp_emerg_established_timeout'] = "100"; } if ($_POST['stream_memcap'] != "") { $natent['stream_memcap'] = $_POST['stream_memcap']; }else{ $natent['stream_memcap'] = "33554432"; } - if ($_POST['stream_max_sessions'] != "") { $natent['stream_max_sessions'] = $_POST['stream_max_sessions']; }else{ $natent['stream_max_sessions'] = "262144"; } if ($_POST['stream_prealloc_sessions'] != "") { $natent['stream_prealloc_sessions'] = $_POST['stream_prealloc_sessions']; }else{ $natent['stream_prealloc_sessions'] = "32768"; } if ($_POST['enable_midstream_sessions'] == "on") { $natent['enable_midstream_sessions'] = 'on'; }else{ $natent['enable_midstream_sessions'] = 'off'; } if ($_POST['enable_async_sessions'] == "on") { $natent['enable_async_sessions'] = 'on'; }else{ $natent['enable_async_sessions'] = 'off'; } @@ -318,7 +316,9 @@ elseif ($_POST['save']) { $a_nat[$id] = $natent; write_config(); $rebuild_rules = false; + conf_mount_rw(); suricata_generate_yaml($natent); + conf_mount_ro(); } header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -431,32 +431,39 @@ include_once("head.inc"); <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); - - /* Display error or save message */ - if ($input_errors) { - print_input_errors($input_errors); // TODO: add checks - } - if ($savemsg) { - print_info_box($savemsg); - } +/* Display error message */ +if ($input_errors) { + print_input_errors($input_errors); // TODO: add checks +} ?> <form action="suricata_flow_stream.php" method="post" name="iform" id="iform"> <input type="hidden" name="eng_id" id="eng_id" value="<?=$eng_id;?>"/> <input type="hidden" name="id" id="id" value="<?=$id;?>"/> +<?php +if ($savemsg) { + /* Display save message */ + print_info_box($savemsg); +} +?> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; @@ -489,6 +496,7 @@ include_once("head.inc"); <?php else: ?> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Host-Specific Defrag and Stream Settings"); ?></td> </tr> @@ -511,6 +519,7 @@ include_once("head.inc"); height="17" border="0" title="<?php echo gettext("Add a new policy configuration");?>"/></th> </tr> </thead> + <tbody> <?php foreach ($pconfig['host_os_policy']['item'] as $f => $v): ?> <tr> <td class="listlr" align="left"><?=gettext($v['name']);?></td> @@ -529,6 +538,7 @@ include_once("head.inc"); </td> </tr> <?php endforeach; ?> + </tbody> </table> </td> </tr> @@ -633,6 +643,7 @@ include_once("head.inc"); <td width="22%" valign="top" class="vncell"><?php echo gettext("TCP Connections"); ?></td> <td width="78%" class="vtable"> <table width="100%" cellspacing="4" cellpadding="0" border="0"> + <tbody> <tr> <td class="vexpl"><input name="flow_tcp_new_timeout" type="text" class="formfld unknown" id="flow_tcp_new_timeout" size="9" value="<?=htmlspecialchars($pconfig['flow_tcp_new_timeout']);?>"> @@ -669,6 +680,7 @@ include_once("head.inc"); <?php echo gettext("Emergency Closed TCP connection timeout in seconds. Default is ") . "<strong>" . gettext("20") . "</strong>."; ?> </td> </tr> + </tbody> </table> </td> </tr> @@ -676,6 +688,7 @@ include_once("head.inc"); <td width="22%" valign="top" class="vncell"><?php echo gettext("UDP Connections"); ?></td> <td width="78%" class="vtable"> <table width="100%" cellspacing="4" cellpadding="0" border="0"> + <tbody> <tr> <td class="vexpl"><input name="flow_udp_new_timeout" type="text" class="formfld unknown" id="flow_udp_new_timeout" size="9" value="<?=htmlspecialchars($pconfig['flow_udp_new_timeout']);?>"> @@ -700,6 +713,7 @@ include_once("head.inc"); <?php echo gettext("Emergency Established UDP connection timeout in seconds. Default is ") . "<strong>" . gettext("100") . "</strong>."; ?> </td> </tr> + </tbody> </table> </td> </tr> @@ -707,6 +721,7 @@ include_once("head.inc"); <td width="22%" valign="top" class="vncell"><?php echo gettext("ICMP Connections"); ?></td> <td width="78%" class="vtable"> <table width="100%" cellspacing="4" cellpadding="0" border="0"> + <tbody> <tr> <td class="vexpl"><input name="flow_icmp_new_timeout" type="text" class="formfld unknown" id="flow_icmp_new_timeout" size="9" value="<?=htmlspecialchars($pconfig['flow_icmp_new_timeout']);?>"> @@ -731,6 +746,7 @@ include_once("head.inc"); <?php echo gettext("Emergency Established ICMP connection timeout in seconds. Default is ") . "<strong>" . gettext("100") . "</strong>."; ?> </td> </tr> + </tbody> </table> </td> </tr> @@ -748,16 +764,6 @@ include_once("head.inc"); </td> </tr> <tr> - <td width="22%" valign="top" class="vncell"><?php echo gettext("Max Sessions"); ?></td> - <td width="78%" class="vtable"> - <input name="stream_max_sessions" type="text" class="formfld unknown" id="stream_max_sessions" size="9" - value="<?=htmlspecialchars($pconfig['stream_max_sessions']);?>"> - <?php echo gettext("Max concurrent stream engine sessions. Default is ") . - "<strong>" . gettext("262,144") . "</strong>" . gettext(" sessions."); ?><br/><br/> - <?php echo gettext("Sets the maximum number of concurrent sessions to be used by the stream engine."); ?> - </td> - </tr> - <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Preallocated Sessions"); ?></td> <td width="78%" class="vtable"> <input name="stream_prealloc_sessions" type="text" class="formfld unknown" id="stream_prealloc_sessions" size="9" @@ -835,12 +841,13 @@ include_once("head.inc"); <?php echo gettext("Please save your settings before you exit. Changes will rebuild the rules file. This "); ?> <?php echo gettext("may take several seconds. Suricata must also be restarted to activate any changes made on this screen."); ?></td> </tr> + </tbody> </table> <?php endif; ?> </div> -</td></tr></table> +</td></tr></tbody></table> </form> <?php include("fend.inc"); ?> </body> diff --git a/config/suricata/suricata_generate_yaml.php b/config/suricata/suricata_generate_yaml.php index bd3ce368..8e3e538c 100644 --- a/config/suricata/suricata_generate_yaml.php +++ b/config/suricata/suricata_generate_yaml.php @@ -68,11 +68,17 @@ foreach ($suricata_files as $file) { $home_net_list = suricata_build_list($suricatacfg, $suricatacfg['homelistname']); $home_net = implode(",", $home_net_list); $home_net = trim($home_net); -$external_net = '!$HOME_NET'; +$external_net = ""; if (!empty($suricatacfg['externallistname']) && $suricatacfg['externallistname'] != 'default') { - $external_net_list = suricata_build_list($suricatacfg, $suricatacfg['externallistname']); + $external_net_list = suricata_build_list($suricatacfg, $suricatacfg['externallistname'], false, true); $external_net = implode(",", $external_net_list); - $external_net = trim($external_net); + $external_net = "[" . trim($external_net) . "]"; +} +else { + $external_net = "["; + foreach ($home_net_list as $ip) + $external_net .= "!{$ip},"; + $external_net = trim($external_net, ', ') . "]"; } // Set the PASS LIST and write its contents to disk @@ -85,7 +91,7 @@ $suricata_servers = array ( "dns_servers" => "\$HOME_NET", "smtp_servers" => "\$HOME_NET", "http_servers" => "\$HOME_NET", "sql_servers" => "\$HOME_NET", "telnet_servers" => "\$HOME_NET", "dnp3_server" => "\$HOME_NET", "dnp3_client" => "\$HOME_NET", "modbus_server" => "\$HOME_NET", "modbus_client" => "\$HOME_NET", - "enip_server" => "\$HOME_NET", "enip_client" => "\$HOME_NET", + "enip_server" => "\$HOME_NET", "enip_client" => "\$HOME_NET", "ftp_servers" => "\$HOME_NET", "ssh_servers" => "\$HOME_NET", "aim_servers" => "64.12.24.0/23,64.12.28.0/23,64.12.161.0/24,64.12.163.0/24,64.12.200.0/24,205.188.3.0/24,205.188.5.0/24,205.188.7.0/24,205.188.9.0/24,205.188.153.0/24,205.188.179.0/24,205.188.248.0/24" ); $addr_vars = ""; @@ -102,6 +108,7 @@ if(is_array($config['system']['ssh']) && isset($config['system']['ssh']['port']) else $ssh_port = "22"; $suricata_ports = array( + "ftp_ports" => "21", "http_ports" => "80", "oracle_ports" => "1521", "ssh_ports" => $ssh_port, @@ -158,6 +165,11 @@ if ($suricatacfg['delayed_detect'] == 'on') else $delayed_detect = "no"; +if ($suricatacfg['intf_promisc_mode'] == 'on') + $intf_promisc_mode = "yes"; +else + $intf_promisc_mode = "no"; + // Add interface-specific blocking settings if ($suricatacfg['blockoffenders'] == 'on') $suri_blockoffenders = "yes"; @@ -184,6 +196,26 @@ if ($suricatacfg['alertsystemlog'] == 'on') else $alert_syslog = "no"; +if (!empty($suricatacfg['alertsystemlog_facility'])) + $alert_syslog_facility = $suricatacfg['alertsystemlog_facility']; +else + $alert_syslog_facility = "local5"; + +if (!empty($suricatacfg['alertsystemlog_priority'])) + $alert_syslog_priority = $suricatacfg['alertsystemlog_priority']; +else + $alert_syslog_priority = "Info"; + +if ($suricatacfg['enable_dns_log'] == 'on') + $dns_log_enabled = "yes"; +else + $dns_log_enabled = "no"; + +if ($suricatacfg['append_dns_log'] == 'on') + $dns_log_append = "yes"; +else + $dns_log_append = "no"; + if ($suricatacfg['enable_stats_log'] == 'on') $stats_log_enabled = "yes"; else @@ -209,6 +241,11 @@ if ($suricatacfg['append_http_log'] == 'on') else $http_log_append = "no"; +if ($suricatacfg['http_log_extended'] == 'on') + $http_log_extended = "yes"; +else + $http_log_extended = "no"; + if ($suricatacfg['enable_tls_log'] == 'on') $tls_log_enabled = "yes"; else @@ -277,6 +314,66 @@ if (isset($suricatacfg['barnyard_sensor_id'])) else $unified2_sensor_id = "0"; +// EVE JSON log output settings +if ($suricatacfg['enable_eve_log'] == 'on') + $enable_eve_log = "yes"; +else + $enable_eve_log = "no"; + +if ($suricatacfg['eve_output_type'] == 'syslog') + $eve_output_type = "syslog"; +else + $eve_output_type = "file"; + +if (!empty($suricatacfg['eve_systemlog_facility'])) + $eve_systemlog_facility = $suricatacfg['eve_systemlog_facility']; +else + $eve_systemlog_facility = "local1"; + +if (!empty($suricatacfg['eve_systemlog_priority'])) + $eve_systemlog_priority = $suricatacfg['eve_systemlog_priority']; +else + $eve_systemlog_priority = "info"; + +// EVE log output included information +$eve_out_types = ""; +if ($suricatacfg['eve_log_alerts'] == 'on') + $eve_out_types .= "\n - alert"; + +if ($suricatacfg['eve_log_http'] == 'on') { + $eve_out_types .= "\n - http:"; + if ($suricatacfg['http_log_extended'] == 'on') + $eve_out_types .= "\n extended: yes"; + else + $eve_out_types .= "\n extended: no"; +} + +if ($suricatacfg['eve_log_dns'] == 'on') + $eve_out_types .= "\n - dns"; + +if ($suricatacfg['eve_log_tls'] == 'on') { + $eve_out_types .= "\n - tls:"; + if ($suricatacfg['tls_log_extended'] == 'on') + $eve_out_types .= "\n extended: yes"; + else + $eve_out_types .= "\n extended: no"; +} + +if ($suricatacfg['eve_log_files'] == 'on') { + $eve_out_types .= "\n - files:"; + if ($suricatacfg['enable_tracked_files_magic'] == 'on') + $eve_out_types .= "\n force-magic: yes"; + else + $eve_out_types .= "\n force-magic: no"; + if ($suricatacfg['enable_tracked_files_md5'] == 'on') + $eve_out_types .= "\n force-md5: yes"; + else + $eve_out_types .= "\n force-md5: no"; +} + +if ($suricatacfg['eve_log_ssh'] == 'on') + $eve_out_types .= "\n - ssh"; + // Add interface-specific IP defrag settings if (!empty($suricatacfg['frag_memcap'])) $frag_memcap = $suricatacfg['frag_memcap']; @@ -406,11 +503,6 @@ if (!empty($suricatacfg['stream_memcap'])) else $stream_memcap = "33554432"; -if (!empty($suricatacfg['stream_max_sessions'])) - $stream_max_sessions = $suricatacfg['stream_max_sessions']; -else - $stream_max_sessions = "262144"; - if (!empty($suricatacfg['stream_prealloc_sessions'])) $stream_prealloc_sessions = $suricatacfg['stream_prealloc_sessions']; else @@ -492,7 +584,7 @@ if (!is_array($suricatacfg['libhtp_policy']['item'])) $suricatacfg['libhtp_policy']['item'] = array(); if (empty($suricatacfg['libhtp_policy']['item'])) { $http_hosts_default_policy = "default-config:\n personality: IDS\n request-body-limit: 4096\n response-body-limit: 4096\n"; - $http_hosts_default_policy .= " double-decode-path: no\n double-decode-query: no\n"; + $http_hosts_default_policy .= " double-decode-path: no\n double-decode-query: no\n uri-include-all: no\n"; } else { foreach ($suricatacfg['libhtp_policy']['item'] as $k => $v) { @@ -519,6 +611,7 @@ else { $engine .= " response-body-limit: {$v['response-body-limit']}\n"; $engine .= " double-decode-path: {$v['double-decode-path']}\n"; $engine .= " double-decode-query: {$v['double-decode-query']}\n"; + $engine .= " uri-include-all: {$v['uri-include-all']}\n"; $http_hosts_policy .= " {$engine}\n"; } else { @@ -531,6 +624,7 @@ else { $http_hosts_default_policy .= " response-body-limit: {$v['response-body-limit']}\n"; $http_hosts_default_policy .= " double-decode-path: {$v['double-decode-path']}\n"; $http_hosts_default_policy .= " double-decode-query: {$v['double-decode-query']}\n"; + $http_hosts_default_policy .= " uri-include-all: {$v['uri-include-all']}\n"; } } // Remove trailing newline @@ -544,6 +638,75 @@ if (!empty($suricatacfg['asn1_max_frames'])) else $asn1_max_frames = "256"; +// Configure App-Layer Parsers/Detection +if (!empty($suricatacfg['tls_parser'])) + $tls_parser = $suricatacfg['tls_parser']; +else + $tls_parser = "yes"; +if (!empty($suricatacfg['dcerpc_parser'])) + $dcerpc_parser = $suricatacfg['dcerpc_parser']; +else + $dcerpc_parser = "yes"; +if (!empty($suricatacfg['ftp_parser'])) + $ftp_parser = $suricatacfg['ftp_parser']; +else + $ftp_parser = "yes"; +if (!empty($suricatacfg['ssh_parser'])) + $ssh_parser = $suricatacfg['ssh_parser']; +else + $ssh_parser = "yes"; +if (!empty($suricatacfg['smtp_parser'])) + $smtp_parser = $suricatacfg['smtp_parser']; +else + $smtp_parser = "yes"; +if (!empty($suricatacfg['imap_parser'])) + $imap_parser = $suricatacfg['imap_parser']; +else + $imap_parser = "detection-only"; +if (!empty($suricatacfg['msn_parser'])) + $msn_parser = $suricatacfg['msn_parser']; +else + $msn_parser = "detection-only"; +if (!empty($suricatacfg['smb_parser'])) + $smb_parser = $suricatacfg['smb_parser']; +else + $smb_parser = "yes"; + +/* DNS Parser */ +if (!empty($suricatacfg['dns_parser_tcp'])) + $dns_parser_tcp = $suricatacfg['dns_parser_tcp']; +else + $dns_parser_tcp = "yes"; +if (!empty($suricatacfg['dns_parser_udp'])) + $dns_parser_udp = $suricatacfg['dns_parser_udp']; +else + $dns_parser_udp = "yes"; +if (!empty($suricatacfg['dns_global_memcap'])) + $dns_global_memcap = $suricatacfg['dns_global_memcap']; +else + $dns_global_memcap = "16777216"; +if (!empty($suricatacfg['dns_state_memcap'])) + $dns_state_memcap = $suricatacfg['dns_state_memcap']; +else + $dns_state_memcap = "524288"; +if (!empty($suricatacfg['dns_request_flood_limit'])) + $dns_request_flood_limit = $suricatacfg['dns_request_flood_limit']; +else + $dns_request_flood_limit = "500"; + +/* HTTP Parser */ +if (!empty($suricatacfg['http_parser'])) + $http_parser = $suricatacfg['http_parser']; +else + $http_parser = "yes"; +if (!empty($suricatacfg['http_parser_memcap'])) + $http_parser_memcap = $suricatacfg['http_parser_memcap']; +else + $http_parser_memcap = "67108864"; + +/* Configure the IP REP section */ +$iprep_path = rtrim(IPREP_PATH, '/'); + // Create the rules files and save in the interface directory suricata_prepare_rule_files($suricatacfg, $suricatacfgdir); @@ -563,4 +726,9 @@ if ($config['installedpackages']['suricata']['config'][0]['log_to_systemlog'] == else $suricata_use_syslog = "no"; +if (!empty($config['installedpackages']['suricata']['config'][0]['log_to_systemlog'])) + $suricata_use_syslog_facility = $config['installedpackages']['suricata']['config'][0]['log_to_systemlog']; +else + $suricata_use_syslog_facility = "local1"; + ?> diff --git a/config/suricata/suricata_global.php b/config/suricata/suricata_global.php index 9c932222..5f01a660 100644 --- a/config/suricata/suricata_global.php +++ b/config/suricata/suricata_global.php @@ -45,29 +45,45 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $g; $suricatadir = SURICATADIR; +$pconfig = array(); -$pconfig['enable_vrt_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules']; -$pconfig['oinkcode'] = $config['installedpackages']['suricata']['config'][0]['oinkcode']; -$pconfig['etprocode'] = $config['installedpackages']['suricata']['config'][0]['etprocode']; -$pconfig['enable_etopen_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; -$pconfig['enable_etpro_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; -$pconfig['rm_blocked'] = $config['installedpackages']['suricata']['config'][0]['rm_blocked']; -$pconfig['autoruleupdate'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdate']; -$pconfig['autoruleupdatetime'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime']; -$pconfig['live_swap_updates'] = $config['installedpackages']['suricata']['config'][0]['live_swap_updates']; -$pconfig['log_to_systemlog'] = $config['installedpackages']['suricata']['config'][0]['log_to_systemlog']; -$pconfig['forcekeepsettings'] = $config['installedpackages']['suricata']['config'][0]['forcekeepsettings']; -$pconfig['snortcommunityrules'] = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; +// If doing a postback, used typed values, else load from stored config +if (!empty($_POST)) { + $pconfig = $_POST; +} +else { + $pconfig['enable_vrt_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules']; + $pconfig['oinkcode'] = $config['installedpackages']['suricata']['config'][0]['oinkcode']; + $pconfig['etprocode'] = $config['installedpackages']['suricata']['config'][0]['etprocode']; + $pconfig['enable_etopen_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; + $pconfig['enable_etpro_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; + $pconfig['rm_blocked'] = $config['installedpackages']['suricata']['config'][0]['rm_blocked']; + $pconfig['autoruleupdate'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdate']; + $pconfig['autoruleupdatetime'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime']; + $pconfig['live_swap_updates'] = $config['installedpackages']['suricata']['config'][0]['live_swap_updates']; + $pconfig['log_to_systemlog'] = $config['installedpackages']['suricata']['config'][0]['log_to_systemlog']; + $pconfig['log_to_systemlog_facility'] = $config['installedpackages']['suricata']['config'][0]['log_to_systemlog_facility']; + $pconfig['forcekeepsettings'] = $config['installedpackages']['suricata']['config'][0]['forcekeepsettings']; + $pconfig['snortcommunityrules'] = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; + $pconfig['snort_rules_file'] = $config['installedpackages']['suricata']['config'][0]['snort_rules_file']; +} +// Do input validation on parameters if (empty($pconfig['autoruleupdatetime'])) $pconfig['autoruleupdatetime'] = '00:30'; +if (empty($pconfig['log_to_systemlog_facility'])) + $pconfig['log_to_systemlog_facility'] = "local1"; + if ($_POST['autoruleupdatetime']) { if (!preg_match('/^([01]?[0-9]|2[0-3]):?([0-5][0-9])$/', $_POST['autoruleupdatetime'])) $input_errors[] = "Invalid Rule Update Start Time! Please supply a value in 24-hour format as 'HH:MM'."; } -if ($_POST['suricatadownload'] == "on" && empty($_POST['oinkcode'])) +if ($_POST['enable_vrt_rules'] == "on" && empty($_POST['snort_rules_file'])) + $input_errors[] = "You must supply a snort rules tarball filename in the box provided in order to enable Snort VRT rules!"; + +if ($_POST['enable_vrt_rules'] == "on" && empty($_POST['oinkcode'])) $input_errors[] = "You must supply an Oinkmaster code in the box provided in order to enable Snort VRT rules!"; if ($_POST['enable_etpro_rules'] == "on" && empty($_POST['etprocode'])) @@ -117,6 +133,7 @@ if (!$input_errors) { } } + $config['installedpackages']['suricata']['config'][0]['snort_rules_file'] = $_POST['snort_rules_file']; $config['installedpackages']['suricata']['config'][0]['oinkcode'] = $_POST['oinkcode']; $config['installedpackages']['suricata']['config'][0]['etprocode'] = $_POST['etprocode']; $config['installedpackages']['suricata']['config'][0]['rm_blocked'] = $_POST['rm_blocked']; @@ -130,6 +147,7 @@ if (!$input_errors) { } $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime'] = str_pad($_POST['autoruleupdatetime'], 4, "0", STR_PAD_LEFT); $config['installedpackages']['suricata']['config'][0]['log_to_systemlog'] = $_POST['log_to_systemlog'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['config'][0]['log_to_systemlog_facility'] = $_POST['log_to_systemlog_facility']; $config['installedpackages']['suricata']['config'][0]['live_swap_updates'] = $_POST['live_swap_updates'] ? 'on' : 'off'; $config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = $_POST['forcekeepsettings'] ? 'on' : 'off'; @@ -138,7 +156,7 @@ if (!$input_errors) { /* create passlist and homenet file, then sync files */ sync_suricata_package_config(); - write_config(); + write_config("Suricata pkg: modified global settings."); /* forces page to reload new settings */ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -161,9 +179,6 @@ include_once("head.inc"); <?php include_once("fbegin.inc"); -if($pfsense_stable == 'yes') - echo '<p class="pgtitle">' . $pgtitle . '</p>'; - /* Display Alert message, under form tag or no refresh */ if ($input_errors) print_input_errors($input_errors); @@ -172,25 +187,29 @@ if ($input_errors) <form action="suricata_global.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php - $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); - $tab_array[] = array(gettext("Global Settings"), true, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array = array(); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), true, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); - display_top_tabs($tab_array, true); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> <td> <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> +<tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Please Choose The Type Of Rules You Wish To Download");?></td> </tr> @@ -198,6 +217,7 @@ if ($input_errors) <td width="22%" valign="top" class="vncell"><?php echo gettext("Install ") . "<strong>" . gettext("Emerging Threats") . "</strong>" . gettext(" rules");?></td> <td width="78%" class="vtable"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td valign="top" width="8%"><input name="enable_etopen_rules" type="checkbox" value="on" onclick="enable_et_rules();" <?php if ($config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']=="on") echo "checked"; ?>/></td> @@ -218,8 +238,10 @@ if ($input_errors) <td class="vexpl"><?php echo "<span class='red'><strong>" . gettext("Note:") . "</strong></span>" . " " . gettext("The ETPro rules contain all of the ETOpen rules, so the ETOpen rules are not required and are disabled when the ETPro rules are selected."); ?></td> </tr> + </tbody> </table> <table id="etpro_code_tbl" width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td colspan="2"> </td> </tr> @@ -232,6 +254,7 @@ if ($input_errors) value="<?=htmlspecialchars($pconfig['etprocode']);?>"/><br/> <?php echo gettext("Obtain an ETPro subscription code and paste it here."); ?></td> </tr> + </tbody> </table> </td> </tr> @@ -239,36 +262,45 @@ if ($input_errors) <td width="22%" valign="top" class="vncell"><?php echo gettext("Install ") . "<strong>" . gettext("Snort VRT") . "</strong>" . gettext(" rules");?></td> <td width="78%" class="vtable"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td><input name="enable_vrt_rules" type="checkbox" id="enable_vrt_rules" value="on" onclick="enable_snort_vrt();" <?php if($pconfig['enable_vrt_rules']=='on') echo 'checked'; ?>/></td> <td><span class="vexpl"><?php echo gettext("Snort VRT free Registered User or paid Subscriber rules"); ?></span></td> <tr> <td> </td> - <td><a href="https://www.snort.org/signup" target="_blank"><?php echo gettext("Sign Up for a free Registered User Rule Account"); ?> </a><br/> - <a href="http://www.snort.org/vrt/buy-a-subscription" target="_blank"> + <td><a href="https://www.snort.org/users/sign_up" target="_blank"><?php echo gettext("Sign Up for a free Registered User Rule Account"); ?> </a><br/> + <a href="https://www.snort.org/products" target="_blank"> <?php echo gettext("Sign Up for paid Sourcefire VRT Certified Subscriber Rules"); ?></a></td> </tr> + </tbody> </table> <table id="snort_oink_code_tbl" width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> - <td colspan="2"> </td> + <td colspan="2" valign="top"><b><span class="vexpl"><?php echo gettext("Snort VRT Configuration"); ?></span></b></td> </tr> <tr> - <td colspan="2" valign="top"><b><span class="vexpl"><?php echo gettext("Snort VRT Oinkmaster Configuration"); ?></span></b></td> + <td valign="top" align="right"><span class="vexpl"><strong><?php echo gettext("Rules Filename:"); ?></strong></span> </td> + <td><input name="snort_rules_file" type="text" class="formfld unknown" id="snort_rules_file" size="52" + value="<?=htmlspecialchars($pconfig['snort_rules_file']);?>"/><br/> + <?php echo gettext("Enter the rules tarball filename (filename only, do not include the URL.)"); ?> + <br/><span class="red"><strong><?php echo gettext("Example: ") . "</strong></span>" . gettext("snortrules-snapshot-2962.tar.gz");?><br/><br/></td> </tr> <tr> - <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> + <td valign="top" align="right"><span class="vexpl"><strong><?php echo gettext("Oinkmaster Code:"); ?></strong></span> </td> <td><input name="oinkcode" type="text" class="formfld unknown" id="oinkcode" size="52" value="<?=htmlspecialchars($pconfig['oinkcode']);?>"/><br/> <?php echo gettext("Obtain a snort.org Oinkmaster code and paste it here."); ?></td> </tr> + </tbody> </table> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Install ") . "<strong>" . gettext("Snort Community") . "</strong>" . gettext(" rules");?></td> <td width="78%" class="vtable"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td valign="top" width="8%"><input name="snortcommunityrules" type="checkbox" value="on" <?php if ($config['installedpackages']['suricata']['config'][0]['snortcommunityrules']=="on") echo " checked";?>/></td> @@ -278,6 +310,7 @@ if ($input_errors) gettext("If you are a Snort VRT Paid Subscriber, the community ruleset is already built into your download of the ") . gettext("Snort VRT rules, and there is no benefit in adding this rule set.");?><br/></td> </tr> + </tbody> </table></td> </tr> <tr> @@ -334,10 +367,29 @@ if ($input_errors) </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Log to System Log"); ?></td> - <td width="78%" class="vtable"><input name="log_to_systemlog" id="log_to_systemlog" type="checkbox" value="yes" + <td width="78%" class="vtable"><input name="log_to_systemlog" id="log_to_systemlog" type="checkbox" value="yes" onclick="toggle_log_to_systemlog();" <?php if ($config['installedpackages']['suricata']['config'][0]['log_to_systemlog']=="on") echo " checked"; ?>/> <?php echo gettext("Copy Suricata messages to the firewall system log."); ?></td> </tr> + <tbody id="log_to_systemlog_rows"> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Facility"); ?></td> + <td width="78%" class="vtable"> + <select name="log_to_systemlog_facility" id="log_to_systemlog_facility" class="formselect"> + <?php + $log_facility = array( "auth", "authpriv", "daemon", "kern", "security", "syslog", "user", "local0", + "local1", "local2", "local3", "local4", "local5", "local6", "local7" ); + foreach ($log_facility as $facility) { + $selected = ""; + if ($facility == $pconfig['log_to_systemlog_facility']) + $selected = " selected"; + echo "<option value='{$facility}'{$selected}>" . $facility . "</option>\n"; + } + ?></select> + <?php echo gettext("Select system log facility to use for reporting. Default is ") . "<strong>" . gettext("local1") . "</strong>."; ?> + </td> + </tr> + </tbody> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Keep Suricata Settings After Deinstall"); ?></td> <td width="78%" class="vtable"><input name="forcekeepsettings" id="forcekeepsettings" type="checkbox" value="yes" @@ -351,9 +403,10 @@ if ($input_errors) <td colspan="2" class="vexpl" align="center"><span class="red"><strong><?php echo gettext("Note:");?></strong> </span><?php echo gettext("Changing any settings on this page will affect all Suricata-configured interfaces.");?></td> </tr> +</tbody> </table> </div><br/> -</td></tr> +</td></tr></tbody> </table> </form> <?php include("fend.inc"); ?> @@ -396,11 +449,20 @@ function enable_change_rules_upd() { document.iform.autoruleupdatetime.disabled=""; } +function toggle_log_to_systemlog() { + var endis = !document.iform.log_to_systemlog.checked; + if (endis) + document.getElementById("log_to_systemlog_rows").style.display="none"; + else + document.getElementById("log_to_systemlog_rows").style.display=""; +} + // Initialize the form controls state based on saved settings enable_snort_vrt(); enable_et_rules(); enable_pro_rules(); enable_change_rules_upd(); +toggle_log_to_systemlog(); //--> </script> diff --git a/config/suricata/suricata_import_aliases.php b/config/suricata/suricata_import_aliases.php index ccaaf29d..e2fa4f40 100644 --- a/config/suricata/suricata_import_aliases.php +++ b/config/suricata/suricata_import_aliases.php @@ -79,8 +79,8 @@ <col width="35%" align="left" axis="string"> </colgroup> <thead> - <tr> - <th class="listhdrr"></th> + <tr class="sortableHeaderRowIdentifier"> + <th class="listhdrr sorttable_nosort"></th> <th class="listhdrr" axis="string"><?=gettext("Alias Name"); ?></th> <th class="listhdrr" axis="string"><?=gettext("Values"); ?></th> <th class="listhdrr" axis="string"><?=gettext("Description"); ?></th> diff --git a/config/suricata/suricata_interfaces.php b/config/suricata/suricata_interfaces.php index 205a872b..3d093d45 100644 --- a/config/suricata/suricata_interfaces.php +++ b/config/suricata/suricata_interfaces.php @@ -60,7 +60,6 @@ $id_gen = count($config['installedpackages']['suricata']['rule']); // Get list of configured firewall interfaces $ifaces = get_configured_interface_list(); - if ($_POST['del_x']) { /* delete selected interfaces */ if (is_array($_POST['rule'])) { @@ -79,7 +78,7 @@ if ($_POST['del_x']) { if (empty($a_nat)) unset($a_nat); - write_config(); + write_config("Suricata pkg: deleted one or more Suricata interfaces."); sleep(2); /* if there are no ifaces remaining do not create suricata.sh */ @@ -87,7 +86,7 @@ if ($_POST['del_x']) { suricata_create_rc(); else { conf_mount_rw(); - @unlink("{$rcdir}/suricata.sh"); + @unlink("{$rcdir}suricata.sh"); conf_mount_ro(); } @@ -170,19 +169,22 @@ include_once("head.inc"); ?> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr> <td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> @@ -191,7 +193,6 @@ include_once("head.inc"); <td> <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> - <colgroup> <col width="3%" align="center"> <col width="12%"> @@ -230,6 +231,7 @@ include_once("head.inc"); </th> </tr> </thead> + <tbody> <?php $nnats = $i = 0; // Turn on buffering to speed up rendering @@ -404,6 +406,7 @@ include_once("head.inc"); <td> </td> <td colspan="6"> <table class="tabcont" width="100%" border="0" cellpadding="1" cellspacing="0"> + <tbody> <tr> <td colspan="3" class="vexpl"><span class="red"><strong><?php echo gettext("Note:"); ?></strong></span> <br> <?php echo gettext("This is the ") . "<strong>" . gettext("Suricata Menu ") . @@ -456,14 +459,17 @@ include_once("head.inc"); delete an interface and settings. </td> </tr> + </tbody> </table> </td> <td> </td> </tr> + </tbody> </table> </div> </td> </tr> +</tbody> </table> </form> diff --git a/config/suricata/suricata_interfaces_edit.php b/config/suricata/suricata_interfaces_edit.php index dcf6fe3f..c4a1775a 100644 --- a/config/suricata/suricata_interfaces_edit.php +++ b/config/suricata/suricata_interfaces_edit.php @@ -59,8 +59,10 @@ if (isset($_POST['id']) && is_numericint($_POST['id'])) elseif (isset($_GET['id']) && is_numericint($_GET['id'])); $id = htmlspecialchars($_GET['id'], ENT_QUOTES | ENT_HTML401); -if (is_null($id)) - $id = 0; +if (is_null($id)) { + header("Location: /suricata/suricata_interfaces.php"); + exit; +} if (isset($_POST['action'])) $action = htmlspecialchars($_POST['action'], ENT_QUOTES | ENT_HTML401); @@ -71,7 +73,7 @@ else $pconfig = array(); if (empty($suricataglob['rule'][$id]['uuid'])) { - /* Adding new interface, so flag rules to build. */ + /* Adding new interface, so generate a new UUID and flag rules to build. */ $pconfig['uuid'] = suricata_generate_id(); $rebuild_rules = true; } @@ -87,14 +89,15 @@ $interfaces = get_configured_interface_with_descr(); // See if interface is already configured, and use its values if (isset($id) && $a_rule[$id]) { + /* old options */ $pconfig = $a_rule[$id]; if (!empty($pconfig['configpassthru'])) $pconfig['configpassthru'] = base64_decode($pconfig['configpassthru']); if (empty($pconfig['uuid'])) $pconfig['uuid'] = $suricata_uuid; } +// Must be a new interface, so try to pick next available physical interface to use elseif (isset($id) && !isset($a_rule[$id])) { - // Must be a new interface, so try to pick next available physical interface to use $ifaces = get_configured_interface_list(); $ifrules = array(); foreach($a_rule as $r) @@ -130,24 +133,44 @@ if (empty($pconfig['enable_http_log'])) $pconfig['enable_http_log'] = "on"; if (empty($pconfig['append_http_log'])) $pconfig['append_http_log'] = "on"; -if (empty($pconfig['enable_tls_log'])) - $pconfig['enable_tls_log'] = "off"; +if (empty($pconfig['http_log_extended'])) + $pconfig['http_log_extended'] = "on"; if (empty($pconfig['tls_log_extended'])) $pconfig['tls_log_extended'] = "on"; -if (empty($pconfig['enable_stats_log'])) - $pconfig['enable_stats_log'] = "off"; if (empty($pconfig['stats_upd_interval'])) $pconfig['stats_upd_interval'] = "10"; -if (empty($pconfig['append_stats_log'])) - $pconfig['append_stats_log'] = "off"; +if (empty($pconfig['append_dns_log'])) + $pconfig['append_dns_log'] = "on"; if (empty($pconfig['append_json_file_log'])) $pconfig['append_json_file_log'] = "on"; -if (empty($pconfig['enable_pcap_log'])) - $pconfig['enable_pcap_log'] = "off"; if (empty($pconfig['max_pcap_log_size'])) $pconfig['max_pcap_log_size'] = "32"; if (empty($pconfig['max_pcap_log_files'])) $pconfig['max_pcap_log_files'] = "1000"; +if (empty($pconfig['alertsystemlog_facility'])) + $pconfig['alertsystemlog_facility'] = "local1"; +if (empty($pconfig['alertsystemlog_priority'])) + $pconfig['alertsystemlog_priority'] = "notice"; +if (empty($pconfig['eve_output_type'])) + $pconfig['eve_output_type'] = "file"; +if (empty($pconfig['eve_systemlog_facility'])) + $pconfig['eve_systemlog_facility'] = "local1"; +if (empty($pconfig['eve_systemlog_priority'])) + $pconfig['eve_systemlog_priority'] = "notice"; +if (empty($pconfig['eve_log_alerts'])) + $pconfig['eve_log_alerts'] = "on"; +if (empty($pconfig['eve_log_http'])) + $pconfig['eve_log_http'] = "on"; +if (empty($pconfig['eve_log_dns'])) + $pconfig['eve_log_dns'] = "on"; +if (empty($pconfig['eve_log_tls'])) + $pconfig['eve_log_tls'] = "on"; +if (empty($pconfig['eve_log_files'])) + $pconfig['eve_log_files'] = "on"; +if (empty($pconfig['eve_log_ssh'])) + $pconfig['eve_log_ssh'] = "on"; +if (empty($pconfig['intf_promisc_mode'])) + $pconfig['intf_promisc_mode'] = "on"; // See if creating a new interface by duplicating an existing one if (strcasecmp($action, 'dup') == 0) { @@ -180,35 +203,37 @@ if (strcasecmp($action, 'dup') == 0) { } if ($_POST["save"] && !$input_errors) { - // If the interface is not enabled, stop any running Suricata - // instance on it, save the new state and exit. - if (!isset($_POST['enable'])) { - if (isset($id) && $a_rule[$id]) { - $a_rule[$id]['enable'] = 'off'; - $a_rule[$id]['interface'] = htmlspecialchars($_POST['interface']); - $a_rule[$id]['descr'] = htmlspecialchars($_POST['descr']); - suricata_stop($a_rule[$id], get_real_interface($a_rule[$id]['interface'])); - - // Save configuration changes - write_config(); - - // Update suricata.conf and suricata.sh files for this interface - sync_suricata_package_config(); - - header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); - header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); - header( 'Cache-Control: no-store, no-cache, must-revalidate' ); - header( 'Cache-Control: post-check=0, pre-check=0', false ); - header( 'Pragma: no-cache' ); - header("Location: /suricata/suricata_interfaces.php"); - exit; + if (!isset($_POST['interface'])) + $input_errors[] = gettext("Choosing an Interface is mandatory!"); + + /* See if assigned interface is already in use */ + if (isset($_POST['interface'])) { + foreach ($a_rule as $k => $v) { + if (($v['interface'] == $_POST['interface']) && ($id <> $k)) { + $input_errors[] = gettext("The '{$_POST['interface']}' interface is already assigned to another Suricata instance."); + break; + } } } - // Validate inputs - if (!isset($_POST['interface'])) - $input_errors[] = gettext("Choosing an Interface is mandatory!"); + // If Suricata is disabled on this interface, stop any running instance, + // save the change and exit. + if ($_POST['enable'] != 'on') { + $a_rule[$id]['enable'] = $_POST['enable'] ? 'on' : 'off'; + suricata_stop($a_rule[$id], get_real_interface($a_rule[$id]['interface'])); + write_config("Suricata pkg: disabled Suricata on " . convert_friendly_interface_to_friendly_descr($a_rule[$id]['interface'])); + $rebuild_rules = false; + sync_suricata_package_config(); + header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); + header( 'Cache-Control: no-store, no-cache, must-revalidate' ); + header( 'Cache-Control: post-check=0, pre-check=0', false ); + header( 'Pragma: no-cache' ); + header("Location: /suricata/suricata_interfaces.php"); + exit; + } + // Validate inputs if (isset($_POST['stats_upd_interval']) && !is_numericint($_POST['stats_upd_interval'])) $input_errors[] = gettext("The value for Stats Update Interval must contain only digits and evaluate to an integer."); @@ -224,16 +249,6 @@ if ($_POST["save"] && !$input_errors) { if (!empty($_POST['inspect_recursion_limit']) && !is_numeric($_POST['inspect_recursion_limit'])) $input_errors[] = gettext("The value for Inspect Recursion Limit can either be blank or contain only digits evaluating to an integer greater than or equal to 0."); - /* See if assigned interface is already in use */ - if (isset($_POST['interface'])) { - foreach ($a_rule as $k => $v) { - if (($v['interface'] == $_POST['interface']) && ($id <> $k)) { - $input_errors[] = gettext("The '{$_POST['interface']}' interface is already assigned to another Suricata instance."); - break; - } - } - } - // if no errors write to suricata.yaml if (!$input_errors) { $natent = $a_rule[$id]; @@ -250,6 +265,7 @@ if ($_POST["save"] && !$input_errors) { if ($_POST['enable_http_log'] == "on") { $natent['enable_http_log'] = 'on'; }else{ $natent['enable_http_log'] = 'off'; } if ($_POST['append_http_log'] == "on") { $natent['append_http_log'] = 'on'; }else{ $natent['append_http_log'] = 'off'; } if ($_POST['enable_tls_log'] == "on") { $natent['enable_tls_log'] = 'on'; }else{ $natent['enable_tls_log'] = 'off'; } + if ($_POST['http_log_extended'] == "on") { $natent['http_log_extended'] = 'on'; }else{ $natent['http_log_extended'] = 'off'; } if ($_POST['tls_log_extended'] == "on") { $natent['tls_log_extended'] = 'on'; }else{ $natent['tls_log_extended'] = 'off'; } if ($_POST['enable_pcap_log'] == "on") { $natent['enable_pcap_log'] = 'on'; }else{ $natent['enable_pcap_log'] = 'off'; } if ($_POST['enable_json_file_log'] == "on") { $natent['enable_json_file_log'] = 'on'; }else{ $natent['enable_json_file_log'] = 'off'; } @@ -257,6 +273,7 @@ if ($_POST["save"] && !$input_errors) { if ($_POST['enable_tracked_files_magic'] == "on") { $natent['enable_tracked_files_magic'] = 'on'; }else{ $natent['enable_tracked_files_magic'] = 'off'; } if ($_POST['enable_tracked_files_md5'] == "on") { $natent['enable_tracked_files_md5'] = 'on'; }else{ $natent['enable_tracked_files_md5'] = 'off'; } if ($_POST['enable_file_store'] == "on") { $natent['enable_file_store'] = 'on'; }else{ $natent['enable_file_store'] = 'off'; } + if ($_POST['enable_eve_log'] == "on") { $natent['enable_eve_log'] = 'on'; }else{ $natent['enable_eve_log'] = 'off'; } if ($_POST['max_pending_packets']) $natent['max_pending_packets'] = $_POST['max_pending_packets']; else unset($natent['max_pending_packets']); if ($_POST['inspect_recursion_limit'] >= '0') $natent['inspect_recursion_limit'] = $_POST['inspect_recursion_limit']; else unset($natent['inspect_recursion_limit']); if ($_POST['detect_eng_profile']) $natent['detect_eng_profile'] = $_POST['detect_eng_profile']; else unset($natent['detect_eng_profile']); @@ -270,8 +287,23 @@ if ($_POST["save"] && !$input_errors) { if ($_POST['externallistname']) $natent['externallistname'] = $_POST['externallistname']; else unset($natent['externallistname']); if ($_POST['suppresslistname']) $natent['suppresslistname'] = $_POST['suppresslistname']; else unset($natent['suppresslistname']); if ($_POST['alertsystemlog'] == "on") { $natent['alertsystemlog'] = 'on'; }else{ $natent['alertsystemlog'] = 'off'; } + if ($_POST['alertsystemlog_facility']) $natent['alertsystemlog_facility'] = $_POST['alertsystemlog_facility']; + if ($_POST['alertsystemlog_priority']) $natent['alertsystemlog_priority'] = $_POST['alertsystemlog_priority']; + if ($_POST['enable_dns_log'] == "on") { $natent['enable_dns_log'] = 'on'; }else{ $natent['enable_dns_log'] = 'off'; } + if ($_POST['append_dns_log'] == "on") { $natent['append_dns_log'] = 'on'; }else{ $natent['append_dns_log'] = 'off'; } + if ($_POST['enable_eve_log'] == "on") { $natent['enable_eve_log'] = 'on'; }else{ $natent['enable_eve_log'] = 'off'; } + if ($_POST['eve_output_type']) $natent['eve_output_type'] = $_POST['eve_output_type']; + if ($_POST['eve_systemlog_facility']) $natent['eve_systemlog_facility'] = $_POST['eve_systemlog_facility']; + if ($_POST['eve_systemlog_priority']) $natent['eve_systemlog_priority'] = $_POST['eve_systemlog_priority']; + if ($_POST['eve_log_alerts'] == "on") { $natent['eve_log_alerts'] = 'on'; }else{ $natent['eve_log_alerts'] = 'off'; } + if ($_POST['eve_log_http'] == "on") { $natent['eve_log_http'] = 'on'; }else{ $natent['eve_log_http'] = 'off'; } + if ($_POST['eve_log_dns'] == "on") { $natent['eve_log_dns'] = 'on'; }else{ $natent['eve_log_dns'] = 'off'; } + if ($_POST['eve_log_tls'] == "on") { $natent['eve_log_tls'] = 'on'; }else{ $natent['eve_log_tls'] = 'off'; } + if ($_POST['eve_log_files'] == "on") { $natent['eve_log_files'] = 'on'; }else{ $natent['eve_log_files'] = 'off'; } + if ($_POST['eve_log_ssh'] == "on") { $natent['eve_log_ssh'] = 'on'; }else{ $natent['eve_log_ssh'] = 'off'; } if ($_POST['delayed_detect'] == "on") { $natent['delayed_detect'] = 'on'; }else{ $natent['delayed_detect'] = 'off'; } - if ($_POST['configpassthru']) $natent['configpassthru'] = base64_encode($_POST['configpassthru']); else unset($natent['configpassthru']); + if ($_POST['intf_promisc_mode'] == "on") { $natent['intf_promisc_mode'] = 'on'; }else{ $natent['intf_promisc_mode'] = 'off'; } + if ($_POST['configpassthru']) $natent['configpassthru'] = base64_encode(str_replace("\r\n", "\n", $_POST['configpassthru'])); else unset($natent['configpassthru']); $if_real = get_real_interface($natent['interface']); if (isset($id) && $a_rule[$id] && $action == '') { @@ -292,9 +324,12 @@ if ($_POST["save"] && !$input_errors) { $a_rule[$id] = $natent; } elseif (strcasecmp($action, 'dup') == 0) { - // Duplicating a new interface, so set flag to build new rules + // Duplicating an existing interface to a new interface, so set flag to build new rules $rebuild_rules = true; + // Duplicating an interface, so need to generate a new UUID for the cloned interface + $natent['uuid'] = suricata_generate_id(); + // Add the new duplicated interface configuration to the [rule] array in config $a_rule[] = $natent; } @@ -330,7 +365,6 @@ if ($_POST["save"] && !$input_errors) { $natent['flow_icmp_emerg_established_timeout'] = '100'; $natent['stream_memcap'] = '33554432'; - $natent['stream_max_sessions'] = '262144'; $natent['stream_prealloc_sessions'] = '32768'; $natent['reassembly_memcap'] = '67108864'; $natent['reassembly_depth'] = '1048576'; @@ -339,8 +373,24 @@ if ($_POST["save"] && !$input_errors) { $natent['enable_midstream_sessions'] = 'off'; $natent['enable_async_sessions'] = 'off'; $natent['delayed_detect'] = 'off'; + $natent['intf_promisc_mode'] = 'on'; $natent['asn1_max_frames'] = '256'; + $natent['dns_global_memcap'] = "16777216"; + $natent['dns_state_memcap'] = "524288"; + $natent['dns_request_flood_limit'] = "500"; + $natent['http_parser_memcap'] = "67108864"; + $natent['dns_parser_udp'] = "yes"; + $natent['dns_parser_tcp'] = "yes"; + $natent['http_parser'] = "yes"; + $natent['tls_parser'] = "yes"; + $natent['smtp_parser'] = "yes"; + $natent['imap_parser'] = "detection-only"; + $natent['ssh_parser'] = "yes"; + $natent['ftp_parser'] = "yes"; + $natent['dcerpc_parser'] = "yes"; + $natent['smb_parser'] = "yes"; + $natent['msn_parser'] = "detection-only"; $default = array( "name" => "default", "bind_to" => "all", "policy" => "bsd" ); if (!is_array($natent['host_os_policy']['item'])) @@ -349,13 +399,14 @@ if ($_POST["save"] && !$input_errors) { $default = array( "name" => "default", "bind_to" => "all", "personality" => "IDS", "request-body-limit" => 4096, "response-body-limit" => 4096, - "double-decode-path" => "no", "double-decode-query" => "no" ); + "double-decode-path" => "no", "double-decode-query" => "no", + "uri-include-all" => "no" ); if (!is_array($natent['libhtp_policy']['item'])) $natent['libhtp_policy']['item'] = array(); $natent['libhtp_policy']['item'][] = $default; // Enable the basic default rules for the interface - $natent['rulesets'] = "decoder-events.rules||files.rules||http-events.rules||smtp-events.rules||stream-events.rules||tls-events.rules"; + $natent['rulesets'] = "decoder-events.rules||dns-events.rules||files.rules||http-events.rules||smtp-events.rules||stream-events.rules||tls-events.rules"; // Adding a new interface, so set flag to build new rules $rebuild_rules = true; @@ -369,7 +420,7 @@ if ($_POST["save"] && !$input_errors) { suricata_stop($natent, $if_real); // Save configuration changes - write_config(); + write_config("Suricata pkg: modified interface configuration for " . convert_friendly_interface_to_friendly_descr($natent['interface'])); // Update suricata.conf and suricata.sh files for this interface sync_suricata_package_config(); @@ -407,18 +458,21 @@ if ($savemsg) { <input name="action" type="hidden" value="<?=$action;?>"/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -436,6 +490,7 @@ if ($savemsg) { </td></tr> <tr><td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" class="listtopic"><?php echo gettext("General Settings"); ?></td> </tr> @@ -471,9 +526,57 @@ if ($savemsg) { </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Send Alerts to System Log"); ?></td> - <td width="78%" class="vtable"><input name="alertsystemlog" type="checkbox" value="on" <?php if ($pconfig['alertsystemlog'] == "on") echo "checked"; ?>/> - <?php echo gettext("Suricata will send Alerts to the firewall's system log."); ?></td> + <td width="78%" class="vtable"><input name="alertsystemlog" type="checkbox" value="on" onclick="toggle_system_log();" <?php if ($pconfig['alertsystemlog'] == "on") echo "checked"; ?>/> + <?php echo gettext("Suricata will send Alerts from this interface to the firewall's system log."); ?></td> + </tr> + <tbody id="alertsystemlog_rows"> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Facility"); ?></td> + <td width="78%" class="vtable"> + <select name="alertsystemlog_facility" id="alertsystemlog_facility" class="formselect"> + <?php + $log_facility = array( "auth", "authpriv", "daemon", "kern", "security", "syslog", "user", "local0", + "local1", "local2", "local3", "local4", "local5", "local6", "local7" ); + foreach ($log_facility as $facility) { + $selected = ""; + if ($facility == $pconfig['alertsystemlog_facility']) + $selected = " selected"; + echo "<option value='{$facility}'{$selected}>" . $facility . "</option>\n"; + } + ?></select> + <?php echo gettext("Select system log Facility to use for reporting. Default is ") . "<strong>" . gettext("local1") . "</strong>."; ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Priority"); ?></td> + <td width="78%" class="vtable"> + <select name="alertsystemlog_priority" id="alertsystemlog_priority" class="formselect"> + <?php + $log_priority = array( "emerg", "crit", "alert", "err", "warning", "notice", "info" ); + foreach ($log_priority as $priority) { + $selected = ""; + if ($priority == $pconfig['alertsystemlog_priority']) + $selected = " selected"; + echo "<option value='{$priority}'{$selected}>" . $priority . "</option>\n"; + } + ?></select> + <?php echo gettext("Select system log Priority (Level) to use for reporting. Default is ") . "<strong>" . gettext("notice") . "</strong>."; ?> + </td> + </tr> + </tbody> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable DNS Log"); ?></td> + <td width="78%" class="vtable"><input name="enable_dns_log" type="checkbox" value="on" <?php if ($pconfig['enable_dns_log'] == "on") echo "checked"; ?> + onClick="toggle_dns_log();" id="enable_dns_log"/> + <?php echo gettext("Suricata will log DNS requests and replies for the interface. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?> + </td> + </tr> + <tr id="dns_log_append_row"> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Append DNS Log"); ?></td> + <td width="78%" class="vtable"><input name="append_dns_log" type="checkbox" value="on" <?php if ($pconfig['append_dns_log'] == "on") echo "checked"; ?>/> + <?php echo gettext("Suricata will append-to instead of clearing DNS log file when restarting. Default is ") . "<strong>" . gettext("Checked") . "</strong>."; ?></td> </tr> + <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Stats Log"); ?></td> <td width="78%" class="vtable"><input name="enable_stats_log" type="checkbox" value="on" <?php if ($pconfig['enable_stats_log'] == "on") echo "checked"; ?> @@ -505,6 +608,11 @@ if ($savemsg) { <td width="78%" class="vtable"><input name="append_http_log" type="checkbox" value="on" <?php if ($pconfig['append_http_log'] == "on") echo "checked"; ?>/> <?php echo gettext("Suricata will append-to instead of clearing HTTP log file when restarting. Default is ") . "<strong>" . gettext("Checked") . "</strong>."; ?></td> </tr> + <tr id="http_log_extended_row"> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Extended HTTP Info"); ?></td> + <td width="78%" class="vtable"><input name="http_log_extended" type="checkbox" value="on" <?php if ($pconfig['http_log_extended'] == "on") echo "checked"; ?>/> + <?php echo gettext("Suricata will log extended HTTP information. Default is ") . "<strong>" . gettext("Checked") . "</strong>."; ?></td> + </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable TLS Log"); ?></td> <td width="78%" class="vtable"><input name="enable_tls_log" type="checkbox" value="on" <?php if ($pconfig['enable_tls_log'] == "on") echo "checked"; ?> @@ -572,6 +680,99 @@ if ($savemsg) { <?php echo gettext("Enter maximum number of packet log files to maintain. Default is ") . "<strong>" . gettext("1000") . "</strong>."; ?><br/><br/><?php echo gettext("When the number of packet log files reaches the set limit, the oldest file will be overwritten.") ?></td> </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("EVE JSON Log"); ?></td> + <td width="78%" class="vtable"><input name="enable_eve_log" id="enable_eve_log" type="checkbox" value="on" <?php if ($pconfig['enable_eve_log'] == "on") echo "checked"; ?> + onClick="toggle_eve_log()"/> + <?php echo gettext("Suricata will output selected info in JSON format to a single file or to syslog. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?> + <div id="file_eve_warning" style="display: none;"><br/><span class="red"><strong><?php echo gettext("Warning: ") . "</strong></span>" . + gettext("This can consume a significant amount of disk space when enabled!"); ?></div> + </td> + </tr> + <tbody id="eve_log_option_rows"> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("EVE Output Type"); ?></td> + <td width="78%" class="vtable"> + <select name="eve_output_type" class="formselect" id="eve_output_type" onChange="eveOutSelect();" > + <?php + foreach (array("file", "syslog") as $btype) { + if ($btype == $pconfig['eve_output_type']) + echo "<option value='{$btype}' selected>"; + else + echo "<option value='{$btype}'>"; + echo htmlspecialchars($btype) . '</option>'; + } + ?> + </select> + <?php echo gettext("Select EVE log output destination."); ?><br/> + <span class="red"><?php echo gettext("Hint:") . "</span> " . gettext("Choosing FILE is suggested, and it is the default value."); ?><br/> + </td> + </tr> + <tr id="eve_systemlog_facility_row"> + <td width="22%" valign="top" class="vncell"><?php echo gettext("EVE Syslog Facility"); ?></td> + <td width="78%" class="vtable"> + <select name="eve_systemlog_facility" id="eve_systemlog_facility" class="formselect"> + <?php + $log_facility = array( "auth", "authpriv", "daemon", "kern", "security", "syslog", "user", "local0", + "local1", "local2", "local3", "local4", "local5", "local6", "local7" ); + foreach ($log_facility as $facility) { + $selected = ""; + if ($facility == $pconfig['eve_systemlog_facility']) + $selected = " selected"; + echo "<option value='{$facility}'{$selected}>" . $facility . "</option>\n"; + } + ?></select> + <?php echo gettext("Select system log Facility to use for reporting by EVE. Default is ") . "<strong>" . gettext("local1") . "</strong>."; ?> + </td> + </tr> + <tr id="eve_systemlog_priority_row"> + <td width="22%" valign="top" class="vncell"><?php echo gettext("EVE Syslog Priority"); ?></td> + <td width="78%" class="vtable"> + <select name="eve_systemlog_priority" id="eve_systemlog_priority" class="formselect"> + <?php + $log_priority = array( "emerg", "crit", "alert", "err", "warning", "notice", "info" ); + foreach ($log_priority as $priority) { + $selected = ""; + if ($priority == $pconfig['eve_systemlog_priority']) + $selected = " selected"; + echo "<option value='{$priority}'{$selected}>" . $priority . "</option>\n"; + } + ?></select> + <?php echo gettext("Select system log Priority (Level) to use for reporting by EVE. Default is ") . "<strong>" . gettext("notice") . "</strong>."; ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("EVE Logged Info"); ?></td> + <td width="78%" class="vtable"><?php echo gettext("Choose the information to log via EVE JSON output. Default is ") . "<strong>" . gettext("All Checked") . "</strong>."; ?><br/> + <table width="100%" cellpadding="0" cellspacing="0" border="0"> + <tbody> + <tr> + <td class="vexpl"><input name="eve_log_alerts" id="eve_log_alerts" type="checkbox" value="on" + <?php if ($pconfig['eve_log_alerts'] == "on") echo "checked"; ?>/>Alerts + </td> + <td class="vexpl"><input name="eve_log_http" id="eve_log_http" type="checkbox" value="on" + <?php if ($pconfig['eve_log_http'] == "on") echo "checked"; ?>/>HTTP Traffic + </td> + <td class="vexpl"><input name="eve_log_dns" id="eve_log_dns" type="checkbox" value="on" + <?php if ($pconfig['eve_log_dns'] == "on") echo "checked"; ?>/>DNS Requests/Replies + </td> + </tr> + <tr> + <td class="vexpl"><input name="eve_log_tls" id="eve_log_tls" type="checkbox" value="on" onClick="toggle_eve_tls();" + <?php if ($pconfig['eve_log_tls'] == "on") echo "checked"; ?>/>TLS Handshakes + </td> + <td class="vexpl"><input name="eve_log_files" id="eve_log_files" type="checkbox" value="on" + <?php if ($pconfig['eve_log_files'] == "on") echo "checked"; ?>/>Tracked Files + </td> + <td class="vexpl"><input name="eve_log_ssh" id="eve_log_ssh" type="checkbox" value="on" + <?php if ($pconfig['eve_log_ssh'] == "on") echo "checked"; ?>/>SSH Handshakes + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> <tr> <td colspan="2" class="listtopic"><?php echo gettext("Alert Settings"); ?></td> </tr> @@ -604,7 +805,7 @@ if ($savemsg) { ?> </select> <?php echo gettext("Select which IP extracted from the packet you wish to block."); ?><br/> - <span class="red"><?php echo gettext("Hint:") . "</span> " . gettext("Choosing BOTH is suggested, and it is the default value."); ?></span><br/></td> + <span class="red"><?php echo gettext("Hint:") . "</span> " . gettext("Choosing BOTH is suggested, and it is the default value."); ?><br/> </td> </tr> <tr> @@ -643,8 +844,8 @@ if ($savemsg) { <td width="78%" class="vtable"> <select name="mpm_algo" class="formselect" id="mpm_algo"> <?php - $interfaces2 = array('ac' => 'AC', 'ac-gfbs' => 'AC-GFBS', 'ac-bs' => 'AC-BS', - 'b2g' => 'B2G', 'b3g' => 'B3G', 'wumanber' => 'WUMANBER'); + $interfaces2 = array('ac' => 'AC', 'ac-gfbs' => 'AC-GFBS', 'b2g' => 'B2G', + 'b2gc' => 'B2GC', 'b2gm' => 'B2GM', 'b3g' => 'B3G', 'wumanber' => 'WUMANBER'); foreach ($interfaces2 as $iface2 => $ifacename2): ?> <option value="<?=$iface2;?>" <?php if ($iface2 == $pconfig['mpm_algo']) echo "selected"; ?>> @@ -691,6 +892,14 @@ if ($savemsg) { "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> </tr> <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Promiscuous Mode"); ?></td> + <td width="78%" class="vtable"> + <input name="intf_promisc_mode" id="intf_promisc_mode" type="checkbox" value="on" + <?php if ($pconfig['intf_promisc_mode'] == "on") echo " checked"; ?>/> + <?php echo gettext("Suricata will place the monitored interface in promiscuous mode when checked. Default is ") . + "<strong>" . gettext("Checked") . "</strong>."; ?></td> + </tr> + <tr> <td colspan="2" class="listtopic"><?php echo gettext("Networks " . "Suricata Should Inspect and Protect"); ?></td> </tr> <tr> @@ -699,9 +908,9 @@ if ($savemsg) { <select name="homelistname" class="formselect" id="homelistname"> <?php echo "<option value='default' >default</option>"; - /* find whitelist names and filter by type */ - if (is_array($suricataglob['whitelist']['item'])) { - foreach ($suricataglob['whitelist']['item'] as $value) { + /* find Pass List names and filter by type */ + if (is_array($suricataglob['passlist']['item'])) { + foreach ($suricataglob['passlist']['item'] as $value) { $ilistname = $value['name']; if ($ilistname == $pconfig['homelistname']) echo "<option value='$ilistname' selected>"; @@ -716,12 +925,13 @@ if ($savemsg) { onclick="viewList('<?=$id;?>','homelistname','homenet')" id="btnHomeNet" title="<?php echo gettext("Click to view currently selected Home Net contents"); ?>"/> <br/> - <span class="vexpl"><?php echo gettext("Choose the Home Net you want this interface to use."); ?></span> + <span class="vexpl"><?php echo gettext("Choose the Home Net you want this interface to use. Most users should choose 'default'."); ?></span> <br/><br/> <span class="red"><?php echo gettext("Note:"); ?></span> <?php echo gettext("Default Home " . "Net adds only local networks, WAN IPs, Gateways, VPNs and VIPs."); ?><br/> <span class="red"><?php echo gettext("Hint:"); ?></span> <?php echo gettext("Create an Alias to hold a list of " . - "friendly IPs that the firewall cannot see or to customize the default Home Net."); ?><br/> + "friendly IPs that the firewall cannot see or to customize the default Home Net. Assign the Alias to a Pass List, and " . + "then assign that Pass List to Home Net."); ?><br/> </td> </tr> <tr> @@ -730,9 +940,9 @@ if ($savemsg) { <select name="externallistname" class="formselect" id="externallistname"> <?php echo "<option value='default' >default</option>"; - /* find whitelist names and filter by type */ - if (is_array($suricataglob['whitelist']['item'])) { - foreach ($suricataglob['whitelist']['item'] as $value) { + /* find Pass List names and filter by type */ + if (is_array($suricataglob['passlist']['item'])) { + foreach ($suricataglob['passlist']['item'] as $value) { $ilistname = $value['name']; if ($ilistname == $pconfig['externallistname']) echo "<option value='$ilistname' selected>"; @@ -742,7 +952,11 @@ if ($savemsg) { } } ?> - </select> + </select> + <input type="button" class="formbtns" value="View List" + onclick="viewList('<?=$id;?>','externallistname','externalnet')" id="btnExternalNet" + title="<?php echo gettext("Click to view currently selected External Net contents"); ?>"/> + <br/> <?php echo gettext("Choose the External Net you want this interface " . "to use."); ?> <br/><br/> <span class="red"><?php echo gettext("Note:"); ?></span> <?php echo gettext("Default " . @@ -772,7 +986,7 @@ if ($savemsg) { <input type="button" class="formbtns" value="View List" onclick="viewList('<?=$id;?>','passlistname','passlist')" id="btnPasslist" title="<?php echo gettext("Click to view currently selected Pass List contents"); ?>"/> <br/> - <?php echo gettext("Choose the Pass List you want this interface to use."); ?> <br/><br/> + <?php echo gettext("Choose the Pass List you want this interface to use. Addresses in a Pass List are never blocked."); ?> <br/><br/> <span class="red"><?php echo gettext("Note:"); ?></span> <?php echo gettext("This option will only be used when block offenders is on."); ?><br/> <span class="red"><?php echo gettext("Hint:"); ?></span> <?php echo gettext("Default " . "Pass List adds local networks, WAN IPs, Gateways, VPNs and VIPs. Create an Alias to customize."); ?> @@ -828,14 +1042,32 @@ if ($savemsg) { gettext("Please save your settings before you attempt to start Suricata."); ?> </td> </tr> +</tbody> </table> </div> </td></tr> +</tbody> </table> </form> <script language="JavaScript"> +function toggle_system_log() { + var endis = !(document.iform.alertsystemlog.checked); + if (endis) + document.getElementById("alertsystemlog_rows").style.display="none"; + else + document.getElementById("alertsystemlog_rows").style.display=""; +} + +function toggle_dns_log() { + var endis = !(document.iform.enable_dns_log.checked); + if (endis) + document.getElementById("dns_log_append_row").style.display="none"; + else + document.getElementById("dns_log_append_row").style.display="table-row"; +} + function enable_blockoffenders() { var endis = !(document.iform.blockoffenders.checked); document.iform.blockoffenderskill.disabled=endis; @@ -860,18 +1092,27 @@ function toggle_stats_log() { function toggle_http_log() { var endis = !(document.iform.enable_http_log.checked); - if (endis) + if (endis) { document.getElementById("http_log_append_row").style.display="none"; - else + document.getElementById("http_log_extended_row").style.display="none"; + } + else { document.getElementById("http_log_append_row").style.display="table-row"; + document.getElementById("http_log_extended_row").style.display="table-row"; + } } function toggle_tls_log() { var endis = !(document.iform.enable_tls_log.checked); if (endis) document.getElementById("tls_log_extended_row").style.display="none"; - else + else { document.getElementById("tls_log_extended_row").style.display="table-row"; + if (document.iform.enable_eve_log.checked && document.iform.eve_log_tls.checked) { + alert('Only one TLS log instance permitted...removing TLS log from EVE JSON output in order to enable standalone TLS logging.'); + document.iform.eve_log_tls.checked = false; + } + } } function toggle_json_file_log() { @@ -912,6 +1153,25 @@ function toggle_pcap_log() { } } +function toggle_eve_log() { + var endis = !(document.iform.enable_eve_log.checked); + if (endis) { + document.getElementById("eve_log_option_rows").style.display = "none"; + } + else { + document.getElementById("eve_log_option_rows").style.display = ""; + if (document.iform.enable_tls_log.checked) + document.iform.eve_log_tls.checked = false; + } +} + +function toggle_eve_tls() { + if (document.iform.enable_tls_log.checked) { + alert('Only one TLS log instance permitted...removing standalone TLS output in order to add EVE JSON TLS output.'); + document.iform.enable_tls_log.checked = false; + } +} + function enable_change(enable_change) { endis = !(document.iform.enable.checked || enable_change); // make sure a default answer is called if this is invoked. @@ -921,6 +1181,7 @@ function enable_change(enable_change) { document.iform.append_stats_log.disabled = endis; document.iform.enable_http_log.disabled = endis; document.iform.append_http_log.disabled = endis; + document.iform.http_log_extended.disabled = endis; document.iform.enable_tls_log.disabled = endis; document.iform.tls_log_extended.disabled = endis; document.iform.enable_json_file_log.disabled = endis; @@ -931,6 +1192,14 @@ function enable_change(enable_change) { document.iform.enable_pcap_log.disabled = endis; document.iform.max_pcap_log_size.disabled = endis; document.iform.max_pcap_log_files.disabled = endis; + document.iform.eve_output_type.disabled = endis; + document.iform.enable_eve_log.disabled = endis; + document.iform.eve_log_alerts.disabled = endis; + document.iform.eve_log_http.disabled = endis; + document.iform.eve_log_dns.disabled = endis; + document.iform.eve_log_tls.disabled = endis; + document.iform.eve_log_files.disabled = endis; + document.iform.eve_log_ssh.disabled = endis; document.iform.max_pending_packets.disabled = endis; document.iform.detect_eng_profile.disabled = endis; document.iform.mpm_algo.disabled = endis; @@ -948,8 +1217,9 @@ function enable_change(enable_change) { document.iform.btnHomeNet.disabled=endis; document.iform.btnPasslist.disabled=endis; document.iform.btnSuppressList.disabled=endis; -} document.iform.delayed_detect.disabled=endis; - + document.iform.delayed_detect.disabled=endis; + document.iform.intf_promisc_mode.disabled=endis; +} function wopen(url, name, w, h) { // Fudge factors for window decoration space. @@ -970,6 +1240,18 @@ function getSelectedValue(elemID) { return ctrl.options[ctrl.selectedIndex].value; } +function eveOutSelect() { + var ctrl = document.getElementById("eve_output_type"); + if (ctrl.options[ctrl.selectedIndex].value == 'syslog') { + document.getElementById("eve_systemlog_facility_row").style.display = "table-row"; + document.getElementById("eve_systemlog_priority_row").style.display = "table-row"; + } + else { + document.getElementById("eve_systemlog_facility_row").style.display = "none"; + document.getElementById("eve_systemlog_priority_row").style.display = "none"; + } +} + function viewList(id, elemID, elemType) { if (typeof elemType == "undefined") { elemType = "passlist"; @@ -982,12 +1264,16 @@ function viewList(id, elemID, elemType) { enable_change(false); //enable_blockoffenders(); +toggle_system_log(); +toggle_dns_log(); toggle_stats_log(); toggle_http_log(); toggle_tls_log(); toggle_json_file_log(); toggle_file_store(); toggle_pcap_log(); +toggle_eve_log(); +eveOutSelect(); </script> <?php include("fend.inc"); ?> diff --git a/config/suricata/suricata_libhtp_policy_engine.php b/config/suricata/suricata_libhtp_policy_engine.php index 7e6ffd6d..248f4c74 100644 --- a/config/suricata/suricata_libhtp_policy_engine.php +++ b/config/suricata/suricata_libhtp_policy_engine.php @@ -60,12 +60,14 @@ resp_body_limit --> Response Body Limit size enable_double_decode_path --> double-decode path part of URI enable_double_decode_query --> double-decode query string part of URI + enable_uri_include_all --> inspect all of URI save_libhtp_policy --> Submit button for save operation and exit cancel_libhtp_policy --> Submit button to cancel operation and exit **************************************************************************************/ ?> <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="middle" class="listtopic"><?php echo gettext("Suricata Target-Based HTTP Server Policy Configuration"); ?></td> </tr> @@ -73,7 +75,7 @@ <td valign="top" class="vncell"><?php echo gettext("Engine Name"); ?></td> <td class="vtable"> <input name="policy_name" type="text" class="formfld unknown" id="policy_name" size="25" maxlength="25" - value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == "default") echo "readonly";?>> + value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == " default") echo " readonly";?>> <?php if (htmlspecialchars($pengcfg['name']) <> "default") echo gettext("Name or description for this engine. (Max 25 characters)"); else @@ -87,6 +89,7 @@ <td class="vtable"> <?php if ($pengcfg['name'] <> "default") : ?> <table width="95%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td class="vexpl"><input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" value="<?=htmlspecialchars($pengcfg['bind_to']);?>" title="<?=trim(filter_expand_alias($pengcfg['bind_to']));?>" autocomplete="off"> @@ -97,6 +100,7 @@ <tr> <td class="vexpl" colspan="2"><?php echo gettext("This policy will apply for packets with destination addresses contained within this IP List.");?></td> </tr> + </tbody> </table> <br/><span class="red"><strong><?php echo gettext("Note: ") . "</strong></span>" . gettext("Supplied value must be a pre-configured Alias or the keyword 'all'.");?> <?php else : ?> @@ -112,7 +116,7 @@ <td width="78%" class="vtable"> <select name="personality" class="formselect" id="personality"> <?php - $profile = array( 'Apache', 'Apache_2_2', 'Generic', 'IDS', 'IIS_4_0', 'IIS_5_0', 'IIS_5_1', 'IIS_6_0', 'IIS_7_0', 'IIS_7_5', 'Minimal' ); + $profile = array( 'Apache_2', 'Generic', 'IDS', 'IIS_4_0', 'IIS_5_0', 'IIS_5_1', 'IIS_6_0', 'IIS_7_0', 'IIS_7_5', 'Minimal' ); foreach ($profile as $val): ?> <option value="<?=$val;?>" <?php if ($val == $pengcfg['personality']) echo "selected"; ?>> @@ -120,7 +124,7 @@ <?php endforeach; ?> </select> <?php echo gettext("Choose the web server personality appropriate for the protected hosts. The default is ") . "<strong>" . gettext("IDS") . "</strong>"; ?>.<br/><br/> - <?php echo gettext("Available web server personality targets are: Apache, Apache 2.2, Generic, IDS (default), IIS_4_0, IIS_5_0, IIS_5_1, IIS_6_0, IIS_7_0, IIS_7_5 and Minimal."); ?><br/> + <?php echo gettext("Available web server personality targets are: Apache 2, Generic, IDS (default), IIS_4_0, IIS_5_0, IIS_5_1, IIS_6_0, IIS_7_0, IIS_7_5 and Minimal."); ?><br/> </td> </tr> <tr> @@ -155,15 +159,22 @@ </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Double-Decode Path"); ?></td> - <td width="78%" class="vtable"><input name="enable_double_decode_path" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-path'] == "yes") echo "checked"; ?>> + <td width="78%" class="vtable"><input name="enable_double_decode_path" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-path'] == "yes") echo " checked"; ?>> <?php echo gettext("Suricata will double-decode path section of the URI. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Double-Decode Query"); ?></td> - <td width="78%" class="vtable"><input name="enable_double_decode_query" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-query'] == "yes") echo "checked"; ?>> + <td width="78%" class="vtable"><input name="enable_double_decode_query" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-query'] == "yes") echo " checked"; ?>> <?php echo gettext("Suricata will double-decode query string section of the URI. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> </tr> <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("URI Include-All"); ?></td> + <td width="78%" class="vtable"><input name="enable_uri_include_all" type="checkbox" value="yes" <?php if ($pengcfg['uri-include-all'] == "yes") echo " checked"; ?>> + <?php echo gettext("Include all parts of the URI. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?><br/><br/> + <?php echo gettext("By default the 'scheme', username/password, hostname and port are excluded from inspection. Enabling this option " . + "adds all of them to the normalized uri. This was the default in Suricata versions prior to 2.0."); ?></td> + </tr> + <tr> <td width="22%" valign="bottom"> </td> <td width="78%" valign="bottom"> <input name="save_libhtp_policy" id="save_libhtp_policy" type="submit" class="formbtn" value=" Save " title="<?php echo @@ -172,6 +183,7 @@ <input name="cancel_libhtp_policy" id="cancel_libhtp_policy" type="submit" class="formbtn" value="Cancel" title="<?php echo gettext("Cancel changes and return to App Parsers tab"); ?>"></td> </tr> + </tbody> </table> <script type="text/javascript" src="/javascript/autosuggest.js"> diff --git a/config/suricata/suricata_list_view.php b/config/suricata/suricata_list_view.php index 722bf47a..ec335abd 100644 --- a/config/suricata/suricata_list_view.php +++ b/config/suricata/suricata_list_view.php @@ -42,7 +42,7 @@ $type = htmlspecialchars($_GET['type']); $title = "List"; if (isset($id) && isset($wlist)) { - $a_rule = $config['installedpackages']['suricataglobal']['rule'][$id]; + $a_rule = $config['installedpackages']['suricata']['rule'][$id]; if ($type == "homenet") { $list = suricata_build_list($a_rule, $wlist); $contents = implode("\n", $list); @@ -58,6 +58,20 @@ if (isset($id) && isset($wlist)) { $contents = str_replace("\r", "", base64_decode($list['suppresspassthru'])); $title = "Suppress List"; } + elseif ($type == "externalnet") { + if ($wlist == "default") { + $list = suricata_build_list($a_rule, $a_rule['homelistname']); + $contents = ""; + foreach ($list as $ip) + $contents .= "!{$ip}\n"; + $contents = trim($contents, "\n"); + } + else { + $list = suricata_build_list($a_rule, $wlist, false, true); + $contents = implode("\n", $list); + } + $title = "EXTERNAL_NET"; + } else $contents = gettext("\n\nERROR -- Requested List Type entity is not valid!"); } diff --git a/config/suricata/suricata_logs_browser.php b/config/suricata/suricata_logs_browser.php index cbe5ee7b..d4475625 100644 --- a/config/suricata/suricata_logs_browser.php +++ b/config/suricata/suricata_logs_browser.php @@ -85,7 +85,6 @@ include_once("head.inc"); <?php include_once("fbegin.inc"); -if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} if ($input_errors) { print_input_errors($input_errors); } @@ -95,8 +94,8 @@ if ($input_errors) { <script type="text/javascript"> function loadFile() { jQuery("#fileStatus").html("<?=gettext("Loading file"); ?> ..."); - jQuery("#fileStatusBox").show(500); - jQuery("#filePathBox").show(500); + jQuery("#fileStatusBox").show(250); + jQuery("#filePathBox").show(250); jQuery("#fbTarget").html(""); jQuery.ajax( @@ -109,7 +108,7 @@ if ($input_errors) { } function loadComplete(req) { - jQuery("#fileContent").show(1000); + jQuery("#fileContent").show(250); var values = req.responseText.split("|"); values.shift(); values.pop(); @@ -118,14 +117,17 @@ if ($input_errors) { var fileContent = Base64.decode(values.join("|")); jQuery("#fileStatus").html("<?=gettext("File successfully loaded"); ?>."); jQuery("#fbTarget").html(file); + jQuery("#fileRefreshBtn").show(); + jQuery("#fileContent").prop("disabled", false); jQuery("#fileContent").val(fileContent); } else { jQuery("#fileStatus").html(values[0]); jQuery("#fbTarget").html(""); + jQuery("#fileRefreshBtn").hide(); jQuery("#fileContent").val(""); + jQuery("#fileContent").prop("disabled", true); } - jQuery("#fileContent").show(1000); } </script> @@ -134,18 +136,21 @@ if ($input_errors) { <input type="hidden" id="instance" value="<?=$instanceid;?>"/> <?php if ($savemsg) print_info_box($savemsg); ?> <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$instanceid}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), true, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), true, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> @@ -153,6 +158,7 @@ if ($input_errors) { <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6"> + <tbody> <tr> <td colspan="2" class="listtopic"><?php echo gettext("Logs Browser Selections"); ?></td> </tr> @@ -176,7 +182,7 @@ if ($input_errors) { <td width="78%" class="vtable"> <select name="logFile" id="logFile" class="formselect" onChange="loadFile();"> <?php - $logs = array( "alerts.log", "block.log", "files-json.log", "http.log", "stats.log", "suricata.log", "tls.log" ); + $logs = array( "alerts.log", "block.log", "dns.log", "eve.json", "files-json.log", "http.log", "sid_changes.log", "stats.log", "suricata.log", "tls.log" ); foreach ($logs as $log) { $selected = ""; if ($log == basename($logfile)) @@ -192,34 +198,51 @@ if ($input_errors) { </tr> <tr> <td colspan="2"> - <div style="display:none; " id="fileStatusBox"> - <div class="list" style="padding-left:15px;"> - <strong id="fileStatus"></strong> - </div> - </div> - <div style="padding-left:15px; display:none;" id="filePathBox"> - <strong><?=gettext("Log File Path"); ?>:</strong> - <div class="list" style="display:inline;" id="fbTarget"></div> - </div> + <table width="100%"> + <tbody> + <tr> + <td width="75%"> + <div style="display:none; " id="fileStatusBox"> + <div class="list" style="padding-left:15px;"> + <strong id="fileStatus"></strong> + </div> + </div> + <div style="padding-left:15px; display:none;" id="filePathBox"> + <strong><?=gettext("Log File Path"); ?>:</strong> + <div class="list" style="display:inline;" id="fbTarget"></div> + </div> + </td> + <td align="right"> + <div style="padding-right:15px; display:none;" id="fileRefreshBtn"> + <input type="button" name="refresh" id="refresh" value="Refresh" class="formbtn" onclick="loadFile();" title="<?=gettext("Refresh current display");?>" /> + </div> + </td> + </tr> + </tbody> + </table> </td> </tr> <tr> <td colspan="2"> <table width="100%"> + <tbody> <tr> <td valign="top" class="label"> <div style="background:#eeeeee;" id="fileOutput"> - <textarea id="fileContent" name="fileContent" style="width:100%;" rows="30" wrap="off"></textarea> + <textarea id="fileContent" name="fileContent" style="width:100%;" rows="30" wrap="off" disabled></textarea> </div> </td> </tr> + </tbody> </table> </td> </tr> + </tbody> </table> </div> </td> </tr> + </tbody> </table> </form> diff --git a/config/suricata/suricata_logs_mgmt.php b/config/suricata/suricata_logs_mgmt.php index 16376c5b..fec2d149 100644 --- a/config/suricata/suricata_logs_mgmt.php +++ b/config/suricata/suricata_logs_mgmt.php @@ -67,6 +67,12 @@ $pconfig['tls_log_retention'] = $config['installedpackages']['suricata']['config $pconfig['unified2_log_limit'] = $config['installedpackages']['suricata']['config'][0]['unified2_log_limit']; $pconfig['u2_archive_log_retention'] = $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention']; $pconfig['file_store_retention'] = $config['installedpackages']['suricata']['config'][0]['file_store_retention']; +$pconfig['dns_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['dns_log_limit_size']; +$pconfig['dns_log_retention'] = $config['installedpackages']['suricata']['config'][0]['dns_log_retention']; +$pconfig['eve_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['eve_log_limit_size']; +$pconfig['eve_log_retention'] = $config['installedpackages']['suricata']['config'][0]['eve_log_retention']; +$pconfig['sid_changes_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size']; +$pconfig['sid_changes_log_retention'] = $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention']; // Load up some arrays with selection values (we use these later). // The keys in the $retentions array are the retention period @@ -88,40 +94,97 @@ if (empty($pconfig['suricataloglimitsize'])) { } // Set default retention periods for rotated logs -if (empty($pconfig['alert_log_retention'])) +if (!isset($pconfig['alert_log_retention'])) $pconfig['alert_log_retention'] = "336"; -if (empty($pconfig['block_log_retention'])) +if (!isset($pconfig['block_log_retention'])) $pconfig['block_log_retention'] = "336"; -if (empty($pconfig['files_json_log_retention'])) +if (!isset($pconfig['files_json_log_retention'])) $pconfig['files_json_log_retention'] = "168"; -if (empty($pconfig['http_log_retention'])) +if (!isset($pconfig['http_log_retention'])) $pconfig['http_log_retention'] = "168"; -if (empty($pconfig['stats_log_retention'])) +if (!isset($pconfig['dns_log_retention'])) + $pconfig['dns_log_retention'] = "168"; +if (!isset($pconfig['stats_log_retention'])) $pconfig['stats_log_retention'] = "168"; -if (empty($pconfig['tls_log_retention'])) +if (!isset($pconfig['tls_log_retention'])) $pconfig['tls_log_retention'] = "336"; -if (empty($pconfig['u2_archive_log_retention'])) +if (!isset($pconfig['u2_archive_log_retention'])) $pconfig['u2_archive_log_retention'] = "168"; -if (empty($pconfig['file_store_retention'])) +if (!isset($pconfig['file_store_retention'])) $pconfig['file_store_retention'] = "168"; +if (!isset($pconfig['eve_log_retention'])) + $pconfig['eve_log_retention'] = "168"; +if (!isset($pconfig['sid_changes_log_retention'])) + $pconfig['sid_changes_log_retention'] = "336"; // Set default log file size limits -if (empty($pconfig['alert_log_limit_size'])) +if (!isset($pconfig['alert_log_limit_size'])) $pconfig['alert_log_limit_size'] = "500"; -if (empty($pconfig['block_log_limit_size'])) +if (!isset($pconfig['block_log_limit_size'])) $pconfig['block_log_limit_size'] = "500"; -if (empty($pconfig['files_json_log_limit_size'])) +if (!isset($pconfig['files_json_log_limit_size'])) $pconfig['files_json_log_limit_size'] = "1000"; -if (empty($pconfig['http_log_limit_size'])) +if (!isset($pconfig['http_log_limit_size'])) $pconfig['http_log_limit_size'] = "1000"; -if (empty($pconfig['stats_log_limit_size'])) +if (!isset($pconfig['dns_log_limit_size'])) + $pconfig['dns_log_limit_size'] = "750"; +if (!isset($pconfig['stats_log_limit_size'])) $pconfig['stats_log_limit_size'] = "500"; -if (empty($pconfig['tls_log_limit_size'])) +if (!isset($pconfig['tls_log_limit_size'])) $pconfig['tls_log_limit_size'] = "500"; -if (empty($pconfig['unified2_log_limit'])) +if (!isset($pconfig['unified2_log_limit'])) $pconfig['unified2_log_limit'] = "32"; +if (!isset($pconfig['eve_log_limit_size'])) + $pconfig['eve_log_limit_size'] = "5000"; +if (!isset($pconfig['sid_changes_log_limit_size'])) + $pconfig['sid_changes_log_limit_size'] = "250"; + +if ($_POST['ResetAll']) { + + // Reset all settings to their defaults + $pconfig['alert_log_retention'] = "336"; + $pconfig['block_log_retention'] = "336"; + $pconfig['files_json_log_retention'] = "168"; + $pconfig['http_log_retention'] = "168"; + $pconfig['dns_log_retention'] = "168"; + $pconfig['stats_log_retention'] = "168"; + $pconfig['tls_log_retention'] = "336"; + $pconfig['u2_archive_log_retention'] = "168"; + $pconfig['file_store_retention'] = "168"; + $pconfig['eve_log_retention'] = "168"; + $pconfig['sid_changes_log_retention'] = "336"; + + $pconfig['alert_log_limit_size'] = "500"; + $pconfig['block_log_limit_size'] = "500"; + $pconfig['files_json_log_limit_size'] = "1000"; + $pconfig['http_log_limit_size'] = "1000"; + $pconfig['dns_log_limit_size'] = "750"; + $pconfig['stats_log_limit_size'] = "500"; + $pconfig['tls_log_limit_size'] = "500"; + $pconfig['unified2_log_limit'] = "32"; + $pconfig['eve_log_limit_size'] = "5000"; + $pconfig['sid_changes_log_limit_size'] = "250"; + + /* Log a message at the top of the page to inform the user */ + $savemsg = gettext("All log management settings on this page have been reset to their defaults. Click APPLY if you wish to keep these new settings."); +} + +if ($_POST["save"] || $_POST['apply']) { + if ($_POST['enable_log_mgmt'] != 'on') { + $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] = $_POST['enable_log_mgmt'] ? 'on' :'off'; + write_config("Suricata pkg: saved updated configuration for LOGS MGMT."); + sync_suricata_package_config(); + + /* forces page to reload new settings */ + header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); + header( 'Cache-Control: no-store, no-cache, must-revalidate' ); + header( 'Cache-Control: post-check=0, pre-check=0', false ); + header( 'Pragma: no-cache' ); + header("Location: /suricata/suricata_logs_mgmt.php"); + exit; + } -if ($_POST["save"]) { if ($_POST['suricataloglimit'] == 'on') { if (!is_numericint($_POST['suricataloglimitsize']) || $_POST['suricataloglimitsize'] < 1) $input_errors[] = gettext("The 'Log Directory Size Limit' must be an integer value greater than zero."); @@ -151,8 +214,14 @@ if ($_POST["save"]) { $config['installedpackages']['suricata']['config'][0]['unified2_log_limit'] = $_POST['unified2_log_limit']; $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] = $_POST['u2_archive_log_retention']; $config['installedpackages']['suricata']['config'][0]['file_store_retention'] = $_POST['file_store_retention']; + $config['installedpackages']['suricata']['config'][0]['dns_log_limit_size'] = $_POST['dns_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['dns_log_retention'] = $_POST['dns_log_retention']; + $config['installedpackages']['suricata']['config'][0]['eve_log_limit_size'] = $_POST['eve_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['eve_log_retention'] = $_POST['eve_log_retention']; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size'] = $_POST['sid_changes_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention'] = $_POST['sid_changes_log_retention']; - write_config(); + write_config("Suricata pkg: saved updated configuration for LOGS MGMT."); sync_suricata_package_config(); /* forces page to reload new settings */ @@ -179,23 +248,32 @@ include_once("fbegin.inc"); /* Display Alert message, under form tag or no refresh */ if ($input_errors) print_input_errors($input_errors); - ?> <form action="suricata_logs_mgmt.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> + +<?php +if ($savemsg) { + /* Display save message */ + print_info_box($savemsg); +} +?> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), true, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -267,7 +345,7 @@ if ($input_errors) <colgroup> <col style="width: 15%;"> <col style="width: 18%;"> - <col style="width: 20%;"> + <col style="width: 18%;"> <col> </colgroup> <thead> @@ -320,6 +398,46 @@ if ($input_errors) <td class="listbg"><?=gettext("Suricata blocked IPs and event details");?></td> </tr> <tr> + <td class="listbg">dns</td> + <td class="listr" align="center"><select name="dns_log_limit_size" class="formselect" id="dns_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['dns_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="dns_log_retention" class="formselect" id="dns_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['dns_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("DNS request/reply details");?></td> + </tr> + <tr> + <td class="listbg">eve-json</td> + <td class="listr" align="center"><select name="eve_log_limit_size" class="formselect" id="eve_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['eve_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="eve_log_retention" class="formselect" id="eve_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['eve_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Eve-JSON (JavaScript Object Notation) data");?></td> + </tr> + <tr> <td class="listbg">files-json</td> <td class="listr" align="center"><select name="files_json_log_limit_size" class="formselect" id="files_json_log_limit_size"> <?php foreach ($log_sizes as $k => $l): ?> @@ -359,6 +477,28 @@ if ($input_errors) </td> <td class="listbg"><?=gettext("Captured HTTP events and session info");?></td> </tr> + + <tr> + <td class="listbg">sid_changes</td> + <td class="listr" align="center"><select name="sid_changes_log_limit_size" class="formselect" id="sid_changes_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['sid_changes_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="sid_changes_log_retention" class="formselect" id="sid_changes_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['sid_changes_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Log of SID changes made by SID Mgmt conf files");?></td> + </tr> + <tr> <td class="listbg">stats</td> <td class="listr" align="center"><select name="stats_log_limit_size" class="formselect" id="stats_log_limit_size"> @@ -444,7 +584,11 @@ if ($input_errors) </tr> <tr> <td width="22%"></td> - <td width="78%" class="vexpl"><input name="save" type="submit" class="formbtn" value="Save"/><br/> + <td width="78%" class="vexpl"><input name="save" type="submit" class="formbtn" value="Save"/> + <input name="ResetAll" type="submit" class="formbtn" value="Reset" title="<?php echo + gettext("Reset all settings to defaults") . "\" onclick=\"return confirm('" . + gettext("WARNING: This will reset ALL Log Management settings to their defaults. Click OK to continue or CANCEL to quit.") . + "');\""; ?>/><br/> <br/><span class="red"><strong><?php echo gettext("Note:");?></strong> </span><?php echo gettext("Changing any settings on this page will affect all Suricata-configured interfaces.");?></td> </tr> @@ -472,6 +616,12 @@ function enable_change() { document.iform.unified2_log_limit.disabled = endis; document.iform.u2_archive_log_retention.disabled = endis; document.iform.file_store_retention.disabled = endis; + document.iform.dns_log_retention.disabled = endis; + document.iform.dns_log_limit_size.disabled = endis; + document.iform.eve_log_retention.disabled = endis; + document.iform.eve_log_limit_size.disabled = endis; + document.iform.sid_changes_log_retention.disabled = endis; + document.iform.sid_changes_log_limit_size.disabled = endis; } function enable_change_dirSize() { diff --git a/config/suricata/suricata_migrate_config.php b/config/suricata/suricata_migrate_config.php new file mode 100644 index 00000000..ba13155b --- /dev/null +++ b/config/suricata/suricata_migrate_config.php @@ -0,0 +1,355 @@ +<?php +/* + * suricata_migrate_config.php + * + * Copyright (C) 2014 Bill Meeks + * All rights reserved. + * + * 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. + */ + +require_once("config.inc"); +require_once("functions.inc"); + +/****************************************************************************/ +/* The code in this module is called once during the post-install process */ +/* via an "include" line. It is used to perform a one-time migration of */ +/* Suricata configuration parameters to any new format required by the */ +/* latest package version. */ +/****************************************************************************/ + +global $config; + +if (!is_array($config['installedpackages']['suricata'])) + $config['installedpackages']['suricata'] = array(); +if (!is_array($config['installedpackages']['suricata']['rule'])) + $config['installedpackages']['suricata']['rule'] = array(); + +// Just exit if this is a clean install with no saved settings +if (empty($config['installedpackages']['suricata']['rule'])) + return; + +$rule = &$config['installedpackages']['suricata']['rule']; + +/****************************************************************************/ +/* Loop through all the <rule> elements in the Suricata configuration and */ +/* migrate relevant parameters to the new format. */ +/****************************************************************************/ + +$updated_cfg = false; +log_error("[Suricata] Checking configuration settings version..."); + +// Check the configuration version to see if XMLRPC Sync should +// auto-disabled as part of the upgrade due to config format changes. +if ($config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] < 2 && + ($config['installedpackages']['suricatasync']['config'][0]['varsynconchanges'] == 'auto' || + $config['installedpackages']['suricatasync']['config'][0]['varsynconchanges'] == 'manual')) { + $config['installedpackages']['suricatasync']['config'][0]['varsynconchanges'] = "disabled"; + log_error("[Suricata] Turning off Suricata Sync on this host due to configuration format changes in this update. Upgrade all Suricata Sync targets to this same Suricata package version before re-enabling Suricata Sync."); + $updated_cfg = true; +} + +/**********************************************************/ +/* Create new Auto SID Mgmt settings if not set */ +/**********************************************************/ + if (empty($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'])) { + $config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] = "off"; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size'] = "250"; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention'] = "336"; + $updated_cfg = true; + } + +// Now process the interface-specific settings +foreach ($rule as &$r) { + + // Initialize arrays for supported preprocessors if necessary + if (!is_array($r['libhtp_policy']['item'])) + $r['libhtp_policy']['item'] = array(); + + $pconfig = array(); + $pconfig = $r; + + /***********************************************************/ + /* This setting is deprecated in Suricata 2.0 and higher, */ + /* so remove it from the configuration. */ + /***********************************************************/ + if (isset($pconfig['stream_max_sessions'])) { + unset($pconfig['stream_max_sessions']); + $updated_cfg = true; + } + + /***********************************************************/ + /* HTTP server personalities for "Apache" and "Apache_2_2" */ + /* are deprecated and replaced with "Apache_2" in Suricata */ + /* versions greater than 2.0. */ + /***********************************************************/ + $http_serv = &$pconfig['libhtp_policy']['item']; + foreach ($http_serv as &$policy) { + if ($policy['personality'] == "Apache" || $policy['personality'] == "Apache_2_2") { + $policy['personality'] = "Apache_2"; + $updated_cfg = true; + } + // Set new URI inspect option for Suricata 2.0 and higher + if (!isset($policy['uri-include-all'])) { + $policy['uri-include-all'] = "no"; + $updated_cfg = true; + } + } + + /***********************************************************/ + /* Add the new 'dns-events.rules' file to the rulesets. */ + /***********************************************************/ + if (strpos("dns-events.rules", $pconfig['rulesets']) === FALSE) { + $pconfig['rulesets'] = rtrim($pconfig['rulesets'], "||") . "||dns-events.rules"; + $updated_cfg = true; + } + + /***********************************************************/ + /* Add new interface promisc mode value and default 'on'. */ + /***********************************************************/ + if (empty($pconfig['intf_promisc_mode'])) { + $pconfig['intf_promisc_mode'] = "on"; + $updated_cfg = true; + } + + /***********************************************************/ + /* Add new HTTP Log Extended Info setting if not present */ + /***********************************************************/ + if (!isset($pconfig['http_log_extended'])) { + $pconfig['http_log_extended'] = "on"; + $updated_cfg = true; + } + + /***********************************************************/ + /* Add new EVE logging settings if not present */ + /***********************************************************/ + if (!isset($pconfig['eve_output_type'])) { + $pconfig['eve_output_type'] = "file"; + $updated_cfg = true; + } + if (empty($pconfig['eve_systemlog_facility'])) { + $pconfig['eve_systemlog_facility'] = "local1"; + $updated_cfg = true; + } + if (empty($pconfig['eve_systemlog_priority'])) { + $pconfig['eve_systemlog_priority'] = "info"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_alerts'])) { + $pconfig['eve_log_alerts'] = "on"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_http'])) { + $pconfig['eve_log_http'] = "on"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_dns'])) { + $pconfig['eve_log_dns'] = "on"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_tls'])) { + $pconfig['eve_log_tls'] = "on"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_files'])) { + $pconfig['eve_log_files'] = "on"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_ssh'])) { + $pconfig['eve_log_ssh'] = "on"; + $updated_cfg = true; + } + + /******************************************************************/ + /* Create default log size and retention limits if not set */ + /******************************************************************/ + if (!isset($pconfig['alert_log_retention']) && $pconfig['alert_log_retention'] != '0') { + $pconfig['alert_log_retention'] = "336"; + $updated_cfg = true; + } + if (!isset($pconfig['alert_log_limit_size']) && $pconfig['alert_log_limit_size'] != '0') { + $pconfig['alert_log_limit_size'] = "500"; + $updated_cfg = true; + } + + if (!isset($pconfig['block_log_retention']) && $pconfig['block_log_retention'] != '0') { + $pconfig['block_log_retention'] = "336"; + $updated_cfg = true; + } + if (!isset($pconfig['block_log_limit_size']) && $pconfig['block_log_limit_size'] != '0') { + $pconfig['block_log_limit_size'] = "500"; + $updated_cfg = true; + } + + if (!isset($pconfig['dns_log_retention']) && $pconfig['dns_log_retention'] != '0') { + $pconfig['dns_log_retention'] = "168"; + $updated_cfg = true; + } + if (!isset($pconfig['dns_log_limit_size']) && $pconfig['dns_log_limit_size'] != '0') { + $pconfig['dns_log_limit_size'] = "750"; + $updated_cfg = true; + } + + if (!isset($pconfig['eve_log_retention']) && $pconfig['eve_log_retention'] != '0') { + $pconfig['eve_log_retention'] = "168"; + $updated_cfg = true; + } + if (!isset($pconfig['eve_log_limit_size']) && $pconfig['eve_log_limit_size'] != '0') { + $pconfig['eve_log_limit_size'] = "5000"; + $updated_cfg = true; + } + + if (!isset($pconfig['files_json_log_retention']) && $pconfig['files_json_log_retention'] != '0') { + $pconfig['files_json_log_retention'] = "168"; + $updated_cfg = true; + } + if (!isset($pconfig['files_json_log_limit_size']) && $pconfig['files_json_log_limit_size'] != '0') { + $pconfig['files_json_log_limit_size'] = "1000"; + $updated_cfg = true; + } + + if (!isset($pconfig['http_log_retention']) && $pconfig['http_log_retention'] != '0') { + $pconfig['http_log_retention'] = "168"; + $updated_cfg = true; + } + if (!isset($pconfig['http_log_limit_size']) && $pconfig['http_log_limit_size'] != '0') { + $pconfig['http_log_limit_size'] = "1000"; + $updated_cfg = true; + } + + if (!isset($pconfig['stats_log_retention']) && $pconfig['stats_log_retention'] != '0') { + $pconfig['stats_log_retention'] = "168"; + $updated_cfg = true; + } + if (!isset($pconfig['stats_log_limit_size']) && $pconfig['stats_log_limit_size'] != '0') { + $pconfig['stats_log_limit_size'] = "500"; + $updated_cfg = true; + } + + if (!isset($pconfig['tls_log_retention']) && $pconfig['tls_log_retention'] != '0') { + $pconfig['tls_log_retention'] = "336"; + $updated_cfg = true; + } + if (!isset($pconfig['tls_log_limit_size']) && $pconfig['tls_log_limit_size'] != '0') { + $pconfig['tls_log_limit_size'] = "500"; + $updated_cfg = true; + } + + if (!isset($pconfig['file_store_retention']) && $pconfig['file_store_retention'] != '0') { + $pconfig['file_store_retention'] = "168"; + $updated_cfg = true; + } + + if (!isset($pconfig['u2_archive_log_retention']) && $pconfig['u2_archive_log_retention'] != '0') { + $pconfig['u2_archive_log_retention'] = "168"; + $updated_cfg = true; + } + + /************************************************************/ + /* Create new DNS App-Layer parser settings if not set */ + /************************************************************/ + if (empty($pconfig['dns_global_memcap'])) { + $pconfig['dns_global_memcap'] = "16777216"; + $updated_cfg = true; + } + if (empty($pconfig['dns_state_memcap'])) { + $pconfig['dns_state_memcap'] = "524288"; + $updated_cfg = true; + } + if (empty($pconfig['dns_request_flood_limit'])) { + $pconfig['dns_request_flood_limit'] = "500"; + $updated_cfg = true; + } + if (empty($pconfig['dns_parser_udp'])) { + $pconfig['dns_parser_udp'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['dns_parser_tcp'])) { + $pconfig['dns_parser_tcp'] = "yes"; + $updated_cfg = true; + } + + /***********************************************************/ + /* Create new HTTP App-Layer parser settings if not set */ + /***********************************************************/ + if (empty($pconfig['http_parser'])) { + $pconfig['http_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['http_parser_memcap'])) { + $pconfig['http_parser_memcap'] = "67108864"; + $updated_cfg = true; + } + + /**********************************************************/ + /* Create other App-Layer parser settings if not set */ + /**********************************************************/ + if (empty($pconfig['tls_parser'])) { + $pconfig['tls_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['smtp_parser'])) { + $pconfig['smtp_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['imap_parser'])) { + $pconfig['imap_parser'] = "detection-only"; + $updated_cfg = true; + } + if (empty($pconfig['ssh_parser'])) { + $pconfig['ssh_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['ftp_parser'])) { + $pconfig['ftp_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['dcerpc_parser'])) { + $pconfig['dcerpc_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['smb_parser'])) { + $pconfig['smb_parser'] = "yes"; + $updated_cfg = true; + } + if (empty($pconfig['msn_parser'])) { + $pconfig['msn_parser'] = "detection-only"; + $updated_cfg = true; + } + + // Save the new configuration data into the $config array pointer + $r = $pconfig; +} +// Release reference to final array element +unset($r); + +// Write out the new configuration to disk if we changed anything +if ($updated_cfg) { + $config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "2.0"; + log_error("[Suricata] Saving configuration settings in new format..."); + write_config("Suricata pkg: migrate existing settings to new format during package upgrade."); + log_error("[Suricata] Settings successfully migrated to new configuration format..."); +} +else + log_error("[Suricata] Configuration version is current..."); + +?> diff --git a/config/suricata/suricata_os_policy_engine.php b/config/suricata/suricata_os_policy_engine.php index 869d940c..9a881f3d 100644 --- a/config/suricata/suricata_os_policy_engine.php +++ b/config/suricata/suricata_os_policy_engine.php @@ -62,6 +62,7 @@ ?> <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" align="center" class="listtopic"><?php echo gettext("Suricata Target-Based Host OS Policy Engine Configuration"); ?></td> </tr> @@ -69,7 +70,7 @@ <td valign="top" class="vncell"><?php echo gettext("Policy Name"); ?></td> <td class="vtable"> <input name="policy_name" type="text" class="formfld unknown" id="policy_name" size="25" maxlength="25" - value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == "default") echo "readonly";?>/> + value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == " default") echo " readonly";?>/> <?php if (htmlspecialchars($pengcfg['name']) <> "default") echo gettext("Name or description for this engine. (Max 25 characters)"); else @@ -83,6 +84,7 @@ <td class="vtable"> <?php if ($pengcfg['name'] <> "default") : ?> <table width="95%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td class="vexpl"><input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" value="<?=htmlspecialchars($pengcfg['bind_to']);?>" title="<?=trim(filter_expand_alias($pengcfg['bind_to']));?>" autocomplete="off"/> @@ -93,6 +95,7 @@ <tr> <td class="vexpl" colspan="2"><?php echo gettext("This policy will apply for packets with destination addresses contained within this IP List.");?></td> </tr> + </tbody> </table> <span class="red"><strong><?php echo gettext("Note: ") . "</strong></span>" . gettext("Supplied value must be a pre-configured Alias or the keyword 'all'.");?> @@ -129,6 +132,7 @@ <input name="cancel_os_policy" id="cancel_os_policy" type="submit" class="formbtn" value="Cancel" title="<?php echo gettext("Cancel changes and return to Flow/Stream tab"); ?>"></td> </tr> + </tbody> </table> <script type="text/javascript" src="/javascript/autosuggest.js"> </script> diff --git a/config/suricata/suricata_passlist.php b/config/suricata/suricata_passlist.php index fc7c60e2..02aa4a3d 100644 --- a/config/suricata/suricata_passlist.php +++ b/config/suricata/suricata_passlist.php @@ -115,18 +115,21 @@ if ($savemsg) { <form action="/suricata/suricata_passlist.php" method="post"> <input type="hidden" name="list_id" id="list_id" value=""/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), true, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> @@ -134,6 +137,7 @@ if ($savemsg) { <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td width="25%" class="listhdrr">List Name</td> <td width="30%" class="listhdrr">Assigned Alias</td> @@ -142,19 +146,19 @@ if ($savemsg) { </tr> <?php foreach ($a_passlist as $i => $list): ?> <tr> - <td class="listlr" + <td class="listlr" ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';"> <?=htmlspecialchars($list['name']);?></td> - <td class="listr" + <td class="listr" ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';" title="<?=filter_expand_alias($list['address']);?>"> <?php echo gettext($list['address']);?></td> - <td class="listbg" + <td class="listbg" ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';"> - <font color="#FFFFFF"> <?=htmlspecialchars($list['descr']);?> - </td> + <font color="#FFFFFF"><?=htmlspecialchars($list['descr']);?></font></td> <td valign="middle" nowrap class="list"> <table border="0" cellspacing="0" cellpadding="1"> + <tbody> <tr> <td valign="middle"><a href="suricata_passlist_edit.php?id=<?=$i;?>"> <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" title="<?php echo gettext("Edit pass list"); ?>"></a> @@ -163,6 +167,7 @@ if ($savemsg) { src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" title="<?php echo gettext("Delete pass list"); ?>"/> </td> </tr> + </tbody> </table> </td> </tr> @@ -171,6 +176,7 @@ if ($savemsg) { <td class="list" colspan="3"></td> <td class="list"> <table border="0" cellspacing="0" cellpadding="1"> + <tbody> <tr> <td valign="middle" width="17"> </td> <td valign="middle"><a href="suricata_passlist_edit.php?id=<?php echo $id_gen;?> "> @@ -178,27 +184,31 @@ if ($savemsg) { width="17" height="17" border="0" title="<?php echo gettext("add a new pass list"); ?>"/></a> </td> </tr> + </tbody> </table> </td> </tr> + </tbody> </table> </div> </td> </tr> + </tbody> </table> <br> -<table width="100%" border="0" cellpadding="1" - cellspacing="1"> +<table width="100%" border="0" cellpadding="1" cellspacing="1"> + <tbody> <tr> - <td width="100%"><span class="vexpl"><span class="red"><strong><?php echo gettext("Notes:"); ?></strong></span> - <p><?php echo gettext("1. Here you can create Pass List files for your Suricata package rules. Hosts on a Pass List are never blocked by Suricata."); ?><br/> - <?php echo gettext("2. Add all the IP addresses or networks (in CIDR notation) you want to protect against Suricata block decisions."); ?><br/> - <?php echo gettext("3. The default Pass List includes the WAN IP and gateway, defined DNS servers, VPNs and locally-attached networks."); ?><br/> - <?php echo gettext("4. Be careful, it is very easy to get locked out of your system by altering the default settings."); ?></p></span></td> + <td width="100%"><span class="vexpl"><span class="red"><strong><?php echo gettext("Notes:"); ?></strong></span> + <p><?php echo gettext("1. Here you can create Pass List files for your Suricata package rules. Hosts on a Pass List are never blocked by Suricata."); ?><br/> + <?php echo gettext("2. Add all the IP addresses or networks (in CIDR notation) you want to protect against Suricata block decisions."); ?><br/> + <?php echo gettext("3. The default Pass List includes the WAN IP and gateway, defined DNS servers, VPNs and locally-attached networks."); ?><br/> + <?php echo gettext("4. Be careful, it is very easy to get locked out of your system by altering the default settings."); ?></p></span></td> </tr> <tr> - <td width="100%"><span class="vexpl"><?php echo gettext("Remember you must restart Suricata on the interface for changes to take effect!"); ?></span></td> + <td width="100%"><span class="vexpl"><?php echo gettext("Remember you must restart Suricata on the interface for changes to take effect!"); ?></span></td> </tr> + </tbody> </table> </form> <?php include("fend.inc"); ?> diff --git a/config/suricata/suricata_passlist_edit.php b/config/suricata/suricata_passlist_edit.php index 437ae9a8..3e1502f3 100644 --- a/config/suricata/suricata_passlist_edit.php +++ b/config/suricata/suricata_passlist_edit.php @@ -63,15 +63,53 @@ if (is_null($id)) { exit; } +if (isset($id) && isset($a_passlist[$id])) { + /* Retrieve saved settings */ + $pconfig['name'] = $a_passlist[$id]['name']; + $pconfig['uuid'] = $a_passlist[$id]['uuid']; + $pconfig['address'] = $a_passlist[$id]['address']; + $pconfig['descr'] = html_entity_decode($a_passlist[$id]['descr']); + $pconfig['localnets'] = $a_passlist[$id]['localnets']; + $pconfig['wanips'] = $a_passlist[$id]['wanips']; + $pconfig['wangateips'] = $a_passlist[$id]['wangateips']; + $pconfig['wandnsips'] = $a_passlist[$id]['wandnsips']; + $pconfig['vips'] = $a_passlist[$id]['vips']; + $pconfig['vpnips'] = $a_passlist[$id]['vpnips']; +} + +// Check for returned "selected alias" if action is import +if ($_GET['act'] == "import") { + + // Retrieve previously typed values we passed to SELECT ALIAS page + $pconfig['name'] = htmlspecialchars($_GET['name']); + $pconfig['uuid'] = htmlspecialchars($_GET['uuid']); + $pconfig['address'] = htmlspecialchars($_GET['address']); + $pconfig['descr'] = htmlspecialchars($_GET['descr']); + $pconfig['localnets'] = htmlspecialchars($_GET['localnets'])? 'yes' : 'no'; + $pconfig['wanips'] = htmlspecialchars($_GET['wanips'])? 'yes' : 'no'; + $pconfig['wangateips'] = htmlspecialchars($_GET['wangateips'])? 'yes' : 'no'; + $pconfig['wandnsips'] = htmlspecialchars($_GET['wandnsips'])? 'yes' : 'no'; + $pconfig['vips'] = htmlspecialchars($_GET['vips'])? 'yes' : 'no'; + $pconfig['vpnips'] = htmlspecialchars($_GET['vpnips'])? 'yes' : 'no'; + + // Now retrieve the "selected alias" returned from SELECT ALIAS page + if ($_GET['varname'] == "address" && isset($_GET['varvalue'])) + $pconfig[$_GET['varname']] = htmlspecialchars($_GET['varvalue']); +} + /* If no entry for this passlist, then create a UUID and treat it like a new list */ -if (!isset($a_passlist[$id]['uuid'])) { +if (!isset($a_passlist[$id]['uuid']) && empty($pconfig['uuid'])) { $passlist_uuid = 0; while ($passlist_uuid > 65535 || $passlist_uuid == 0) { $passlist_uuid = mt_rand(1, 65535); $pconfig['uuid'] = $passlist_uuid; $pconfig['name'] = "passlist_{$passlist_uuid}"; } -} else +} +elseif (!empty($pconfig['uuid'])) { + $passlist_uuid = $pconfig['uuid']; +} +else $passlist_uuid = $a_passlist[$id]['uuid']; /* returns true if $name is a valid name for a pass list file name or ip */ @@ -85,28 +123,6 @@ function is_validpasslistname($name) { return false; } -if (isset($id) && $a_passlist[$id]) { - /* old settings */ - $pconfig = array(); - $pconfig['name'] = $a_passlist[$id]['name']; - $pconfig['uuid'] = $a_passlist[$id]['uuid']; - $pconfig['detail'] = $a_passlist[$id]['detail']; - $pconfig['address'] = $a_passlist[$id]['address']; - $pconfig['descr'] = html_entity_decode($a_passlist[$id]['descr']); - $pconfig['localnets'] = $a_passlist[$id]['localnets']; - $pconfig['wanips'] = $a_passlist[$id]['wanips']; - $pconfig['wangateips'] = $a_passlist[$id]['wangateips']; - $pconfig['wandnsips'] = $a_passlist[$id]['wandnsips']; - $pconfig['vips'] = $a_passlist[$id]['vips']; - $pconfig['vpnips'] = $a_passlist[$id]['vpnips']; -} - -// Check for returned "selected alias" if action is import -if ($_GET['act'] == "import") { - if ($_GET['varname'] == "address" && isset($_GET['varvalue'])) - $pconfig[$_GET['varname']] = htmlspecialchars($_GET['varvalue']); -} - if ($_POST['save']) { unset($input_errors); $pconfig = $_POST; @@ -128,11 +144,11 @@ if ($_POST['save']) { $input_errors[] = gettext("Pass List file name may only consist of the characters \"a-z, A-Z, 0-9 and _\". Note: No Spaces or dashes. Press Cancel to reset."); /* check for name conflicts */ - foreach ($a_passlist as $w_list) { - if (isset($id) && ($a_passlist[$id]) && ($a_passlist[$id] === $w_list)) + foreach ($a_passlist as $p_list) { + if (isset($id) && ($a_passlist[$id]) && ($a_passlist[$id] === $p_list)) continue; - if ($w_list['name'] == $_POST['name']) { + if ($p_list['name'] == $_POST['name']) { $input_errors[] = gettext("A Pass List file name with this name already exists."); break; } @@ -143,27 +159,27 @@ if ($_POST['save']) { $input_errors[] = gettext("A valid alias must be provided"); if (!$input_errors) { - $w_list = array(); + $p_list = array(); /* post user input */ - $w_list['name'] = $_POST['name']; - $w_list['uuid'] = $passlist_uuid; - $w_list['localnets'] = $_POST['localnets']? 'yes' : 'no'; - $w_list['wanips'] = $_POST['wanips']? 'yes' : 'no'; - $w_list['wangateips'] = $_POST['wangateips']? 'yes' : 'no'; - $w_list['wandnsips'] = $_POST['wandnsips']? 'yes' : 'no'; - $w_list['vips'] = $_POST['vips']? 'yes' : 'no'; - $w_list['vpnips'] = $_POST['vpnips']? 'yes' : 'no'; - - $w_list['address'] = $_POST['address']; - $w_list['descr'] = mb_convert_encoding($_POST['descr'],"HTML-ENTITIES","auto"); - $w_list['detail'] = $final_address_details; + $p_list['name'] = $_POST['name']; + $p_list['uuid'] = $passlist_uuid; + $p_list['localnets'] = $_POST['localnets']? 'yes' : 'no'; + $p_list['wanips'] = $_POST['wanips']? 'yes' : 'no'; + $p_list['wangateips'] = $_POST['wangateips']? 'yes' : 'no'; + $p_list['wandnsips'] = $_POST['wandnsips']? 'yes' : 'no'; + $p_list['vips'] = $_POST['vips']? 'yes' : 'no'; + $p_list['vpnips'] = $_POST['vpnips']? 'yes' : 'no'; + + $p_list['address'] = $_POST['address']; + $p_list['descr'] = mb_convert_encoding(str_replace("\r\n", "\n", $_POST['descr']),"HTML-ENTITIES","auto"); + $p_list['detail'] = $final_address_details; if (isset($id) && $a_passlist[$id]) - $a_passlist[$id] = $w_list; + $a_passlist[$id] = $p_list; else - $a_passlist[] = $w_list; + $a_passlist[] = $p_list; - write_config("Snort pkg: modified PASS LIST {$w_list['name']}."); + write_config("Suricata pkg: modified PASS LIST {$p_list['name']}."); /* create pass list and homenet file, then sync files */ sync_suricata_package_config(); @@ -193,24 +209,28 @@ if ($savemsg) <form action="suricata_passlist_edit.php" method="post" name="iform" id="iform"> <input name="id" type="hidden" value="<?=$id;?>" /> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), true, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> </tr> <tr><td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Add the name and " . "description of the file."); ?></td> @@ -286,8 +306,8 @@ if ($savemsg) </td> <td width="78%" class="vtable"> <input autocomplete="off" name="address" type="text" class="formfldalias" id="address" size="30" value="<?=htmlspecialchars($pconfig['address']);?>" - title="<?=trim(filter_expand_alias($pconfig['address']));?>"/> - <input type="button" class="formbtns" value="Aliases" onclick="parent.location='suricata_select_alias.php?id=0&type=host|network&varname=address&act=import&multi_ip=yes&returl=<?=urlencode($_SERVER['PHP_SELF']);?>'" + title="<?=trim(filter_expand_alias($pconfig['address']));?>"/> + <input type="button" class="formbtns" value="Aliases" onclick="selectAlias();" title="<?php echo gettext("Select an existing IP alias");?>"/> </td> </tr> @@ -298,9 +318,10 @@ if ($savemsg) <input id="cancel" name="cancel" type="submit" class="formbtn" value="Cancel" /> </td> </tr> + </tbody> </table> </div> -</td></tr> +</td></tr></tbody> </table> </form> <script type="text/javascript"> @@ -326,6 +347,29 @@ function createAutoSuggest() { ?> } +function selectAlias() { + + var loc; + var fields = [ "name", "descr", "localnets", "wanips", "wangateips", "wandnsips", "vips", "vpnips", "address" ]; + + // Scrape current form field values and add to + // the select alias URL as a query string. + var loc = '/suricata/suricata_select_alias.php?id=<?=$id;?>&act=import&type=host|network'; + loc = loc + '&varname=address&multi_ip=yes'; + loc = loc + '&returl=<?=urlencode($_SERVER['PHP_SELF']);?>'; + loc = loc + '&uuid=<?=$passlist_uuid;?>'; + + // Iterate over just the specific form fields we want to pass to + // the select alias URL. + fields.forEach(function(entry) { + var tmp = $(entry).serialize(); + if (tmp.length > 0) + loc = loc + '&' + tmp; + }); + + window.parent.location = loc; +} + setTimeout("createAutoSuggest();", 500); </script> diff --git a/config/suricata/suricata_post_install.php b/config/suricata/suricata_post_install.php index eb193d58..7c8d03a5 100644 --- a/config/suricata/suricata_post_install.php +++ b/config/suricata/suricata_post_install.php @@ -51,7 +51,33 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $config, $g, $rebuild_rules, $pkg_interface, $suricata_gui_include; +/**************************************** + * Define any new constants here that * + * may not be yet defined in the old * + * "suricata.inc" include file that * + * might be cached and used by the * + * package manager installation code. * + * * + * This is a hack to work around the * + * fact the old version of suricata.inc * + * is cached and used instead of the * + * updated version icluded with the * + * updated GUI package. * + ****************************************/ +if (!defined('SID_MODS_PATH')) + define('SID_MODS_PATH', '/var/db/suricata/sidmods/'); +if (!defined('IPREP_PATH')) + define('IPREP_PATH', '/var/db/suricata/iprep/'); + +/**************************************** + * End of PHP cachine workaround * + ****************************************/ + +// Initialize some common values from defined constants $suricatadir = SURICATADIR; +$suricatalogdir = SURICATALOGDIR; +$flowbit_rules_file = FLOWBITS_FILENAME; +$suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; $rcdir = RCFILEPREFIX; // Hard kill any running Suricata process that may have been started by any @@ -73,47 +99,59 @@ if(is_process_running("barnyard")) { // Set flag for post-install in progress $g['suricata_postinstall'] = true; +// Mount file system read/write so we can modify some files +conf_mount_rw(); + // Remove any previously installed script since we rebuild it -@unlink("{$rcdir}/suricata.sh"); +@unlink("{$rcdir}suricata.sh"); // Create the top-tier log directory safe_mkdir(SURICATALOGDIR); -// remake saved settings +// Create the IP Rep and SID Mods lists directory +safe_mkdir(SID_MODS_PATH); +safe_mkdir(IPREP_PATH); + +// remake saved settings if previously flagged if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] == 'on') { log_error(gettext("[Suricata] Saved settings detected... rebuilding installation with saved settings...")); update_status(gettext("Saved settings detected...")); + /* Do one-time settings migration for new version configuration */ + update_output_window(gettext("Please wait... migrating settings to new configuration...")); + include('/usr/local/pkg/suricata/suricata_migrate_config.php'); update_output_window(gettext("Please wait... rebuilding installation with saved settings...")); log_error(gettext("[Suricata] Downloading and updating configured rule types...")); update_output_window(gettext("Please wait... downloading and updating configured rule types...")); if ($pkg_interface <> "console") $suricata_gui_include = true; - include('/usr/local/www/suricata/suricata_check_for_rule_updates.php'); + include('/usr/local/pkg/suricata/suricata_check_for_rule_updates.php'); update_status(gettext("Generating suricata.yaml configuration file from saved settings...")); $rebuild_rules = true; // Create the suricata.yaml files for each enabled interface $suriconf = $config['installedpackages']['suricata']['rule']; - foreach ($suriconf as $value) { - $if_real = get_real_interface($value['interface']); - - // ## 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", "tls-events.rules" ) as $r){ - if (!in_array($r, $rules)) - $rules[] = $r; - } - natcasesort($rules); - $value['rulesets'] = implode("||", $rules); - write_config(); - // ## end of BETA pkg bug fix-up ## - - // create a suricata.yaml file for interface - suricata_generate_yaml($value); + foreach ($suriconf as $suricatacfg) { + $if_real = get_real_interface($suricatacfg['interface']); + $suricata_uuid = $suricatacfg['uuid']; + $suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; + + // Pull in the PHP code that generates the suricata.yaml file + // variables that will be substituted further down below. + include("/usr/local/pkg/suricata/suricata_generate_yaml.php"); + + // Pull in the boilerplate template for the suricata.yaml + // configuration file. The contents of the template along + // with substituted variables are stored in $suricata_conf_text + // (which is defined in the included file). + include("/usr/local/pkg/suricata/suricata_yaml_template.inc"); + + // Now write out the conf file using $suricata_conf_text contents + @file_put_contents("{$suricatacfgdir}/suricata.yaml", $suricata_conf_text); + unset($suricata_conf_text); // create barnyard2.conf file for interface - if ($value['barnyard_enable'] == 'on') - suricata_generate_barnyard2_conf($value, $if_real); + if ($suricatacfg['barnyard_enable'] == 'on') + suricata_generate_barnyard2_conf($suricatacfg, $if_real); } // create Suricata bootup file suricata.sh @@ -128,10 +166,14 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = 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']; + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget']) && !empty($config['widgets']['sequence'])) { + if (strpos($config['widgets']['sequence'], "suricata_alerts-container") === FALSE) + $config['widgets']['sequence'] .= "," . $config['installedpackages']['suricata']['config'][0]['dashboard_widget']; + } + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows']) && !empty($config['widgets'])) { + if (empty($config['widgets']['widget_suricata_display_lines'])) + $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...")); @@ -142,14 +184,22 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = update_status(gettext("Starting Suricata using rebuilt configuration...")); update_output_window(gettext("Please wait... while Suricata is started...")); log_error(gettext("[Suricata] Starting Suricata using rebuilt configuration...")); - start_service("suricata"); + mwexec_bg("{$rcdir}suricata.sh start"); update_output_window(gettext("Suricata has been started using the rebuilt configuration...")); } } +// If this is first install and "forcekeepsettings" is empty, +// then default it to 'on'. +if (empty($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'])) + $config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = 'on'; + +// Finished with file system mods, so remount it read-only +conf_mount_ro(); + // Update Suricata package version in configuration -$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "v1.0.2"; -write_config(); +$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "2.0"; +write_config("Suricata pkg: updated GUI package version number."); // Done with post-install, so clear flag unset($g['suricata_postinstall']); diff --git a/config/suricata/suricata_rules.php b/config/suricata/suricata_rules.php index 82bb33eb..aa420371 100644 --- a/config/suricata/suricata_rules.php +++ b/config/suricata/suricata_rules.php @@ -41,7 +41,7 @@ require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); -global $g, $rebuild_rules; +global $g, $config, $rebuild_rules; $suricatadir = SURICATADIR; $rules_map = array(); @@ -107,9 +107,27 @@ $emergingdownload = $config['installedpackages']['suricata']['config'][0]['enabl $etpro = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; $categories = explode("||", $pconfig['rulesets']); -// Add any previously saved rules files to the categories array -if (!empty($pconfig['rulesets'])) - $categories = explode("||", $pconfig['rulesets']); +// Get any automatic rule category enable/disable modifications +// if auto-SID Mgmt is enabled, and adjust the available rulesets +// in the CATEGORY drop-down box as necessary. +$cat_mods = suricata_sid_mgmt_auto_categories($a_rule[$id], FALSE); +foreach ($cat_mods as $k => $v) { + switch ($v) { + case 'disabled': + if (($key = array_search($k, $categories)) !== FALSE) + unset($categories[$key]); + break; + + case 'enabled': + if (!in_array($k, $categories)) + $categories[] = $k; + break; + + default: + break; + } +} + if ($_GET['openruleset']) $currentruleset = htmlspecialchars($_GET['openruleset'], ENT_QUOTES | ENT_HTML401); @@ -148,7 +166,10 @@ if ($currentruleset != 'custom.rules') { $rules_map = suricata_load_rules_map($rulefile); } -/* Load up our enablesid and disablesid arrays with enabled or disabled SIDs */ +/* Process the current category rules through any auto SID MGMT changes if enabled */ +suricata_auto_sid_mgmt($rules_map, $a_rule[$id], FALSE); + +/* Load up our enablesid and disablesid arrays with manually enabled or disabled SIDs */ $enablesid = suricata_load_sid_mods($a_rule[$id]['rule_sid_on']); $disablesid = suricata_load_sid_mods($a_rule[$id]['rule_sid_off']); @@ -159,12 +180,16 @@ if ($_POST['toggle'] && is_numeric($_POST['sid']) && is_numeric($_POST['gid']) & $sid = $_POST['sid']; // See if the target SID is in our list of modified SIDs, - // and toggle it back to default if present; otherwise, + // and toggle it opposite state if present; otherwise, // add it to the appropriate modified SID list. - if (isset($enablesid[$gid][$sid])) + if (isset($enablesid[$gid][$sid])) { unset($enablesid[$gid][$sid]); - elseif (isset($disablesid[$gid][$sid])) + $disablesid[$gid][$sid] = "disablesid"; + } + elseif (isset($disablesid[$gid][$sid])) { unset($disablesid[$gid][$sid]); + $enablesid[$gid][$sid] = "enablesid"; + } else { if ($rules_map[$gid][$sid]['disabled'] == 1) $enablesid[$gid][$sid] = "enablesid"; @@ -198,8 +223,12 @@ if ($_POST['toggle'] && is_numeric($_POST['sid']) && is_numeric($_POST['gid']) & unset($a_rule[$id]['rule_sid_off']); /* Update the config.xml file. */ - write_config(); + write_config("Suricata pkg: modified state for rule {$gid}:{$sid} on {$a_rule[$id]['interface']}."); + // We changed a rule state, remind user to apply the changes + mark_subsystem_dirty('suricata_rules'); + + // Set a scroll-to anchor location $anchor = "rule_{$gid}_{$sid}"; } elseif ($_POST['disable_all'] && !empty($rules_map)) { @@ -238,7 +267,10 @@ elseif ($_POST['disable_all'] && !empty($rules_map)) { else unset($a_rule[$id]['rule_sid_off']); - write_config(); + // We changed a rule state, remind user to apply the changes + mark_subsystem_dirty('suricata_rules'); + + write_config("Suricata pkg: disabled all rules in category {$currentruleset} for {$a_rule[$id]['interface']}."); } elseif ($_POST['enable_all'] && !empty($rules_map)) { @@ -275,7 +307,10 @@ elseif ($_POST['enable_all'] && !empty($rules_map)) { else unset($a_rule[$id]['rule_sid_off']); - write_config(); + // We changed a rule state, remind user to apply the changes + mark_subsystem_dirty('suricata_rules'); + + write_config("Suricata pkg: enable all rules in category {$currentruleset} for {$a_rule[$id]['interface']}."); } elseif ($_POST['resetcategory'] && !empty($rules_map)) { @@ -314,7 +349,10 @@ elseif ($_POST['resetcategory'] && !empty($rules_map)) { else unset($a_rule[$id]['rule_sid_off']); - write_config(); + // We changed a rule state, remind user to apply the changes + mark_subsystem_dirty('suricata_rules'); + + write_config("Suricata pkg: remove enablesid/disablesid changes for category {$currentruleset} on {$a_rule[$id]['interface']}."); } elseif ($_POST['resetall'] && !empty($rules_map)) { @@ -322,51 +360,64 @@ elseif ($_POST['resetall'] && !empty($rules_map)) { unset($a_rule[$id]['rule_sid_on']); unset($a_rule[$id]['rule_sid_off']); + // We changed a rule state, remind user to apply the changes + mark_subsystem_dirty('suricata_rules'); + /* Update the config.xml file. */ - write_config(); + write_config("Suricata pkg: remove all enablesid/disablesid changes for {$a_rule[$id]['interface']}."); } elseif ($_POST['clear']) { unset($a_rule[$id]['customrules']); - write_config(); + write_config("Suricata pkg: clear all custom rules for {$a_rule[$id]['interface']}."); $rebuild_rules = true; + conf_mount_rw(); suricata_generate_yaml($a_rule[$id]); + conf_mount_ro(); $rebuild_rules = false; $pconfig['customrules'] = ''; } elseif ($_POST['cancel']) { $pconfig['customrules'] = base64_decode($a_rule[$id]['customrules']); + clear_subsystem_dirty('suricata_rules'); } elseif ($_POST['save']) { $pconfig['customrules'] = $_POST['customrules']; if ($_POST['customrules']) - $a_rule[$id]['customrules'] = base64_encode($_POST['customrules']); + $a_rule[$id]['customrules'] = base64_encode(str_replace("\r\n", "\n", $_POST['customrules'])); else unset($a_rule[$id]['customrules']); - write_config(); + write_config("Suricata pkg: save modified custom rules for {$a_rule[$id]['interface']}."); $rebuild_rules = true; + conf_mount_rw(); suricata_generate_yaml($a_rule[$id]); + conf_mount_ro(); $rebuild_rules = false; /* Signal Suricata to "live reload" the rules */ suricata_reload_config($a_rule[$id]); + clear_subsystem_dirty('suricata_rules'); } elseif ($_POST['apply']) { /* Save new configuration */ - write_config(); + write_config("Suricata pkg: new rules configuration for {$a_rule[$id]['interface']}."); /*************************************************/ /* Update the suricata.yaml file and rebuild the */ /* rules for this interface. */ /*************************************************/ $rebuild_rules = true; + conf_mount_rw(); suricata_generate_yaml($a_rule[$id]); + conf_mount_ro(); $rebuild_rules = false; /* Signal Suricata to "live reload" the rules */ suricata_reload_config($a_rule[$id]); + + // We have saved changes and done a soft restart, so clear "dirty" flag + clear_subsystem_dirty('suricata_rules'); } -require_once("guiconfig.inc"); include_once("head.inc"); $if_friendly = convert_friendly_interface_to_friendly_descr($pconfig['interface']); @@ -392,19 +443,27 @@ if ($savemsg) { <input type='hidden' name='openruleset' id='openruleset' value='<?=$currentruleset;?>'/> <input type='hidden' name='sid' id='sid' value=''/> <input type='hidden' name='gid' id='gid' value=''/> + +<?php if (is_subsystem_dirty('suricata_rules')): ?><p> +<?php print_info_box_np(gettext("A change has been made to a rule state.") . "<br/>" . gettext("Click APPLY when finished to send the changes to the running configuration."));?> +<?php endif; ?> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -422,6 +481,7 @@ if ($savemsg) { </td></tr> <tr><td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="4" cellspacing="0"> + <tbody> <tr> <td class="listtopic"><?php echo gettext("Available Rule Categories"); ?></td> </tr> @@ -430,7 +490,7 @@ if ($savemsg) { <select id="selectbox" name="selectbox" class="formselect" onChange="go();"> <option value='custom.rules'>custom.rules</option> <?php - $files = explode("||", $pconfig['rulesets']); + $files = $categories; if ($a_rule[$id]['ips_policy_enable'] == 'on') $files[] = "IPS Policy - " . ucfirst($a_rule[$id]['ips_policy']); if ($a_rule[$id]['autoflowbitrules'] == 'on') @@ -478,6 +538,7 @@ if ($savemsg) { <tr> <td class="vncell"> <table width="100%" align="center" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr> <td rowspan="5" width="48%" valign="middle"><input type="submit" name="apply" id="apply" value="<?php echo gettext("Apply"); ?>" class="formbtn" title="<?php echo gettext("Click to rebuild the rules with your changes"); ?>"/><br/><br/> @@ -534,6 +595,7 @@ if ($savemsg) { gettext("clicking here") . ".</a>";?></td> </tr> <?php endif;?> + </tbody> </table> </td> </tr> @@ -544,7 +606,7 @@ if ($savemsg) { <td> <table id="myTable" class="sortable" style="table-layout: fixed;" width="100%" border="0" cellpadding="0" cellspacing="0"> <colgroup> - <col width="14" align="left" valign="middle"> + <col width="16" align="center" valign="middle"> <col width="6%" align="center" axis="number"> <col width="9%" align="center" axis="number"> <col width="52" align="center" axis="string"> @@ -555,8 +617,8 @@ if ($savemsg) { <col axis="string"> </colgroup> <thead> - <tr> - <th class="list"> </th> + <tr class="sortableHeaderRowIdentifier"> + <th class="list sorttable_nosort"> </th> <th class="listhdrr"><?php echo gettext("GID"); ?></th> <th class="listhdrr"><?php echo gettext("SID"); ?></th> <th class="listhdrr"><?php echo gettext("Proto"); ?></th> @@ -570,18 +632,35 @@ if ($savemsg) { <tbody> <?php - $counter = $enable_cnt = $disable_cnt = 0; + $counter = $enable_cnt = $disable_cnt = $managed_count = 0; foreach ($rules_map as $k1 => $rulem) { foreach ($rulem as $k2 => $v) { $sid = suricata_get_sid($v['rule']); $gid = suricata_get_gid($v['rule']); - - if (isset($disablesid[$gid][$sid])) { + $ruleset = $currentruleset; + $style = ""; + + if ($v['managed'] == 1) { + if ($v['disabled'] == 1) { + $textss = "<span class=\"gray\">"; + $textse = "</span>"; + $style= "style=\"opacity: 0.4; filter: alpha(opacity=40);\""; + $title = gettext("Auto-disabled by settings on SID Mgmt tab"); + } + else { + $textss = $textse = ""; + $ruleset = "suricata.rules"; + $title = gettext("Auto-managed by settings on SID Mgmt tab"); + } + $iconb = "icon_advanced.gif"; + $managed_count++; + } + elseif (isset($disablesid[$gid][$sid])) { $textss = "<span class=\"gray\">"; $textse = "</span>"; $iconb = "icon_reject_d.gif"; $disable_cnt++; - $title = gettext("Disabled by user. Click to toggle to default state"); + $title = gettext("Disabled by user. Click to toggle to enabled state"); } elseif (($v['disabled'] == 1) && (!isset($enablesid[$gid][$sid]))) { $textss = "<span class=\"gray\">"; @@ -594,7 +673,7 @@ if ($savemsg) { $textss = $textse = ""; $iconb = "icon_reject.gif"; $enable_cnt++; - $title = gettext("Enabled by user. Click to toggle to default state"); + $title = gettext("Enabled by user. Click to toggle to disabled state"); } else { $textss = $textse = ""; @@ -623,36 +702,44 @@ if ($savemsg) { $message = suricata_get_msg($v['rule']); $sid_tooltip = gettext("View the raw text for this rule"); - echo "<tr><td class=\"listt\" align=\"left\" valign=\"middle\" sorttable_customkey=\"\">{$textss} - <a id=\"rule_{$gid}_{$sid}\" href='#'><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; - document.getElementById('gid').value='{$gid}';\" - src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" - title='{$title}' name=\"toggle[]\"/></a>{$textse} - </td> - <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + echo "<tr><td class=\"listt\" style=\"align:center;\" valign=\"middle\">{$textss}"; + + if ($v['managed'] == 1) { + echo "<img {$style} src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}'/>{$textse}"; + } + else { + echo "<a id=\"rule_{$gid}_{$sid}\" href='#'><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; + document.getElementById('gid').value='{$gid}';\" + src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}' name=\"toggle[]\"/></a>{$textse}"; + } + echo "</td> + + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$gid}{$textse} </td> - <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> <a href=\"javascript: void(0)\" - onclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\" + onclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\" title='{$sid_tooltip}'>{$textss}{$sid}{$textse}</a> </td> - <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$protocol}{$textse} </td> - <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$srcspan}{$source}</span> </td> - <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$srcprtspan}{$source_port}</span> </td> - <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$dstspan}{$destination}</span> </td> - <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$dstprtspan}{$destination_port}</span> </td> - <td class=\"listbg\" style=\"word-wrap:break-word; whitespace:pre-line;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> + <td class=\"listbg\" style=\"word-wrap:break-word; whitespace:pre-line;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$ruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$message}{$textse} </td> </tr>"; @@ -667,13 +754,15 @@ if ($savemsg) { <tr> <td> <table width="100%" border="0" cellspacing="0" cellpadding="1"> + <tbody> <tr> <td width="16"></td> <td class="vexpl" height="35" valign="top"> <strong><?php echo gettext("--- Category Rules Summary ---") . "</strong><br/>" . gettext("Total Rules: {$counter}") . " " . gettext("Enabled: {$enable_cnt}") . " " . - gettext("Disabled: {$disable_cnt}"); ?></td> + gettext("Disabled: {$disable_cnt}") . " " . + gettext("Auto-Managed: {$managed_count}"); ?></td> </tr> <tr> <td width="16"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" @@ -695,14 +784,29 @@ if ($savemsg) { width="11" height="11"></td> <td nowrap><?php echo gettext("Rule changed to Disabled by user"); ?></td> </tr> + <?php if (!empty($cat_mods)): ?> + <tr> + <td width="16"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_advanced.gif" + width="11" height="11"></td> + <td nowrap><?php echo gettext("Rule auto-enabled by files configured on SID Mgmt tab"); ?></td> + </tr> + <tr> + <td width="16"><img style="opacity: 0.4; filter: alpha(opacity=40);" src="../themes/<?= $g['theme']; ?>/images/icons/icon_advanced.gif" + width="11" height="11"></td> + <td nowrap><?php echo gettext("Rule auto-disabled by files configured on SID Mgmt tab"); ?></td> + </tr> + <?php endif; ?> + </tbody> </table> </td> </tr> <?php endif;?> + </tbody> </table> </div> </td> </tr> + </tbody> </table> </form> <script language="javascript" type="text/javascript"> diff --git a/config/suricata/suricata_rules_edit.php b/config/suricata/suricata_rules_edit.php index 0a4bd62a..8329272f 100644 --- a/config/suricata/suricata_rules_edit.php +++ b/config/suricata/suricata_rules_edit.php @@ -73,6 +73,8 @@ $wrap_flag = "off"; // Correct displayed file title if necessary if ($file == "Auto-Flowbit Rules") $displayfile = FLOWBITS_FILENAME; +elseif ($file == "suricata.rules") + $displayfile = "Currently Active Rules"; else $displayfile = $file; @@ -102,6 +104,8 @@ elseif (isset($_GET['sid']) && is_numericint($_GET['sid']) && isset($_GET['gid'] // If flowbit rule, point to interface-specific file if ($file == "Auto-Flowbit Rules") $rules_map = suricata_load_rules_map("{$suricatacfgdir}rules/" . FLOWBITS_FILENAME); + elseif ($file == "suricata.rules") + $rules_map = suricata_load_rules_map("{$suricatacfgdir}rules/suricata.rules"); else $rules_map = suricata_load_rules_map("{$suricatadir}rules/{$file}"); $contents = $rules_map[$_GET['gid']][trim($_GET['sid'])]['rule']; diff --git a/config/suricata/suricata_rules_flowbits.php b/config/suricata/suricata_rules_flowbits.php index 8d0fd5d3..b16353cb 100644 --- a/config/suricata/suricata_rules_flowbits.php +++ b/config/suricata/suricata_rules_flowbits.php @@ -159,7 +159,6 @@ include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC" > - <?php include("fbegin.inc"); if ($input_errors) print_input_errors($input_errors); @@ -227,7 +226,7 @@ if ($savemsg) <col axis="string"> </colgroup> <thead> - <tr> + <tr class="sortableHeaderRowIdentifier"> <th class="listhdrr" axis="number"><?php echo gettext("SID"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Proto"); ?></th> <th class="listhdrr" axis="string"><?php echo gettext("Source"); ?></th> @@ -274,7 +273,7 @@ if ($savemsg) // Use "echo" to write the table HTML row-by-row. echo "<tr>" . - "<td class=\"listr\" sorttable_customkey=\"{$sid}\">{$sid} {$supplink}</td>" . + "<td class=\"listr\" style=\"sorttable_customkey:{$sid};\" sorttable_customkey=\"{$sid}\">{$sid} {$supplink}</td>" . "<td class=\"listr\" style=\"text-align:center;\">{$protocol}</td>" . "<td class=\"listr ellipsis\" nowrap style=\"text-align:center;\"><span title=\"{$rule_content[2]}\">{$source}</span></td>" . "<td class=\"listr ellipsis\" nowrap style=\"text-align:center;\"><span title=\"{$rule_content[5]}\">{$destination}</span></td>" . diff --git a/config/suricata/suricata_rulesets.php b/config/suricata/suricata_rulesets.php index c939ef25..ce32af20 100644 --- a/config/suricata/suricata_rulesets.php +++ b/config/suricata/suricata_rulesets.php @@ -47,7 +47,7 @@ $suricatadir = SURICATADIR; $flowbit_rules_file = FLOWBITS_FILENAME; // Array of default events rules for Suricata -$default_rules = array( "decoder-events.rules", "files.rules", "http-events.rules", +$default_rules = array( "decoder-events.rules", "dns-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ); if (!is_array($config['installedpackages']['suricata']['rule'])) { @@ -63,15 +63,12 @@ if (is_null($id)) $id = 0; if (isset($id) && $a_nat[$id]) { - $pconfig['enable'] = $a_nat[$id]['enable']; - $pconfig['interface'] = $a_nat[$id]['interface']; - $pconfig['rulesets'] = $a_nat[$id]['rulesets']; - $pconfig['autoflowbitrules'] = $a_nat[$id]['autoflowbitrules']; + $pconfig['autoflowbits'] = $a_nat[$id]['autoflowbitrules']; $pconfig['ips_policy_enable'] = $a_nat[$id]['ips_policy_enable']; $pconfig['ips_policy'] = $a_nat[$id]['ips_policy']; } -$if_real = get_real_interface($pconfig['interface']); +$if_real = get_real_interface($a_nat[$id]['interface']); $suricata_uuid = $a_nat[$id]['uuid']; $snortdownload = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules'] == 'on' ? 'on' : 'off'; $emergingdownload = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules'] == 'on' ? 'on' : 'off'; @@ -81,6 +78,8 @@ $snortcommunitydownload = $config['installedpackages']['suricata']['config'][0][ $no_emerging_files = false; $no_snort_files = false; +$enabled_rulesets_array = explode("||", $a_nat[$id]['rulesets']); + /* Test rule categories currently downloaded to $SURICATADIR/rules and set appropriate flags */ if ($emergingdownload == 'on') { $test = glob("{$suricatadir}rules/" . ET_OPEN_FILE_PREFIX . "*.rules"); @@ -147,81 +146,73 @@ if ($_POST["save"]) { @unlink("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}"); } - write_config(); + write_config("Suricata pkg: save enabled rule categories for {$a_nat[$id]['interface']}."); /*************************************************/ /* Update the suricata.yaml file and rebuild the */ /* rules for this interface. */ /*************************************************/ $rebuild_rules = true; + conf_mount_rw(); suricata_generate_yaml($a_nat[$id]); + conf_mount_ro(); $rebuild_rules = false; /* Signal Suricata to "live reload" the rules */ suricata_reload_config($a_nat[$id]); + + $pconfig = $_POST; + $enabled_rulesets_array = explode("||", $enabled_items); + if (suricata_is_running($suricata_uuid, $if_real)) + $savemsg = gettext("Suricata is 'live-loading' the new rule set on this interface."); } elseif ($_POST['unselectall']) { // Remove all but the default events and files rules - $a_nat[$id]['rulesets'] = implode("||", $default_rules); - - if ($_POST['ips_policy_enable'] == "on") { - $a_nat[$id]['ips_policy_enable'] = 'on'; - $a_nat[$id]['ips_policy'] = $_POST['ips_policy']; - } - else { - $a_nat[$id]['ips_policy_enable'] = 'off'; - unset($a_nat[$id]['ips_policy']); - } + $enabled_rulesets_array = array(); + $enabled_rulesets_array = implode("||", $default_rules); - write_config(); - sync_suricata_package_config(); + $savemsg = gettext("All rule categories have been de-selected. "); + if ($_POST['ips_policy_enable']) + $savemsg .= gettext("Only the rules included in the selected IPS Policy will be used."); + else + $savemsg .= gettext("There currently are no inspection rules enabled for this Suricata instance!"); } elseif ($_POST['selectall']) { // Start with the required default events and files rules - $rulesets = $default_rules; - - if ($_POST['ips_policy_enable'] == "on") { - $a_nat[$id]['ips_policy_enable'] = 'on'; - $a_nat[$id]['ips_policy'] = $_POST['ips_policy']; - } - else { - $a_nat[$id]['ips_policy_enable'] = 'off'; - unset($a_nat[$id]['ips_policy']); - } + $enabled_rulesets_array = $default_rules; if ($emergingdownload == 'on') { $files = glob("{$suricatadir}rules/" . ET_OPEN_FILE_PREFIX . "*.rules"); foreach ($files as $file) - $rulesets[] = basename($file); + $enabled_rulesets_array[] = basename($file); } elseif ($etpro == 'on') { $files = glob("{$suricatadir}rules/" . ET_PRO_FILE_PREFIX . "*.rules"); foreach ($files as $file) - $rulesets[] = basename($file); + $enabled_rulesets_array[] = basename($file); } if ($snortcommunitydownload == 'on') { $files = glob("{$suricatadir}rules/" . GPL_FILE_PREFIX . "community.rules"); foreach ($files as $file) - $rulesets[] = basename($file); + $enabled_rulesets_array[] = basename($file); } /* Include the Snort VRT rules only if enabled and no IPS policy is set */ - if ($snortdownload == 'on' && $a_nat[$id]['ips_policy_enable'] == 'off') { + if ($snortdownload == 'on' && empty($_POST['ips_policy_enable'])) { $files = glob("{$suricatadir}rules/" . VRT_FILE_PREFIX . "*.rules"); foreach ($files as $file) - $rulesets[] = basename($file); + $enabled_rulesets_array[] = basename($file); } - - $a_nat[$id]['rulesets'] = implode("||", $rulesets); - - write_config(); - sync_suricata_package_config(); } +// Get any automatic rule category enable/disable modifications +// if auto-SID Mgmt is enabled. +$cat_mods = suricata_sid_mgmt_auto_categories($a_nat[$id], FALSE); + // See if we have any Auto-Flowbit rules and enable // the VIEW button if we do. -if ($a_nat[$id]['autoflowbitrules'] == 'on') { +if ($pconfig['autoflowbits'] == 'on') { if (file_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") && filesize("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") > 0) { $btn_view_flowb_rules = " title=\"" . gettext("View flowbit-required rules") . "\""; @@ -232,9 +223,7 @@ if ($a_nat[$id]['autoflowbitrules'] == 'on') { else $btn_view_flowb_rules = " disabled"; -$enabled_rulesets_array = explode("||", $a_nat[$id]['rulesets']); - -$if_friendly = convert_friendly_interface_to_friendly_descr($pconfig['interface']); +$if_friendly = convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface']); $pgtitle = gettext("Suricata IDS: Interface {$if_friendly} - Categories"); include_once("head.inc"); ?> @@ -258,18 +247,21 @@ if ($savemsg) { <form action="suricata_rulesets.php" method="post" name="iform" id="iform"> <input type="hidden" name="id" id="id" value="<?=$id;?>" /> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -289,6 +281,7 @@ if ($savemsg) { <td> <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <?php $isrulesfolderempty = glob("{$suricatadir}rules/*.rules"); $iscfgdirempty = array(); @@ -307,18 +300,19 @@ if ($savemsg) { <?php else: ?> <tr> <td> - <table width="100%" border="0" - cellpadding="0" cellspacing="0"> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr> <td colspan="4" class="listtopic"><?php echo gettext("Automatic flowbit resolution"); ?><br/></td> </tr> <tr> - <td colspan="4" valign="center" class="listn"> + <td colspan="4" style="vertical-align: middle;" class="listn"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td width="15%" class="listn"><?php echo gettext("Resolve Flowbits"); ?></td> <td width="85%"><input name="autoflowbits" id="autoflowbitrules" type="checkbox" value="on" - <?php if ($a_nat[$id]['autoflowbitrules'] == "on" || empty($a_nat[$id]['autoflowbitrules'])) echo "checked"; ?>/> + <?php if ($pconfig['autoflowbits'] == "on" || empty($pconfig['autoflowbits'])) echo "checked"; ?>/> <span class="vexpl"><?php echo gettext("If checked, Suricata will auto-enable rules required for checked flowbits. "); echo gettext("The Default is "); ?><strong><?php echo gettext("Checked."); ?></strong></span></td> </tr> @@ -340,6 +334,7 @@ if ($savemsg) { <?php echo "<span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . gettext("Auto-enabled rules generating unwanted alerts should have their GID:SID added to the Suppression List for the interface."); ?> <br/></td> </tr> + </tbody> </table> </td> </tr> @@ -349,8 +344,9 @@ if ($savemsg) { <td colspan="4" class="listtopic"><?php echo gettext("Snort IPS Policy selection"); ?><br/></td> </tr> <tr> - <td colspan="4" valign="center" class="listn"> + <td colspan="4" style="vertical-align: middle;" class="listn"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> <tr> <td width="15%" class="listn"><?php echo gettext("Use IPS Policy"); ?></td> <td width="85%"><input name="ips_policy_enable" id="ips_policy_enable" type="checkbox" value="on" <?php if ($a_nat[$id]['ips_policy_enable'] == "on") echo "checked"; ?> @@ -365,7 +361,9 @@ if ($savemsg) { "although Emerging Threats categories may still be selected if enabled on the Global Settings tab. " . "These will be added to the pre-defined Snort IPS policy rules from the Snort VRT."); ?><br/></td> </tr> - <tr id="ips_row1"> + </tbody> + <tbody id="ips_controls"> + <tr> <td width="15%" class="listn"><?php echo gettext("IPS Policy Selection"); ?></td> <td width="85%"><select name="ips_policy" class="formselect" <?=$policy_select_disable?> > <option value="connectivity" <?php if ($pconfig['ips_policy'] == "connected") echo "selected"; ?>><?php echo gettext("Connectivity"); ?></option> @@ -374,7 +372,7 @@ if ($savemsg) { </select> <span class="vexpl"><?php echo gettext("Snort IPS policies are: Connectivity, Balanced or Security."); ?></span></td> </tr> - <tr id="ips_row2"> + <tr> <td width="15%"> </td> <td width="85%"> <?php echo gettext("Connectivity blocks most major threats with few or no false positives. " . @@ -383,6 +381,7 @@ if ($savemsg) { "Security is a stringent policy. It contains everything in the first two " . "plus policy-type rules such as Flash in an Excel file."); ?><br/></td> </tr> + </tbody> </table> </td> </tr> @@ -392,15 +391,27 @@ if ($savemsg) { </tr> <tr> <td colspan="4"> - <table width=90% align="center" border="0" cellpadding="2" cellspacing="0"> - <tr height="45px"> - <td valign="middle"><input value="Select All" class="formbtns" type="submit" name="selectall" id="selectall" title="<?php echo gettext("Add all to enforcing rules"); ?>"/></td> - <td valign="middle"><input value="Unselect All" class="formbtns" type="submit" name="unselectall" id="unselectall" title="<?php echo gettext("Remove all from enforcing rules"); ?>"/></td> - <td valign="middle"><input value=" Save " class="formbtns" type="submit" name="save" id="save" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> - <td valign="middle"><span class="vexpl"><?php echo gettext("Click to save changes and auto-resolve flowbit rules (if option is selected above)"); ?></span></td> + <table width="95%" style="margin-left: auto; margin-right: auto;" border="0" cellpadding="2" cellspacing="0"> + <tbody> + <tr height="32px"> + <td style="vertical-align: middle;"><input value="Select All" class="formbtns" type="submit" name="selectall" id="selectall" title="<?php echo gettext("Add all to enforcing rules"); ?>"/></td> + <td style="vertical-align: middle;"><input value="Unselect All" class="formbtns" type="submit" name="unselectall" id="unselectall" title="<?php echo gettext("Remove all from enforcing rules"); ?>"/></td> + <td style="vertical-align: middle;"><input value=" Save " class="formbtns" type="submit" name="save" id="save" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> + <td style="vertical-align: middle;"><span class="vexpl"><?php echo gettext("Click to save changes and auto-resolve flowbit rules (if option is selected above)"); ?></span></td> + </tr> + <?php if (!empty($cat_mods)): ?> + <tr height="20px"> + <td colspan="4" style="vertical-align: middle;"><img style="vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext("- Category is auto-enabled by SID Mgmt conf files");?> + <img style="opacity: 0.4; filter: alpha(opacity=40); vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext("- Category is auto-disabled by SID Mgmt conf files");?></td> </tr> + <?php endif; ?> + </tbody> </table> + </td> </tr> + <?php if ($no_community_files) $msg_community = "NOTE: Snort Community Rules have not been downloaded. Perform a Rules Update to enable them."; else @@ -412,15 +423,29 @@ if ($savemsg) { <td width="5%" class="listhdrr"><?php echo gettext("Enabled"); ?></td> <td colspan="5" class="listhdrr"><?php echo gettext('Ruleset: Snort GPLv2 Community Rules');?></td> </tr> - <?php if (in_array($community_rules_file, $enabled_rulesets_array)): ?> + <?php if (isset($cat_mods[$community_rules_file])): ?> + <?php if ($cat_mods[$community_rules_file] == 'enabled') : ?> + <tr> + <td width="5%" class="listr" style="text-align: center;"> + <img src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" title="<?=gettext("Auto-managed by settings on SID Mgmt tab");?>" /></td> + <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?=gettext("{$msg_community}");?></a></td> + </tr> + <?php else: ?> + <tr> + <td width="5%" class="listr" style="text-align: center;"> + <img style="opacity: 0.4; filter: alpha(opacity=40);" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" title="<?=gettext("Auto-managed by settings on SID Mgmt tab");?>" /></td> + <td colspan="5" class="listr"><?=gettext("{$msg_community}"); ?></td> + </tr> + <?php endif; ?> + <?php elseif (in_array($community_rules_file, $enabled_rulesets_array)): ?> <tr> - <td width="5" class="listr" align="center" valign="top"> + <td width="5%" class="listr" style="text-align: center;"> <input type="checkbox" name="toenable[]" value="<?=$community_rules_file;?>" checked="checked"/></td> <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?php echo gettext("{$msg_community}"); ?></a></td> </tr> <?php else: ?> <tr> - <td width="5" class="listr" align="center" valign="top"> + <td width="5%" class="listr" style="text-align: center;"> <input type="checkbox" name="toenable[]" value="<?=$community_rules_file;?>" <?php if ($snortcommunitydownload == 'off') echo "disabled"; ?>/></td> <td colspan="5" class="listr"><?php echo gettext("{$msg_community}"); ?></td> </tr> @@ -438,19 +463,19 @@ if ($savemsg) { ?> <tr id="frheader"> <?php if ($emergingdownload == 'on' && !$no_emerging_files): ?> - <td width="5%" class="listhdrr" align="center"><?php echo gettext("Enabled"); ?></td> + <td width="5%" class="listhdrr" style="text-align: center;"><?php echo gettext("Enabled"); ?></td> <td width="45%" class="listhdrr"><?php echo gettext('Ruleset: ET Open Rules');?></td> <?php elseif ($etpro == 'on' && !$no_emerging_files): ?> - <td width="5%" class="listhdrr" align="center"><?php echo gettext("Enabled"); ?></td> + <td width="5%" class="listhdrr" style="text-align: center;"><?php echo gettext("Enabled"); ?></td> <td width="45%" class="listhdrr"><?php echo gettext('Ruleset: ET Pro Rules');?></td> <?php else: ?> - <td colspan="2" align="center" width="50%" class="listhdrr"><?php echo gettext("{$et_type} rules {$msg_emerging}"); ?></td> + <td colspan="2" style="text-align: center;" width="50%" class="listhdrr"><?php echo gettext("{$et_type} rules {$msg_emerging}"); ?></td> <?php endif; ?> <?php if ($snortdownload == 'on' && !$no_snort_files): ?> - <td width="5%" class="listhdrr" align="center"><?php echo gettext("Enabled"); ?></td> + <td width="5%" class="listhdrr" style="text-align: center;"><?php echo gettext("Enabled"); ?></td> <td width="45%" class="listhdrr"><?php echo gettext('Ruleset: Snort VRT Rules');?></td> <?php else: ?> - <td colspan="2" align="center" width="50%" class="listhdrr"><?php echo gettext("Snort VRT rules {$msg_snort}"); ?></td> + <td colspan="2" style="text-align: center;" width="50%" class="listhdrr"><?php echo gettext("Snort VRT rules {$msg_snort}"); ?></td> <?php endif; ?> </tr> <?php @@ -482,15 +507,28 @@ if ($savemsg) { echo "<tr>\n"; if (!empty($emergingrules[$j])) { $file = $emergingrules[$j]; - echo "<td width='5%' class='listr' align=\"center\" valign=\"top\">"; + echo "<td width='5%' class='listr' align=\"center\">"; if(is_array($enabled_rulesets_array)) { - if(in_array($file, $enabled_rulesets_array)) + if(in_array($file, $enabled_rulesets_array) && !isset($cat_mods[$file])) $CHECKED = " checked=\"checked\""; else $CHECKED = ""; } else $CHECKED = ""; - echo " \n<input type='checkbox' name='toenable[]' value='$file' {$CHECKED} />\n"; + if (isset($cat_mods[$file])) { + if (in_array($file, $enabled_rulesets_array)) + echo "<input type='hidden' name='toenable[]' value='{$file}' />\n"; + if ($cat_mods[$file] == 'enabled') { + $CHECKED = "enabled"; + echo " \n<img src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-enabled by settings on SID Mgmt tab") . "\" />\n"; + } + else { + echo " \n<img style=\"opacity: 0.4; filter: alpha(opacity=40);\" src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-disabled by settings on SID Mgmt tab") . "\" />\n"; + } + } + else { + echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + } echo "</td>\n"; echo "<td class='listr' width='45%' >\n"; if (empty($CHECKED)) @@ -503,17 +541,30 @@ if ($savemsg) { if (!empty($snortrules[$j])) { $file = $snortrules[$j]; - echo "<td class='listr' width='5%' align=\"center\" valign=\"top\">"; + echo "<td class='listr' width='5%' align=\"center\">"; if(is_array($enabled_rulesets_array)) { if (!empty($disable_vrt_rules)) $CHECKED = $disable_vrt_rules; - elseif(in_array($file, $enabled_rulesets_array)) + elseif(in_array($file, $enabled_rulesets_array) && !isset($cat_mods[$file])) $CHECKED = " checked=\"checked\""; else $CHECKED = ""; } else $CHECKED = ""; - echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + if (isset($cat_mods[$file])) { + if (in_array($file, $enabled_rulesets_array)) + echo "<input type='hidden' name='toenable[]' value='{$file}' />\n"; + if ($cat_mods[$file] == 'enabled') { + $CHECKED = "enabled"; + echo " \n<img src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-enabled by settings on SID Mgmt tab") . "\" />\n"; + } + else { + echo " \n<img style=\"opacity: 0.4; filter: alpha(opacity=40);\" src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-disabled by settings on SID Mgmt tab") . "\" />\n"; + } + } + else { + echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + } echo "</td>\n"; echo "<td class='listr' width='45%' >\n"; if (empty($CHECKED) || $CHECKED == "disabled") @@ -526,21 +577,30 @@ if ($savemsg) { echo "</tr>\n"; } ?> - </table> + </tbody> + </table> </td> </tr> -<tr> -<td colspan="4" class="vexpl"> <br/></td> -</tr> - <tr> - <td colspan="4" align="center" valign="middle"> - <input value="Save" type="submit" name="save" id="save" class="formbtn" title=" <?php echo gettext("Click to Save changes and rebuild rules"); ?>"/></td> - </tr> + <?php if (!empty($cat_mods)): ?> + <tr> + <td colspan="4" style="vertical-align: middle;"><br/> + <img style="vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext(" - Category auto-enabled by parameters in SID Mgmt conf files");?><br/> + <img style="opacity: 0.4; filter: alpha(opacity=40); vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext(" - Category auto-disabled by parameters in SID Mgmt conf files");?><br/><br/></td> + </tr> + <?php endif; ?> + <tr height="32px"> + <td colspan="4" style="vertical-align: bottom; text-align: center;"> + <input value="Save" type="submit" name="save" id="save" class="formbtn" title=" <?php echo gettext("Click to Save changes and rebuild rules"); ?>"/></td> + </tr> <?php endif; ?> +</tbody> </table> </div> </td> </tr> +</tbody> </table> </form> <?php @@ -566,28 +626,29 @@ h += 96; function enable_change() { - var endis = !(document.iform.ips_policy_enable.checked); - document.iform.ips_policy.disabled=endis; - - if (endis) { - document.getElementById("ips_row1").style.display="none"; - document.getElementById("ips_row2").style.display="none"; - document.getElementById("ips_col1").className="vexpl"; - document.getElementById("ips_col2").className="vexpl"; - } - else { - document.getElementById("ips_row1").style.display="table-row"; - document.getElementById("ips_row2").style.display="table-row"; - document.getElementById("ips_col1").className="vncell"; - document.getElementById("ips_col2").className="vtable"; - } - for (var i = 0; i < document.iform.elements.length; i++) { - if (document.iform.elements[i].type == 'checkbox') { - var str = document.iform.elements[i].value; - if (str.substr(0,6) == "snort_") - document.iform.elements[i].disabled = !(endis); - } - } + + if (document.getElementById("ips_policy_enable")) { + var endis = !(document.iform.ips_policy_enable.checked); + document.iform.ips_policy.disabled=endis; + + if (endis) { + document.getElementById("ips_controls").style.display="none"; + document.getElementById("ips_col1").className=""; + document.getElementById("ips_col2").className=""; + } + else { + document.getElementById("ips_controls").style.display=""; + document.getElementById("ips_col1").className="vncell"; + document.getElementById("ips_col2").className="vtable"; + } + } + for (var i = 0; i < document.iform.elements.length; i++) { + if (document.iform.elements[i].type == 'checkbox') { + var str = document.iform.elements[i].value; + if (str.substr(0,6) == "snort_") + document.iform.elements[i].disabled = !(endis); + } + } } // Set initial state of dynamic HTML form controls diff --git a/config/suricata/suricata_select_alias.php b/config/suricata/suricata_select_alias.php index c11802c2..47bbec4a 100644 --- a/config/suricata/suricata_select_alias.php +++ b/config/suricata/suricata_select_alias.php @@ -153,8 +153,8 @@ include("head.inc"); <col width="35%" align="left" axis="string"> </colgroup> <thead> - <tr> - <th class="listhdrr"></th> + <tr class="sortableHeaderRowIdentifier"> + <th class="listhdrr sorttable_nosort"></th> <th class="listhdrr" axis="string"><?=gettext("Alias Name"); ?></th> <th class="listhdrr" axis="string"><?=gettext("Values"); ?></th> <th class="listhdrr" axis="string"><?=gettext("Description"); ?></th> diff --git a/config/suricata/suricata_sid_mgmt.php b/config/suricata/suricata_sid_mgmt.php new file mode 100644 index 00000000..c69a9fcd --- /dev/null +++ b/config/suricata/suricata_sid_mgmt.php @@ -0,0 +1,597 @@ +<?php +/* + * suricata_sid_mgmt.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * All rights reserved. + * + * 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. + */ + +require_once("guiconfig.inc"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +global $g, $config, $rebuild_rules; + +$suricatadir = SURICATADIR; +$pconfig = array(); + +// Grab saved settings from configuration +if (!is_array($config['installedpackages']['suricata']['rule'])) + $config['installedpackages']['suricata']['rule'] = array(); +$a_nat = &$config['installedpackages']['suricata']['rule']; + +$pconfig['auto_manage_sids'] = $config['installedpackages']['suricata']['config'][0]['auto_manage_sids']; + +// Hard-code the path where SID Mods Lists are stored +// and disregard any user-supplied path element. +$sidmods_path = SID_MODS_PATH; + +// Set default to not show SID modification lists editor controls +$sidmodlist_edit_style = "display: none;"; + +if (!empty($_POST)) + $pconfig = $_POST; + +function suricata_is_sidmodslist_active($sidlist) { + + /***************************************************** + * This function checks all the configured Suricata * + * interfaces to see if the passed SID Mods List is * + * used by an interface. * + * * + * Returns: TRUE if List is in use * + * FALSE if List is not in use * + *****************************************************/ + + global $g, $config; + + if (!is_array($config['installedpackages']['suricata']['rule'])) + return FALSE; + + foreach ($config['installedpackages']['suricata']['rule'] as $rule) { + if ($rule['enable_sid_file'] == $sidlist) { + return TRUE; + } + if ($rule['disable_sid_file'] == $sidlist) { + return TRUE; + } + if ($rule['modify_sid_file'] == $sidlist) { + return TRUE; + } + } + return FALSE; +} + +if (isset($_POST['upload'])) { + if ($_FILES["sidmods_fileup"]["error"] == UPLOAD_ERR_OK) { + $tmp_name = $_FILES["sidmods_fileup"]["tmp_name"]; + $name = basename($_FILES["sidmods_fileup"]["name"]); + move_uploaded_file($tmp_name, "{$sidmods_path}{$name}"); + } + else + $input_errors[] = gettext("Failed to upload file {$_FILES["sidmods_fileup"]["name"]}"); +} + +if (isset($_POST['sidlist_delete']) && isset($_POST['sidlist_fname'])) { + if (!suricata_is_sidmodslist_active(basename($_POST['sidlist_fname']))) + unlink_if_exists($sidmods_path . basename($_POST['sidlist_fname'])); + else + $input_errors[] = gettext("This SID Mods List is currently assigned to an interface and cannot be deleted."); +} + +if (isset($_POST['sidlist_edit']) && isset($_POST['sidlist_fname'])) { + $file = $sidmods_path . basename($_POST['sidlist_fname']); + $data = file_get_contents($file); + if ($data !== FALSE) { + $sidmodlist_data = htmlspecialchars($data); + $sidmodlist_edit_style = "display: table-row-group;"; + $sidmodlist_name = basename($_POST['sidlist_fname']); + unset($data); + } + else { + $input_errors[] = gettext("An error occurred reading the file."); + } +} + +if (isset($_POST['save']) && isset($_POST['sidlist_data'])) { + if (strlen(basename($_POST['sidlist_name'])) > 0) { + $file = $sidmods_path . basename($_POST['sidlist_name']); + $data = str_replace("\r\n", "\n", $_POST['sidlist_data']); + file_put_contents($file, $data); + unset($data); + } + else { + $input_errors[] = gettext("You must provide a valid filename for the SID Mods List."); + $sidmodlist_edit_style = "display: table-row-group;"; + } +} + +if (isset($_POST['save_auto_sid_conf'])) { + $config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] = $pconfig['auto_manage_sids'] ? "on" : "off"; + + // Grab the SID Mods config for the interfaces from the form's controls array + foreach ($_POST['sid_state_order'] as $k => $v) { + $a_nat[$k]['sid_state_order'] = $v; + } + foreach ($_POST['enable_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['enable_sid_file']); + continue; + } + $a_nat[$k]['enable_sid_file'] = $v; + } + foreach ($_POST['disable_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['disable_sid_file']); + continue; + } + $a_nat[$k]['disable_sid_file'] = $v; + } + foreach ($_POST['modify_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['modify_sid_file']); + continue; + } + $a_nat[$k]['modify_sid_file'] = $v; + } + + // Write the new configuration + write_config("Suricata pkg: updated automatic SID management settings."); + + $intf_msg = ""; + + // If any interfaces were marked for restart, then do it + if (is_array($_POST['torestart'])) { + foreach ($_POST['torestart'] as $k) { + // Update the suricata.yaml file and + // rebuild rules for this interface. + $rebuild_rules = true; + conf_mount_rw(); + suricata_generate_yaml($a_nat[$k]); + conf_mount_ro(); + $rebuild_rules = false; + + // Signal Suricata to "live reload" the rules + suricata_reload_config($a_nat[$k]); + + $intf_msg .= convert_friendly_interface_to_friendly_descr($a_nat[$k]['interface']) . ", "; + } + $savemsg = gettext("Changes were applied to these interfaces: " . trim($intf_msg, ' ,') . " and Suricata signaled to live-load the new rules."); + } +} + +if (isset($_POST['sidlist_dnload']) && isset($_POST['sidlist_fname'])) { + $file = $sidmods_path . basename($_POST['sidlist_fname']); + if (file_exists($file)) { + ob_start(); //important or other posts will fail + if (isset($_SERVER['HTTPS'])) { + header('Pragma: '); + header('Cache-Control: '); + } else { + header("Pragma: private"); + header("Cache-Control: private, must-revalidate"); + } + header("Content-Type: application/octet-stream"); + header("Content-length: " . filesize($file)); + header("Content-disposition: attachment; filename = " . basename($file)); + ob_end_clean(); //important or other post will fail + readfile($file); + } + else + $savemsg = gettext("Unable to locate the file specified!"); +} + +if (isset($_POST['sidlist_dnload_all_x'])) { + $save_date = exec('/bin/date "+%Y-%m-%d-%H-%M-%S"'); + $file_name = "suricata_sid_conf_files_{$save_date}.tar.gz"; + exec("cd {$sidmods_path} && /usr/bin/tar -czf /tmp/{$file_name} *"); + + if (file_exists("/tmp/{$file_name}")) { + ob_start(); //important or other posts will fail + if (isset($_SERVER['HTTPS'])) { + header('Pragma: '); + header('Cache-Control: '); + } else { + header("Pragma: private"); + header("Cache-Control: private, must-revalidate"); + } + header("Content-Type: application/octet-stream"); + header("Content-length: " . filesize("/tmp/{$file_name}")); + header("Content-disposition: attachment; filename = {$file_name}"); + ob_end_clean(); //important or other post will fail + readfile("/tmp/{$file_name}"); + + // Clean up the temp file + @unlink("/tmp/{$file_name}"); + } + else + $savemsg = gettext("An error occurred while creating the gzip archive!"); +} + +// Get all files in the SID Mods Lists sub-directory as an array +// Leave this as the last thing before spewing the page HTML +// so we can pick up any changes made to files in code above. +$sidmodfiles = return_dir_as_array($sidmods_path); +$sidmodselections = array_merge(Array( "None" ), $sidmodfiles); + +$pgtitle = gettext("Suricata: SID Management"); +include_once("head.inc"); + +?> + +<body link="#000000" vlink="#000000" alink="#000000"> + +<?php +include_once("fbegin.inc"); + +/* Display Alert message, under form tag or no refresh */ +if ($input_errors) + print_input_errors($input_errors); +?> + +<form action="suricata_sid_mgmt.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> +<input type="hidden" name="MAX_FILE_SIZE" value="100000000" /> +<input type="hidden" name="sidlist_fname" id="sidlist_fname" value=""/> + +<?php +if ($savemsg) { + /* Display save message */ + print_info_box($savemsg); +} +?> + +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <?php + $tab_array = array(); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); + $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), true, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + display_top_tabs($tab_array, true); + ?> + </td></tr> + <tr><td> + <div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Automatic SID State Management"); ?></td> + <td width="78%" class="vtable"><input type="checkbox" id="auto_manage_sids" name="auto_manage_sids" value="on" + <?php if ($pconfig['auto_manage_sids'] == 'on') echo " checked"; ?> onclick="enable_sid_conf();" /> <?=gettext("Enable automatic management of rule state ") . + gettext("and content using configuration files. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>";?>.<br/><br/> + <?=gettext("Suricata will automatically enable/disable/modify text rules upon each update using criteria specified in configuration files. ") . + gettext("The supported configuration file format is the same as that used in the PulledPork and Oinkmaster enablesid.conf, disablesid.conf and ") . + gettext("modifysid.conf files. You can either upload existing files or create your own."); ?> + </td> + </tr> + </tbody> + <tbody id="sid_conf_rows"> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("SID Management Configuration Files"); ?></td> + </tr> + <tr> + <td colspan="2" class="vtable" align="center" > + <table width="100%" border="0" cellpadding="4" cellspacing="0"> + <tbody id="uploader" style="display: none;"> + <tr> + <td class="list"><br/><?php echo gettext("Click BROWSE to select a file to import, and then click UPLOAD. Click CLOSE to quit."); ?></td> + </tr> + <tr> + <td class="list"><input type="file" name="sidmods_fileup" id="sidmods_fileup" class="formfld file" size="50" /> + <input type="submit" name="upload" id="upload" value="<?=gettext("Upload");?>" + title="<?=gettext("Upload selected SID mods list to firewall");?>"/> <input type="button" + value="<?=gettext("Close");?>" onClick="document.getElementById('uploader').style.display='none';" /><br/></td> + <td class="list"></td> + </tr> + </tbody> + <tbody> + <tr> + <td> + <table id="maintable" width="100%" border="0" cellpadding="4" cellspacing="0"> + <colgroup> + <col style="width: 45%;"> + <col style="width: 25%;"> + <col style="width: 15%;"> + <col style="width: 15%;"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?php echo gettext("SID Mods List File Name"); ?></th> + <th class="listhdrr"><?php echo gettext("Last Modified Time"); ?></th> + <th class="listhdrr"><?php echo gettext("File Size"); ?></th> + <th class="list" align="left"><img style="cursor:pointer;" name="sidlist_new" id="sidlist_new" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext('Create a new SID Mods List');?>" + onClick="document.getElementById('sidlist_data').value=''; document.getElementById('sidlist_name').value=''; document.getElementById('sidlist_editor').style.display='table-row-group'; document.getElementById('sidlist_name').focus();" /> + <img style="cursor:pointer;" name="sidlist_import" id="sidlist_import" + onClick="document.getElementById('uploader').style.display='table-row-group';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" + height="17" border="0" title="<?php echo gettext('Import/Upload a SID Mods List');?>"/> + <input type="image" name="sidlist_dnload_all" id="sidlist_dnload_all" + src="../tree/page-file_play.gif" width="16" height="16" border="0" + title="<?php echo gettext('Download all SID Mods List files in a single gzip archive');?>"/> + </th> + </tr> + </thead> + <tbody> + <?php foreach ($sidmodfiles as $file): ?> + <tr> + <td class="listr"><?php echo gettext($file); ?></td> + <td class="listr"><?=date('M-d Y g:i a', filemtime("{$sidmods_path}{$file}")); ?></td> + <td class="listr"><?=format_bytes(filesize("{$sidmods_path}{$file}")); ?> </td> + <td class="list"><input type="image" name="sidlist_edit[]" id="sidlist_edit[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" + height="17" border="0" title="<?php echo gettext('Edit this SID Mods List');?>"/> + <input type="image" name="sidlist_delete[]" id="sidlist_delete[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>'; + return confirm('<?=gettext("Are you sure you want to permanently delete this file? Click OK to continue or CANCEL to quit.");?>');" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" + height="17" border="0" title="<?php echo gettext('Delete this SID Mods List');?>"/> + <input type="image" name="sidlist_dnload[]" id="sidlist_dnload[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>';" + src="../tree/page-file_play.gif" width="16" height="16" border="0" + title="<?php echo gettext('Download this SID Mods List file');?>"/> + </td> + </tr> + <?php endforeach; ?> + </tbody> + <tbody id="sidlist_editor" style="<?=$sidmodlist_edit_style;?>"> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><strong><?=gettext("File Name: ");?></strong><input type="text" size="45" class="formfld file" id="sidlist_name" name="sidlist_name" value="<?=$sidmodlist_name;?>" /> + <input type="submit" id="save" name="save" value="<?=gettext(" Save ");?>" title="<?=gettext("Save changes and close editor");?>" /> + <input type="button" id="cancel" name="cancel" value="<?=gettext("Cancel");?>" onClick="document.getElementById('sidlist_editor').style.display='none';" + title="<?=gettext("Abandon changes and quit editor");?>" /></td> + </tr> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><textarea wrap="off" cols="80" rows="20" name="sidlist_data" id="sidlist_data" + style="width:95%; height:100%;"><?=$sidmodlist_data;?></textarea> + </td> + </tr> + </tbody> + <tbody> + <tr> + <td colspan="3" class="vexpl"><br/><span class="red"><strong><?php echo gettext("Note:"); ?></strong></span> + <br/><?php echo gettext("SID Mods Lists are stored as local files on the firewall and their contents are " . + "not saved as part of the firewall configuration file."); ?></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><br/><strong><?php echo gettext("File List Controls:"); ?></strong><br/><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the editor window to create a new SID Mods List. You must provide a valid filename before saving.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the file upload control for uploading a new SID Mods List from your local machine.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the SID Mods List in a text edit control for viewing or editing its contents.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" /> + <?=gettext("Deletes the SID Mods List from the file system after confirmation.");?><br/> + <img src="../tree/page-file_play.gif" width="16" height="16" border="0" /> + <?=gettext("Downloads the SID Mods List file to your local machine.");?><br/> + </td> + <td class="list"></td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Interface SID Management File Assignments"); ?></td> + </tr> + <tr> + <td colspan="2" class="vtable" align="center" > + <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> + <tr> + <td> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <colgroup> + <col width="4%" align="center"> + <col width="20" align="center"> + <col width="16%" align="center"> + <col width="20%" align="center"> + <col width="20%" align="center"> + <col width="20%" align="center"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?=gettext("Rebuild"); ?></th> + <th class="listhdrr"><?=gettext("Interface"); ?></th> + <th class="listhdrr"><?=gettext("SID State Order"); ?></th> + <th class="listhdrr"><?=gettext("Enable SID File"); ?></th> + <th class="listhdrr"><?=gettext("Disable SID File"); ?></th> + <th class="listhdrr"><?=gettext("Modify SID File"); ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($a_nat as $k => $natent): ?> + <tr> + <td class="listr" align="center"> + <input type="checkbox" name="torestart[]" id="torestart[]" value="<?=$k;?>" title="<?=gettext("Apply new configuration and rebuild rules for this interface when saving");?>" /> + </td> + <td class="listbg"><?=convert_friendly_interface_to_friendly_descr($natent['interface']); ?></td> + <td class="listr" align="center"> + <select name="sid_state_order[<?=$k?>]" class="formselect" id="sid_state_order[<?=$k?>]"> + <?php + foreach (array("disable_enable" => "Disable, Enable", "enable_disable" => "Enable, Disable") as $key => $order) { + if ($key == $natent['sid_state_order']) + echo "<option value='{$key}' selected>"; + else + echo "<option value='{$key}'>"; + echo htmlspecialchars($order) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="enable_sid_file[<?=$k?>]" class="formselect" id="enable_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['enable_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="disable_sid_file[<?=$k?>]" class="formselect" id="disable_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['disable_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="modify_sid_file[<?=$k?>]" class="formselect" id="modify_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['modify_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + </tr> + <?php endforeach; ?> + </tbody> + </table> + </td> + </tr> + <tr> + <td class="vexpl"> + </td> + </tr> + <tr> + <td> + <table width="100%" cellpadding="2" cellspacing="2" border="0"> + <tbody> + <tr> + <td colspan="2" class="vexpl" style="text-align: bottom;"><strong><span class="red"><?=gettext("Notes:");?></span></strong></td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("1.");?></td> + <td class="vexpl"><?=gettext("Check the box beside an interface to immediately apply new auto-SID management ") . + gettext("changes and signal Suricata to live-load the new rules for the interface when clicking SAVE; ") . + gettext("otherwise only the new file assignments will be saved.");?> + </td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("2.");?></td> + <td class="vexpl"><?=gettext("SID State Order controls the order in which enable and disable state modifications are performed. ") . + gettext("An example would be to disable an entire category and later enable only a rule or two from it. In this case you would ") . + gettext("choose 'disable,enable' for the State Order. Note that the last action performed takes priority.");?> + </td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("3.");?></td> + <td class="vexpl"><?=gettext("The Enable SID File, Disable SID File and Modify SID File controls specify which rule modification ") . + gettext("files are run automatically for the interface. Setting a file control to 'None' disables that modification. ") . + gettext("Setting all file controls for an interface to 'None' disables automatic SID state management for the interface.");?> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + <tbody> + <tr> + <td colspan="2" class="vexpl" align="center"><input type="submit" id="save_auto_sid_conf" name="save_auto_sid_conf" class="formbtn" value="<?=gettext("Save");?>" title="<?=gettext("Save SID Management configuration");?>" /> + <?=gettext("Remember to save changes before exiting this page"); ?> + </td> + </tr> + </tbody> + </table> + </div> + </td></tr> + </tbody> +</table> +</form> + + +<?php include("fend.inc"); ?> +<script type="text/javascript"> + +function enable_sid_conf() { + var endis = !document.iform.auto_manage_sids.checked; + if (endis) { + document.getElementById("sid_conf_rows").style.display = "none"; + } + else { + document.getElementById("sid_conf_rows").style.display = ""; + } +} + +enable_sid_conf(); + +</script> +</body> +</html> diff --git a/config/suricata/suricata_suppress.php b/config/suricata/suricata_suppress.php index 4f2e8d0d..2fd2deeb 100644 --- a/config/suricata/suricata_suppress.php +++ b/config/suricata/suricata_suppress.php @@ -127,18 +127,21 @@ if ($input_errors) { <form action="/suricata/suricata_suppress.php" method="post"><?php if ($savemsg) print_info_box($savemsg); ?> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), true, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td> @@ -172,6 +175,7 @@ if ($input_errors) { </td> <td height="20px" valign="middle" nowrap class="list"> <table border="0" cellspacing="0" cellpadding="1"> + <tbody> <tr> <td valign="middle"><a href="suricata_suppress_edit.php?id=<?=$i;?>"><img @@ -192,6 +196,7 @@ if ($input_errors) { <td> </td> <?php endif; ?> </tr> + </tbody> </table> </td> </tr> @@ -200,6 +205,7 @@ if ($input_errors) { <td class="list" colspan="2"></td> <td class="list"> <table border="0" cellspacing="0" cellpadding="1"> + <tbody> <tr> <td valign="middle" width="17"> </td> <td valign="middle"><a @@ -207,6 +213,7 @@ if ($input_errors) { src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" title="<?php echo gettext("add a new list"); ?>"></a></td> </tr> + </tbody> </table> </td> </tr> @@ -224,6 +231,7 @@ if ($input_errors) { gettext("You must first unassign the Suppress List on the Interface Edit tab."); ?> </p></span></td> </tr> +</tbody> </table> </form> <?php include("fend.inc"); ?> diff --git a/config/suricata/suricata_suppress_edit.php b/config/suricata/suricata_suppress_edit.php index d4549e56..24572789 100644 --- a/config/suricata/suricata_suppress_edit.php +++ b/config/suricata/suricata_suppress_edit.php @@ -157,15 +157,17 @@ if ($savemsg) <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); - $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); - $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Blocks"), false, "/suricata/suricata_blocked.php"); $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), true, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs View"), false, "/suricata/suricata_logs_browser.php"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_sync.xml b/config/suricata/suricata_sync.xml new file mode 100644 index 00000000..a85a3d63 --- /dev/null +++ b/config/suricata/suricata_sync.xml @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> +<packagegui> + <copyright> +<![CDATA[ +/* $Id$ */ +/* ========================================================================== */ +/* +based on snortsync.xml developed as part +of pfSense (http://www.pfSense.com) +Copyright (C) 2013 Marcello Coutinho +based on pfblocker_sync.xml +All rights reserved. + +modified for use with Suricata package +Copyright (C) 2014 Bill Meeks +All rights reserved. + +Based on m0n0wall (http://m0n0.ch/wall) +Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. +All rights reserved. +*/ +/* ========================================================================== */ +/* +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. +*/ +/* ========================================================================== */ +]]></copyright> + <description><![CDATA[Describe your package here]]></description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> + <name>suricatasync</name> + <version>1.0</version> + <title>Suricata: XMLRPC Sync</title> + <include_file>/usr/local/pkg/suricata/suricata.inc</include_file> + <tabs> + <tab> + <text>Interfaces</text> + <url>/suricata/suricata_interfaces.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Global Settings</text> + <url>/suricata/suricata_global.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Updates</text> + <url>/suricata/suricata_download_updates.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Alerts</text> + <url>/suricata/suricata_alerts.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Blocks</text> + <url>/suricata/suricata_blocked.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Pass Lists</text> + <url>/suricata/suricata_passlist.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Suppress</text> + <url>/suricata/suricata_suppress.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Logs View</text> + <url>/suricata/suricata_logs_browser.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Logs Mgmt</text> + <url>/suricata/suricata_logs_mgmt.php</url> + <no_drop_down/> + </tab> + <tab> + <text>SID Mgmt</text> + <url>/suricata/suricata_sid_mgmt.php</url> + <no_drop_down/> + </tab> + <tab> + <text>Sync</text> + <url>/pkg_edit.php?xml=suricata/suricata_sync.xml</url> + <no_drop_down/> + <active/> + </tab> + </tabs> + <fields> + <field> + <name>Suricata Package XMLRPC Sync Settings</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>Enable Sync</fielddescr> + <fieldname>varsynconchanges</fieldname> + <description><![CDATA[All changes will be synced with apply config to the IPs listed below if this option is checked.<br/><br/> + <b>Important:</b> While using "Sync to hosts defined below", only sync from host A to B, A to C but <b>do not</B> enable XMLRPC sync <b>to</b> A. This will result in a loop!]]></description> + <type>select</type> + <required/> + <default_value>disabled</default_value> + <options> + <option><name>Sync to configured system backup server</name><value>auto</value></option> + <option><name>Sync to host(s) defined below</name><value>manual</value></option> + <option><name>Do not sync this package configuration</name><value>disabled</value></option> + </options> + </field> + <field> + <fielddescr>XMLRPC Timeout</fielddescr> + <fieldname>varsynctimeout</fieldname> + <description><![CDATA[Timeout in seconds for the XMLRPC timeout. Default: 150]]></description> + <type>input</type> + <default_value>150</default_value> + <size>5</size> + </field> + + <field> + <fielddescr>Refresh Rule Sets</fielddescr> + <fieldname>vardownloadrules</fieldname> + <description><![CDATA[Ask target hosts to refresh rule sets files on each sync operation.<br/><br/> + During each Suricata package sync operation, ask the target remote host to check for + a new set of posted rule sets files and refresh the local copies if necessary. The default is + to refresh the files if newer versions have been posted.<br/><br/> + <b>Note: </b>The sync process will wait for the rules download and rebuild to finish on the target remote host before returning.]]></description> + <type>select</type> + <default_value>yes</default_value> + <options> + <option><name>Signal target host to refresh rules files</name><value>yes</value></option> + <option><name>Do NOT ask target host to refresh rules files</name><value>no</value></option> + </options> + </field> + + <field> + <fielddescr>Replication Targets</fielddescr> + <fieldname>none</fieldname> + <type>rowhelper</type> + <rowhelper> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>varsyncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>varsyncprotocol</fieldname> + <description><![CDATA[Choose the protocol of the destination host. Probably <b>http</b> or <b>https</b>]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP-Address</fielddescr> + <fieldname>varsyncipaddress</fieldname> + <description><![CDATA[IP Address of the destination host.]]></description> + <type>input</type> + <size>15</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>varsyncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Admin Password</fielddescr> + <fieldname>varsyncpassword</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> + <type>password</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Start Suricata</fielddescr> + <fieldname>varsyncsuricatastart</fieldname> + <description><![CDATA[Start Suricata on target host if not already running.]]></description> + <type>checkbox</type> + <value>ON</value> + </rowhelperfield> + </rowhelper> + </field> + </fields> + <custom_delete_php_command> + </custom_delete_php_command> + <custom_php_resync_config_command> + write_config("Suricata pkg: updating CARP sync info.");suricata_sync_on_changes(); + </custom_php_resync_config_command> +</packagegui> diff --git a/config/suricata/suricata_uninstall.php b/config/suricata/suricata_uninstall.php index 2a82e473..280e2394 100644 --- a/config/suricata/suricata_uninstall.php +++ b/config/suricata/suricata_uninstall.php @@ -44,6 +44,8 @@ global $config, $g; $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; +$sidmodspath = SID_MODS_PATH; +$iprep_path = IPREP_PATH; $rcdir = RCFILEPREFIX; $suricata_rules_upd_log = RULES_UPD_LOGFILE; $suri_pf_table = SURICATA_PF_TABLE; @@ -71,9 +73,9 @@ sleep(1); unlink_if_exists("{$g['varrun_path']}/barnyard2_*.pid"); /* Remove the Suricata cron jobs. */ -install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/www/suricata/suricata_check_for_rule_updates.php", false); -install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_cron_misc.inc", false); -install_cron_job("pfctl -t {$suri_pf_table} -T expire" , false); +install_cron_job("suricata_check_for_rule_updates.php", false); +install_cron_job("suricata_check_cron_misc.inc", false); +install_cron_job("{$suri_pf_table}" , false); /* See if we are to keep Suricata log files on uninstall */ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') { @@ -82,6 +84,9 @@ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') mwexec("/bin/rm -rf {$suricatalogdir}"); } +// Mount filesystem read-write to remove our files +conf_mount_rw(); + /* Remove the Suricata GUI app directories */ mwexec("/bin/rm -rf /usr/local/pkg/suricata"); mwexec("/bin/rm -rf /usr/local/www/suricata"); @@ -105,12 +110,15 @@ if (!empty($widgets)) { } } $config['widgets']['sequence'] = implode(",", $widgetlist); - write_config(); + write_config("Suricata pkg: remove Suricata Dashboard Widget on package deinstall."); } @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"); +// Finished with filesystem mods so remount it read-only +conf_mount_ro(); + /* 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...")); @@ -118,6 +126,8 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] ! unset($config['installedpackages']['suricatasync']); @unlink("{$suricata_rules_upd_log}"); mwexec("/bin/rm -rf {$suricatalogdir}"); + mwexec("/bin/rm -rf {$sidmodspath}"); + mwexec("/bin/rm -rf {$iprep_path}"); log_error(gettext("[Suricata] The package has been removed from this system...")); } diff --git a/config/suricata/suricata_yaml_template.inc b/config/suricata/suricata_yaml_template.inc index 44fd1d5f..82c449d3 100644 --- a/config/suricata/suricata_yaml_template.inc +++ b/config/suricata/suricata_yaml_template.inc @@ -15,6 +15,10 @@ max-pending-packets: {$max_pend_pkts} # Runmode the engine should use. runmode: autofp +# If set to auto, the variable is internally switched to 'router' in IPS +# mode and 'sniffer-only' in IDS mode. +host-mode: auto + # Specifies the kind of flow load balancer used by the flow pinned autofp mode. autofp-scheduler: active-packets @@ -55,9 +59,7 @@ outputs: enabled: {$http_log_enabled} filename: http.log append: {$http_log_append} - #extended: yes # enable this for extended logging information - #custom: yes # enabled the custom logging format (defined by customformat) - #customformat: "%{%D-%H:%M:%S}t.%z %{X-Forwarded-For}i %H %m %h %u %s %B %a:%p -> %A:%P" + extended: {$http_log_extended} filetype: regular - pcap-log: @@ -82,8 +84,8 @@ outputs: - syslog: enabled: {$alert_syslog} identity: suricata - facility: auth - level: Info + facility: {$alert_syslog_facility} + level: {$alert_syslog_priority} - drop: enabled: no @@ -94,8 +96,8 @@ outputs: - file-store: enabled: {$file_store_enabled} log-dir: files - force-magic: no - force-md5: no + force-magic: {$json_log_magic} + force-md5: {$json_log_md5} waldo: file.waldo - file-log: @@ -106,6 +108,21 @@ outputs: force-magic: {$json_log_magic} force-md5: {$json_log_md5} + - dns-log: + enabled: {$dns_log_enabled} + filename: dns.log + append: {$dns_log_append} + filetype: regular + + - eve-log: + enabled: {$enable_eve_log} + type: {$eve_output_type} + filename: eve.json + identity: "suricata" + facility: {$eve_systemlog_facility} + level: {$eve_systemlog_priority} + types: {$eve_out_types} + # Magic file. The extension .mgc is added to the value here. magic-file: /usr/share/misc/magic @@ -233,12 +250,13 @@ logging: filename: {$suricatalogdir}suricata_{$if_real}{$suricata_uuid}/suricata.log - syslog: enabled: {$suricata_use_syslog} - facility: auth + facility: {$suricata_use_syslog_facility} format: "[%i] <%d> -- " pcap: - interface: {$if_real} checksum-checks: auto + promisc: {$intf_promisc_mode} # For FreeBSD ipfw(8) divert(4) support. # ipfw add 100 divert 8000 ip from any to any @@ -276,8 +294,8 @@ action-order: - alert # IP Reputation -#reputation-categories-file: {$suricatacfgdir}/iprep/categories.txt -#default-reputation-path: {$suricatacfgdir}/iprep +#reputation-categories-file: {$iprep_path}/categories.txt +#default-reputation-path: {$iprep_path} #reputation-files: # - reputation.list @@ -293,6 +311,47 @@ pcre: match-limit: 3500 match-limit-recursion: 1500 +# Holds details on the app-layer. The protocols section details each protocol. +app-layer: + protocols: + tls: + enabled: {$tls_parser} + detection-ports: + dp: 443 + #no-reassemble: yes + dcerpc: + enabled: {$dcerpc_parser} + ftp: + enabled: {$ftp_parser} + ssh: + enabled: {$ssh_parser} + smtp: + enabled: {$smtp_parser} + imap: + enabled: {$imap_parser} + msn: + enabled: {$msn_parser} + smb: + enabled: {$smb_parser} + detection-ports: + dp: 139 + dns: + global-memcap: {$dns_global_memcap} + state-memcap: {$dns_state_memcap} + request-flood: {$dns_request_flood_limit} + + tcp: + enabled: {$dns_parser_tcp} + detection-ports: + dp: 53 + udp: + enabled: {$dns_parser_udp} + detection-ports: + dp: 53 + http: + enabled: {$http_parser} + memcap: {$http_parser_memcap} + ########################################################################### # Configure libhtp. libhtp: |