prelude-correlator/master: Firewall plugin improvement
[email protected] Fri, 29 Jan 2010 18:02:50 +0100 (CET)
| Newsgroups | gmane.comp.security.ids.prelude.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 3c35a8870f623504d0976f3487bcb59b1bcb3c18 Author: Yoann Vandoorselaere <[email protected]> Date: Wed Jan 20 22:03:16 2010 +0100 Firewall plugin improvement The plugin will now report CorrelationAlert for events / sets of events that appear to have passed through a firewall known to protect the target machine. If no firewall ever emit block concerning a given host, then this host is considered un-protected, and there is no point in reporting CorrelationAlert. The 'flush-protected-hosts' variable allow you to define how much time a given target hosts should be considered as protected when a firewall drop is noticed for this machine. ======================================== PreludeCorrelator/plugins/firewall.py | 89 ++++++++++++++++++++++++++------ prelude-correlator.conf | 21 +++++++- 2 files changed, 90 insertions(+), 20 deletions(-) ======================================== diff --git a/PreludeCorrelator/plugins/firewall.py b/PreludeCorrelator/plugins/firewall.py index f21a35f..cad9b31 100644 --- a/PreludeCorrelator/plugins/firewall.py +++ b/PreludeCorrelator/plugins/firewall.py @@ -17,33 +17,88 @@ # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -import re +import re, time from PreludeCorrelator import context from PreludeCorrelator.pluginmanager import Plugin + +def _evict(ctx): + now = time.time() + for target, values in ctx._protected_hosts.items(): + if now - values[0] > ctx._flush_protected_hosts: + ctx._protected_hosts.pop(target) + + ctx.reset() + +def _alert(ctx): + cnt = 0 + fw = context.search("FIREWALL INFOS") + + for idmef in ctx.candidates: + source = idmef.Get("alert.source(0).node.address(0).address") + target = idmef.Get("alert.target(0).node.address(0).address") + dport = str(idmef.Get("alert.target(0).service.port", 0)) + + if not fw._protected_hosts.has_key(target): + continue + + if fw._protected_hosts[target][1].has_key(source + dport): + continue + + cnt += 1 + ctx.addAlertReference(idmef) + + if cnt > 0: + ctx.Set("alert.classification.text", "Events hit target") + ctx.Set("alert.assessment.impact.severity", "medium") + ctx.Set("alert.assessment.impact.description", "The target are known to be protected by a Firewall device, but a set of event have not been dropped") + ctx.Set("alert.correlation_alert.name", "No firewall block observed") + ctx.alert() + + ctx.destroy() + class FirewallPlugin(Plugin): + def __init__(self, env): + Plugin.__init__(self, env) + self._flush_protected_hosts = self.getConfigValue("flush-protected-hosts", 3600, type=int) + def run(self, idmef): source = idmef.Get("alert.source(0).node.address(0).address") + scat = idmef.Get("alert.source(0).node.address(0).category") target = idmef.Get("alert.target(0).node.address(0).address") - dport = idmef.Get("alert.target(0).service.port", 0) + tcat = idmef.Get("alert.target(0).node.address(0).category") - if not source or not target: + dport = idmef.Get("alert.target(0).service.port") + if not source or not target or not dport: return - ctxname = context.getName("FIREWALL", source, target, dport) + if scat not in ("ipv4-addr", "ipv6-addr") or tcat not in ("ipv4-addr", "ipv6-addr"): + return + + ctx = context.Context("FIREWALL INFOS", { "expire": self._flush_protected_hosts, "alert_on_expire": _evict }, update=True) + if ctx.getUpdateCount() == 0: + ctx._protected_hosts = {} + ctx._flush_protected_hosts = self._flush_protected_hosts if idmef.match("alert.classification.text", re.compile("[Pp]acket [Dd]ropped|[Dd]enied")): - # overwrite any existing context, with the same name. - ctx = context.Context(ctxname, { "expire": 10 }, update=True) - ctx.block_installed = True + if not ctx._protected_hosts.has_key(target): + ctx._protected_hosts[target] = [0, {}] + + ctx._protected_hosts[target][0] = float(idmef.getTime()) + ctx._protected_hosts[target][1][source + str(dport)] = True else: - # Begins a timer for every event that contains a source and a target - # address which has not been matched by an observed packet denial. If a packet - # denial is not observed in the next 10 seconds, an event alert is generated. - ctx = context.search(ctxname) - if not ctx or ctx.block_installed == False: - ctx = context.Context(ctxname, { "expire": 10, "alert_on_expire": True }, idmef=idmef, update=True) - ctx.Set("alert.assessment", idmef.Get("alert.assessment")) - ctx.Set("alert.classification", idmef.Get("alert.classification")) - ctx.Set("alert.correlation_alert.name", "No firewall block observed for these events") - ctx.block_installed = False + if not ctx._protected_hosts.has_key(target): + return + + if time.time() - ctx._protected_hosts[target][0] > self._flush_protected_hosts: + ctx._protected_hosts.pop(target) + return; + + if ctx._protected_hosts[target][1].has_key(source + str(dport)): + return + + ctx = context.Context(("FIREWALL", source), { "expire": 120, "alert_on_expire": _alert }, update=True) + if ctx.getUpdateCount() == 0: + ctx.candidates = [] + + ctx.candidates.append(idmef) diff --git a/prelude-correlator.conf b/prelude-correlator.conf index a6183ad..ca7f777 100644 --- a/prelude-correlator.conf +++ b/prelude-correlator.conf @@ -28,7 +28,7 @@ disable = true # [DshieldPlugin] # disable = false # -# How often the Dshield database should be reloaded (download + reload) +# How often the Dshield database should be reloaded (download + reload) # (default: once a week). 0 to disable reloading. # reload = 604800 # @@ -38,12 +38,27 @@ disable = true # URI used to retrive the dshield database: # uri = /ipsascii.html?limit=10000 # -# Define the maximum allowed time for downloading the database (only work with Python >= 2.6, default is 10 seconds) +# Define the maximum allowed time for downloading the database +# (only work with Python >= 2.6, default is 10 seconds) # timeout = 10 -# Disable firewall correlation by default since it is very verbose +# This plugin will report CorrelationAlert for events / sets of events +# that appear to have passed through a firewall known to protect the +# target machine. +# +# If no firewall ever emit block concerning a given host, then this host +# is considered un-protected, and there is no point in reporting +# CorrelationAlert. +# +# The 'flush-protected-hosts' variable allow you to define how much +# time a given target hosts should be considered as protected when a +# firewall drop is noticed for this machine. +# +# The plugin is disabled by default since it tend to be very verbose + [FirewallPlugin] disable = True +flush-protected-hosts = 3600 ## _______________________________________________ Prelude-cvslog site list [email protected] http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog