Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pfSense-pkg-suricata-3.1.2 - Update for bug fixes and new features #256

Merged
merged 9 commits into from
Jan 16, 2017
3 changes: 1 addition & 2 deletions security/pfSense-pkg-suricata/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# $FreeBSD$

PORTNAME= pfSense-pkg-suricata
PORTVERSION= 3.0
PORTREVISION= 12
PORTVERSION= 3.1.2
CATEGORIES= security
MASTER_SITES= # empty
DISTFILES= # empty
113 changes: 102 additions & 11 deletions security/pfSense-pkg-suricata/files/usr/local/pkg/suricata/suricata.inc
Original file line number Diff line number Diff line change
@@ -838,6 +838,11 @@ function sync_suricata_package_config() {
$suricatadir = SURICATADIR;
$rcdir = RCFILEPREFIX;

/* Create required log and db directories in /var on each sync, in case /var is in RAM. */
safe_mkdir(SURICATALOGDIR);
safe_mkdir(SURICATA_IPREP_PATH);
safe_mkdir(SURICATA_SID_MODS_PATH);

// Do not start config build if there are no Suricata-configured interfaces
if (!is_array($config['installedpackages']['suricata']['rule']) || count($config['installedpackages']['suricata']['rule']) < 1) {
return;
@@ -1328,7 +1333,8 @@ function suricata_load_rules_map($rules_path) {
* 0 if not auto-managed
* state_toggled = 1 if rule was toggled by SID MGMT process,
* 0 if not toggled
* modified = 1 if rule action or content is modified by SID MGMT process,
* modified = 1 if rule action or content is modified by SID MGMT or
* IPS Poliocy process,
* 0 if not modified
* flowbits = Array of applicable flowbits if rule contains
* flowbits options
@@ -1786,16 +1792,22 @@ function suricata_write_flowbit_rules_file($flowbit_rules, $rule_file) {
}
}

function suricata_load_vrt_policy($policy, $all_rules=null) {
function suricata_load_vrt_policy($policy, $mode='alert', $all_rules=null) {

/************************************************/
/* This function returns an array of all rules */
/* marked with the passed in $policy metadata. */
/* */
/* $policy --> desired VRT security policy */
/* 1. connectivity */
/* 2. balanced */
/* 3. security */
/* 1. connectivity */
/* 2. balanced */
/* 3. security */
/* */
/* $mode --> determines rule action */
/* 1. alert = all rule alert */
/* 2. policy = rule action */
/* set according */
/* policy spec. */
/* */
/* $all_rules --> optional Rules Map array of */
/* rules to scan for policy. */
@@ -1835,6 +1847,19 @@ function suricata_load_vrt_policy($policy, $all_rules=null) {
$vrt_policy_rules[$k1][$k2]['rule'] = ltrim(substr($arulem2['rule'], strpos($arulem2['rule'], "#") + 1));
$vrt_policy_rules[$k1][$k2]['disabled'] = 0;
}

// If policy mode is enabled, grab the suggested action
// for this policy and set it as the rule action.
if ($mode == 'policy') {
$matches = array();
if (preg_match('/' . "policy {$policy}-ips" . '([^,|^;]*)/', $arulem2['rule'], $matches)) {
if ($tmp = preg_replace('/^\s*alert\s/', trim($matches[1]) . ' ', $vrt_policy_rules[$k1][$k2]['rule'], 1)) {
$vrt_policy_rules[$k1][$k2]['rule'] = $tmp;
$vrt_policy_rules[$k1][$k2]['action'] = trim($matches[1]);
$vrt_policy_rules[$k1][$k2]['modified'] = 1;
}
}
}
}
}
}
@@ -2389,7 +2414,7 @@ function suricata_modify_sid_state(&$rule_map, $sid_mods, $action, $log_results
$modcount++;
}
elseif ($action == 'drop' && $rule_map[$k1][$k2]['action'] != 'drop') {
if ($tmp = preg_replace('/alert/', 'drop', $rule_map[$k1][$k2]['rule'], 1)) {
if ($tmp = preg_replace('/\s*alert\s*/', 'drop ', $rule_map[$k1][$k2]['rule'], 1)) {
$rule_map[$k1][$k2]['rule'] = $tmp;
$rule_map[$k1][$k2]['action'] = 'drop';
$rule_map[$k1][$k2]['managed'] = 1;
@@ -2899,6 +2924,67 @@ function suricata_modify_sids(&$rule_map, $suricatacfg) {
unset($enablesid, $disablesid);
}

function suricata_modify_sids_action(&$rule_map, $suricatacfg) {

/***********************************************/
/* This function modifies the rules in the */
/* passed rules_map array based on values in */
/* the alertsid/dropsid configuration */
/* parameters for the interface. */
/* */
/* $rule_map = array of current rules */
/* $suricatacfg = interface config settings */
/***********************************************/

if (!isset($suricatacfg['rule_sid_force_alert']) &&
!isset($suricatacfg['rule_sid_force_drop'])) {
return;
}

/* Load up our alertsid and dropsid arrays with manually changed SID actions */
$alertsid = suricata_load_sid_mods($suricatacfg['rule_sid_force_alert']);
$dropsid = suricata_load_sid_mods($suricatacfg['rule_sid_force_drop']);

/* Change action for any rules that need to be */
/* forced to "alert" with alertsid mods. */
if (!empty($alertsid)) {
foreach ($rule_map as $k1 => $rulem) {
foreach ($rulem as $k2 => $v) {
if (isset($alertsid[$k1][$k2]) && $v['action'] != 'alert') {
$matches = array();
if (preg_match('/^\s*#*\s*(drop|pass|reject)/i', $v['rule'], $matches)) {
$txt_regx = '/^\s*' . "{$matches[1]}" . '\s/';
if ($tmp = preg_replace($txt_regx, 'alert ', $v['rule'], 1)) {
$rule_map[$k1][$k2]['rule'] = $tmp;
$rule_map[$k1][$k2]['action'] = 'alert';
}
}
}
}
}
}

/* Change action for any rules that need to be */
/* forced to "drop" with dropsid mods. */
if (!empty($dropsid)) {
foreach ($rule_map as $k1 => $rulem) {
foreach ($rulem as $k2 => $v) {
if (isset($dropsid[$k1][$k2]) && $v['action'] != 'drop') {
$matches = array();
if (preg_match('/^\s*#*\s*(alert|pass|reject)/i', $v['rule'], $matches)) {
$txt_regx = '/^\s*' . "{$matches[1]}" . '\s/';
if ($tmp = preg_replace($txt_regx, 'drop ', $v['rule'], 1)) {
$rule_map[$k1][$k2]['rule'] = $tmp;
$rule_map[$k1][$k2]['action'] = 'drop';
}
}
}
}
}
}
unset($alertsid, $dropsid);
}

function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) {

/***********************************************************/
@@ -3009,8 +3095,8 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) {

// Check if a pre-defined Snort VRT policy is selected. If so,
// add all the VRT policy rules to our enforcing rule set.
if (!empty($suricatacfg['ips_policy'])) {
$policy_rules = suricata_load_vrt_policy($suricatacfg['ips_policy'], $all_rules);
if ($suricatacfg['ips_policy_enable'] == 'on' && !empty($suricatacfg['ips_policy'])) {
$policy_rules = suricata_load_vrt_policy($suricatacfg['ips_policy'], $suricatacfg['ips_policy_mode'], $all_rules);
foreach ($policy_rules as $k1 => $policy) {
foreach ($policy as $k2 => $p) {
if (!is_array($enabled_rules[$k1])) {
@@ -3019,19 +3105,22 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) {
if (!is_array($enabled_rules[$k1][$k2])) {
$enabled_rules[$k1][$k2] = array();
}
$enabled_rules[$k1][$k2]['rule'] = $p['rule'];
$enabled_rules[$k1][$k2]['category'] = $p['category'];
$enabled_rules[$k1][$k2]['disabled'] = $p['disabled'];
$enabled_rules[$k1][$k2]['flowbits'] = $p['flowbits'];
$enabled_rules[$k1][$k2]['rule'] = $p['rule'];
$enabled_rules[$k1][$k2]['action'] = $p['action'];
$enabled_rules[$k1][$k2]['modified'] = $p['modified'];
}
}
unset($policy_rules, $policy, $p);
}

// Process any enablesid or disablesid modifications for the selected rules.
// Process any enablesid, disablesid, alertsid or dropsid 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);
suricata_modify_sids_action($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}");
@@ -3059,9 +3148,11 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) {

suricata_auto_sid_mgmt($enabled_rules, $suricatacfg, TRUE);
if (!empty($enabled_rules)) {
// Auto-SID management generated some rules, so use them
// Auto-SID management generated some rules, so use them but
// apply any user-specified overrides for state or action.
$no_rules_defined = false;
suricata_modify_sids($enabled_rules, $suricatacfg);
suricata_modify_sids_action($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}");
Original file line number Diff line number Diff line change
@@ -64,6 +64,17 @@
@file_put_contents("{$suricatacfgdir}/passlist", implode("\n", $plist));
$suri_passlist = "{$suricatacfgdir}/passlist";

// If using inline IPS mode, generate PASS rules to substitute for the PASS LIST
@file_put_contents("{$suricatacfgdir}/rules/passlist.rules", '');
if ($suricatacfg['ips_mode'] == 'ips_mode_inline' && $suricatacfg['blockoffenders'] == 'on') {
$sid_tmp = 1000001;
foreach ($plist as $ip_tmp) {
$line = "pass ip {$ip_tmp} any <> any any (msg:\"Pass List Entry - allow all traffic from/to {$ip_tmp}\"; sid:{$sid_tmp};)\n";
@file_put_contents("{$suricatacfgdir}/rules/passlist.rules", $line, FILE_APPEND);
$sid_tmp++;
}
}

// Set default and user-defined variables for SERVER_VARS and PORT_VARS
$suricata_servers = array (
"dns_servers" => "\$HOME_NET", "smtp_servers" => "\$HOME_NET", "http_servers" => "\$HOME_NET",
@@ -229,6 +240,11 @@
else
$tls_log_enabled = "no";

if ($suricatacfg['enable_tls_store'] == 'on')
$tls_store_enabled = "yes";
else
$tls_store_enabled = "no";

if ($suricatacfg['tls_log_extended'] == 'on')
$tls_log_extended = "yes";
else
@@ -764,6 +780,8 @@
$rules_files .= "\n - " . FLOWBITS_FILENAME;
if (filesize("{$suricatacfgdir}/rules/custom.rules") > 0)
$rules_files .= "\n - custom.rules";
if (filesize("{$suricatacfgdir}/rules/passlist.rules") > 0)
$rules_files .= "\n - passlist.rules";
$rules_files = ltrim($rules_files, '\n -');

// Add the general logging settings to the configuration (non-interface specific)
Original file line number Diff line number Diff line change
@@ -74,6 +74,9 @@ outputs:
enabled: {$tls_log_enabled}
filename: tls.log
extended: {$tls_log_extended}

- tls-store:
enabled: {$tls_store_enabled}
certs-log-dir: certs

- stats:
Original file line number Diff line number Diff line change
@@ -508,7 +508,7 @@ function build_logfile_list() {
'arefresh',
null,
'Refresh',
($config['installedpackages']['suricata']['alertsblocks']['arefresh'] == "on"),
$pconfig['arefresh'] == 'on' ? true:false,
'on'
))->setHelp('Default is ON');

@@ -641,10 +641,10 @@ function build_logfile_list() {
'filterlogentries_clear',
'Clear',
null,
'fa-trash'
'fa-trash-o'
))->setHelp("Remove all filters")
->removeclass("btn-primary")
->addClass("btn-danger");
->addClass("btn-danger no-confirm");

$section->add($group);

Original file line number Diff line number Diff line change
@@ -265,6 +265,7 @@
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['enable_tls_store'] == "on") { $natent['enable_tls_store'] = 'on'; }else{ $natent['enable_tls_store'] = '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'; }
@@ -630,6 +631,13 @@ function suricata_get_config_lists($lists) {
$pconfig['enable_tls_log'] == 'on' ? true:false,
'on'
));
$section->addInput(new Form_Checkbox(
'enable_tls_store',
'Enable TLS Store',
'Suricata will log and store TLS certificates for the interface. Default is Not Checked.',
$pconfig['enable_tls_store'] == 'on' ? true:false,
'on'
));

$section->addInput(new Form_Checkbox(
'tls_log_extended',
@@ -1063,7 +1071,6 @@ function enable_blockoffenders() {
if ($('#ips_mode').val() == 'ips_mode_inline') {
hideCheckbox('blockoffenderskill', true);
hideSelect('blockoffendersip', true);
hideClass('passlist', true);
}
}

@@ -1092,6 +1099,7 @@ function toggle_http_log() {

function toggle_tls_log() {
var hide = ! $('#enable_tls_log').prop('checked');
hideCheckbox('enable_tls_store', hide);
hideCheckbox('tls_log_extended', hide);
}

@@ -1154,6 +1162,7 @@ function enable_change() {
disableInput('append_http_log', disable);
disableInput('http_log_extended', disable);
disableInput('enable_tls_log', disable);
disableInput('enable_tls_store', disable);
disableInput('tls_log_extended', disable);
disableInput('enable_json_file_log', disable);
disableInput('append_json_file_log', disable);
@@ -1262,7 +1271,6 @@ function getListContents(listName, listType, ctrlID) {
if ($('#ips_mode').val() == 'ips_mode_inline') {
hideCheckbox('blockoffenderskill', true);
hideSelect('blockoffendersip', true);
hideClass('passlist', true);
}
else {
hideCheckbox('blockoffenderskill', false);
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@
$pconfig = array();

// Grab saved settings from configuration
$pconfig['enable_log_mgmt'] = $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == 'on' ? 'on' : 'off';
$pconfig['enable_log_mgmt'] = $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == 'off' ? 'off' : 'on';
$pconfig['clearlogs'] = $config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on' ? 'on' : 'off';
$pconfig['suricataloglimit'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimit'] == 'on' ? 'on' : 'off';
$pconfig['suricataloglimitsize'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize'];

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@
$pconfig['autoflowbits'] = $a_nat[$id]['autoflowbitrules'];
$pconfig['ips_policy_enable'] = $a_nat[$id]['ips_policy_enable'];
$pconfig['ips_policy'] = $a_nat[$id]['ips_policy'];
$pconfig['ips_policy_mode'] = $a_nat[$id]['ips_policy_mode'];
}

$if_real = get_real_interface($a_nat[$id]['interface']);
@@ -109,10 +110,12 @@
if ($_POST['ips_policy_enable'] == "on") {
$a_nat[$id]['ips_policy_enable'] = 'on';
$a_nat[$id]['ips_policy'] = $_POST['ips_policy'];
$a_nat[$id]['ips_policy_mode'] = $_POST['ips_policy_mode'];
}
else {
$a_nat[$id]['ips_policy_enable'] = 'off';
unset($a_nat[$id]['ips_policy']);
unset($a_nat[$id]['ips_policy_mode']);
}

// Always start with the default events and files rules
@@ -126,7 +129,6 @@

if ($_POST['autoflowbits'] == "on") {
$a_nat[$id]['autoflowbitrules'] = 'on';
print("Autoflowbits is on");
}
else {
$a_nat[$id]['autoflowbitrules'] = 'off';
@@ -159,15 +161,18 @@
if ($_POST['ips_policy_enable'] == "on") {
$a_nat[$id]['ips_policy_enable'] = 'on';
$a_nat[$id]['ips_policy'] = $_POST['ips_policy'];
$a_nat[$id]['ips_policy_mode'] = $_POST['ips_policy_mode'];
}
else {
$a_nat[$id]['ips_policy_enable'] = 'off';
unset($a_nat[$id]['ips_policy']);
unset($a_nat[$id]['ips_policy_mode']);
}

$pconfig['autoflowbits'] = $_POST['autoflowbits'];
$pconfig['ips_policy_enable'] = $_POST['ips_policy_enable'];
$pconfig['ips_policy'] = $_POST['ips_policy'];
$pconfig['ips_policy_mode'] = $_POST['ips_policy_mode'];

// Remove all but the default events and files rules
$enabled_rulesets_array = array();
@@ -182,15 +187,18 @@
if ($_POST['ips_policy_enable'] == "on") {
$a_nat[$id]['ips_policy_enable'] = 'on';
$a_nat[$id]['ips_policy'] = $_POST['ips_policy'];
$a_nat[$id]['ips_policy_mode'] = $_POST['ips_policy_mode'];
}
else {
$a_nat[$id]['ips_policy_enable'] = 'off';
unset($a_nat[$id]['ips_policy']);
unset($a_nat[$id]['ips_policy_mode']);
}

$pconfig['autoflowbits'] = $_POST['autoflowbits'];
$pconfig['ips_policy_enable'] = $_POST['ips_policy_enable'];
$pconfig['ips_policy'] = $_POST['ips_policy'];
$pconfig['ips_policy_mode'] = $_POST['ips_policy_mode'];

// Start with the required default events and files rules
$enabled_rulesets_array = $default_rules;
@@ -301,7 +309,7 @@
'fa-file-text-o'
);

$viewbtn->removeClass('btn-primary')->addClass('btn-success')
$viewbtn->removeClass('btn-primary')->addClass('btn-success btn-sm')
->setHelp('Click to view auto-enabled rules required to satisfy flowbit dependencies' . '<br /><br />' .
'<span class="text-danger"><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.'));
@@ -327,41 +335,42 @@

print($section);

if (true || $snortdownload == 'on') {
if ($snortdownload == 'on') {

$section = new Form_Section("Snort IPS Policy selection");

$chkips = new Form_Checkbox(
'ips_policy_enable',
'Use IPS Policy',
'Use rules from one of three pre-defined Snort IPS policies',
($a_nat[$id]['ips_policy_enable'] == "on"),
'on'
);

$chkips->setHelp('<span class="text-danger"><strong>' . gettext("Note: ") . '</strong></span>' . gettext('You must be using the Snort VRT rules to use this option.' . '<br />' .
'Selecting this option disables manual selection of Snort VRT categories in the list below, ' .
'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.'));


if (($snortdownload != 'on') || ($a_nat[$id]['ips_policy_enable'] != 'on')) {
// $chkips->setDisabled();
}

$section->addInput($chkips);

$section->addInput(new Form_Select(
'ips_policy',
'IPS Policy Selection',
$pconfig['ips_policy'],
array(
'connected' => 'Conected',
array( 'connectivity' => 'Connectivity',
'balanced' => 'Balanced',
'security' => 'Security')
'security' => 'Security',
'max-detect' => 'Maximum Detection')
))->setHelp('Connectivity blocks most major threats with few or no false positives. Balanced is a good starter policy. ' .
'It is speedy, has good base coverage level, and covers most threats of the day. It includes all rules in Connectivity. Security is a stringent policy. ' .
'It contains everything in the first two plus policy-type rules such as Flash in an Excel file.');
'It contains everything in the first two plus policy-type rules such as Flash in an Excel file. Maximum Detection encompasses vulnerabilities from 2005 ' .
'or later with a CVSS score of at least 7.5 along with critical malware and exploit kit rules. The Maximum Detection policy favors detection over rated ' .
'throughput. In some situations this policy can and will cause significant throughput reductions.');
$section->addInput(new Form_Select(
'ips_policy_mode',
'IPS Policy Mode',
$pconfig['ips_policy_mode'],
array( 'alert' => 'Alert',
'policy' => 'Policy')
))->setHelp('When Policy is selected, this will automatically change the action for rules in the selected IPS Policy from their default action of alert to the action specified ' .
'in the policy metadata (typically drop, but may be alert for some policy rules).');

print($section);
}
@@ -635,6 +644,7 @@ function enable_change()
var endis = !($('#ips_policy_enable').prop('checked'));

hideInput('ips_policy', endis);
hideInput('ips_policy_mode', endis);

$('input[type="checkbox"]').each(function() {
var str = $(this).val();