]> git.ipfire.org Git - people/mfischer/ipfire-2.x.git/commitdiff
suricata: correct rule actions in IPS mode
authorTim FitzGeorge <ipfr@tfitzgeorge.me.uk>
Wed, 5 Jun 2019 18:56:32 +0000 (20:56 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 5 Jun 2019 11:39:57 +0000 (12:39 +0100)
In IPS mode rule actions need to be have the action 'drop' for the
protection to work, however this is not appropriate for all rules.
Modify the generator for oinkmaster-modify-sids.conf to leave
rules with the action 'alert' here this is appropriate.  Also add
a script to be run on update to correct existing downloaded rules.

Fixes #12086

Signed-off-by: Tim FitzGeorge <ipfr@tfitzgeorge.me.uk>
Tested-by: Peter Müller <peter.mueller@ipfire.org>
Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
config/cfgroot/ids-functions.pl
config/rootfiles/common/configroot
config/rootfiles/core/133/update.sh
config/suricata/convert-ids-modifysids-file [new file with mode: 0644]
html/cgi-bin/ids.cgi
lfs/configroot

index 88734a3caababc80bf42d54384d49d980da55ca4..e1caa6e58b317186e34f343040ce0c4749839a18 100644 (file)
@@ -243,7 +243,7 @@ sub downloadruleset {
        # Load perl module to deal with temporary files.
        use File::Temp;
 
-       # Generate temporay file name, located in "/var/tmp" and with a suffix of ".tar.gz".
+       # Generate temporary file name, located in "/var/tmp" and with a suffix of ".tar.gz".
        my $tmp = File::Temp->new( SUFFIX => ".tar.gz", DIR => "/var/tmp/", UNLINK => 0 );
        my $tmpfile = $tmp->filename();
 
@@ -293,6 +293,9 @@ sub downloadruleset {
        # Overwrite existing rules tarball with the new downloaded one.
        move("$tmpfile", "$rulestarball");
 
+       # Set correct ownership for the rulesdir and files.
+       set_ownership("$rulestarball");
+
        # If we got here, everything worked fine. Return nothing.
        return;
 }
@@ -726,8 +729,8 @@ sub write_used_rulefiles_file(@) {
 #
 ## Function to generate and write the file for modify the ruleset.
 #
-sub write_modify_sids_file($) {
-       my ($ruleaction) = @_;
+sub write_modify_sids_file($$) {
+       my ($ruleaction,$rulefile) = @_;
 
        # Open modify sid's file for writing.
        open(FILE, ">$modify_sids_file") or die "Could not write to $modify_sids_file. $!\n";
@@ -737,8 +740,39 @@ sub write_modify_sids_file($) {
 
        # Check if the traffic only should be monitored.
        unless($ruleaction eq "alert") {
-               # Tell oinkmaster to switch all rules from alert to drop.
-               print FILE "modifysid \* \"alert\" \| \"drop\"\n";
+               # Suricata is in IPS mode, which means that the rule actions have to be changed
+               # from 'alert' to 'drop', however not all rules should be changed.  Some rules
+               # exist purely to set a flowbit which is used to convey other information, such
+               # as a specific type of file being downloaded, to other rulewhich then check for
+               # malware in that file.  Rules which fall into the first category should stay as
+               # alert since not all flows of that type contain malware.
+
+               if($rulefile eq 'registered' or $rulefile eq 'subscripted' or $rulefile eq 'community') {
+                       # These types of rulesfiles contain meta-data which gives the action that should
+                       # be used when in IPS mode.  Do the following:
+                       #
+                       # 1. Disable all rules and set the action to 'drop'
+                       # 2. Set the action back to 'alert' if the rule contains 'flowbits:noalert;'
+                       #    This should give rules not in the policy a reasonable default if the user
+                       #    manually enables them.
+                       # 3. Enable rules and set actions according to the meta-data strings.
+
+                       my $policy = 'balanced';  # Placeholder to allow policy to be changed.
+
+                       print FILE <<END;
+modifysid * "^#?(?:alert|drop)" | "#drop"
+modifysid * "^#drop(.+flowbits:noalert;)" | "#alert\${1}"
+modifysid * "^#(?:alert|drop)(.+policy $policy-ips alert)" | "alert\${1}"
+modifysid * "^#(?:alert|drop)(.+policy $policy-ips drop)" | "drop\${1}"
+END
+               } else {
+                       # These rulefiles don't have the metadata, so set rules to 'drop' unless they
+                       # contain the string 'flowbits:noalert;'.
+                       print FILE <<END;
+modifysid * "^(#?)(?:alert|drop)" | "\${1}drop"
+modifysid * "^(#?)drop(.+flowbits:noalert;)" | "\${1}alert\${2}"
+END
+               }
        }
 
        # Close file handle.
index a7f27fe5510fe99300c2a33a0a92ea6cebffd9ea..56b0257bcce8656e3b7ffeb64e1b901b5e1eacdc 100644 (file)
@@ -3,6 +3,7 @@ usr/sbin/convert-outgoingfw
 usr/sbin/convert-portfw
 usr/sbin/convert-snort
 usr/sbin/convert-xtaccess
+usr/sbin/convert-ids-modifysids-file
 usr/sbin/firewall-policy
 #var/ipfire
 var/ipfire/addon-lang
index 9d708f0924b84b58ba0f76250c82534468d0adcb..a05ad074182604555bc1f73b494d9e0c04edebff 100644 (file)
@@ -62,6 +62,9 @@ telinit u
 # Regenerate /etc/ipsec.conf
 sudo -u nobody /srv/web/ipfire/cgi-bin/vpnmain.cgi
 
+# Modify suricata modify-sids file
+/usr/sbin/convert-ids-modifysids-file
+
 # Start services
 /usr/local/bin/ipsecctrl S
 /etc/init.d/suricata restart
diff --git a/config/suricata/convert-ids-modifysids-file b/config/suricata/convert-ids-modifysids-file
new file mode 100644 (file)
index 0000000..8b70aa0
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2019 IPFire Development Team <info@ipfire.org>                #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+use strict;
+
+require '/var/ipfire/general-functions.pl';
+require "${General::swroot}/ids-functions.pl";
+
+# Hash which contains the IDS (suricata) settings.
+my %idssettings;
+
+# Hash which contains the RULES settings.
+my %rulessettings;
+
+#
+## Step 1: Read IDS and rules settings.
+#
+
+exit unless(-f $IDS::ids_settings_file and -f $IDS::rules_settings_file);
+
+# Read IDS settings.
+&General::readhash("$IDS::ids_settings_file", \%idssettings);
+
+# Read rules settings.
+&General::readhash("$IDS::rules_settings_file", \%rulessettings);
+
+#
+## Step 2: Generate and write the file to modify the ruleset.
+#
+
+my $IDS_action = "drop";
+
+# Check if the traffic only should be monitored.
+if ($idssettings{"MONITOR_TRAFFIC_ONLY"} eq "on") {
+       # Switch IDS action to alert only.
+       $IDS_action = "alert";
+}
+
+# Call subfunction and pass the desired IDS action.
+&IDS::write_modify_sids_file($IDS_action, $rulessettings{RULES});
+
+# Set correct ownership.
+&IDS::set_ownership("$IDS::modify_sids_file");
+
+#
+## Step 3: Call oinkmaster to extract and setup the rules structures.
+#
+
+# Check if a rulestarball is present.
+if (-f $IDS::rulestarball) {
+       # Launch oinkmaster by calling the subfunction.
+       &IDS::oinkmaster();
+
+       # Set correct ownership for the rulesdir and files.
+       &IDS::set_ownership("$IDS::rulespath");
+}
+
+#
+## Step 4: Start the IDS if enabled.
+#
+
+# Check if the IDS should be started.
+if($idssettings{"ENABLE_IDS"} eq "on") {
+       # Call suricatactrl and reload the rules.
+       &IDS::call_suricatactrl("reload");
+}
index 00db6a0c3afd197627547d09ee3f635610f8971a..1791e9bebce094b8b12f0383e79ab50f4f870fed 100644 (file)
@@ -359,7 +359,7 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
                                $errormessage = "$Lang::tr{'could not download latest updates'} - $Lang::tr{'system is offline'}";
                        }
 
-                       # Check if enought free disk space is availabe.
+                       # Check if enough free disk space is availabe.
                        if(&IDS::checkdiskspace()) {
                                $errormessage = "$Lang::tr{'not enough disk space'}";
                        }
@@ -370,6 +370,22 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
                                # a new ruleset.
                                &working_notice("$Lang::tr{'ids working'}");
 
+                               &General::readhash("$IDS::ids_settings_file", \%idssettings);
+
+                               # Temporary variable to set the ruleaction.
+                               # Default is "drop" to use suricata as IPS.
+                               my $ruleaction="drop";
+
+                               # Check if the traffic only should be monitored.
+                               if($idssettings{'MONITOR_TRAFFIC_ONLY'} eq 'on') {
+                                       # Switch the ruleaction to "alert".
+                                       # Suricata acts as an IDS only.
+                                       $ruleaction="alert";
+                               }
+
+                               # Write the modify sid's file and pass the taken ruleaction.
+                               &IDS::write_modify_sids_file($ruleaction, $cgiparams{'RULES'});
+
                                # Call subfunction to download the ruleset.
                                if(&IDS::downloadruleset()) {
                                        $errormessage = $Lang::tr{'could not download latest updates'};
@@ -609,8 +625,10 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
                $ruleaction="alert";
        }
 
+       &General::readhash("$IDS::rules_settings_file", \%rulessettings);
+
        # Write the modify sid's file and pass the taken ruleaction.
-       &IDS::write_modify_sids_file($ruleaction);
+       &IDS::write_modify_sids_file($ruleaction, $rulessettings{'RULES'});
 
        # Check if "MONITOR_TRAFFIC_ONLY" has been changed.
        if($cgiparams{'MONITOR_TRAFFIC_ONLY'} ne $oldidssettings{'MONITOR_TRAFFIC_ONLY'}) {
index d4eb545f034a3062a97b834e8e70e1b16ff8fcf2..227d092391403cffb97f956cee735718a4d19d39 100644 (file)
@@ -135,6 +135,7 @@ $(TARGET) :
 
        # Install snort to suricata converter.
        cp $(DIR_SRC)/config/suricata/convert-snort     /usr/sbin/convert-snort
+       cp $(DIR_SRC)/config/suricata/convert-ids-modifysids-file   /usr/sbin/convert-ids-modifysids-file
 
        # Add conntrack helper default settings
        for proto in FTP H323 IRC SIP TFTP; do \