Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > 4031e5ae9e357e0b20f97773b9194fb4 > files > 28

prelude-correlator-5.0.1-1.mga7.noarch.rpm

# Copyright (C) 2009-2018 CS-SI. All Rights Reserved.
# Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
#
# This file is part of the Prelude-Correlator program.
#
# 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 2, 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import re
import 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 target not in fw._protected_hosts:
            continue

        if (source + dport) in fw._protected_hosts[target][1]:
            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")
        tcat = idmef.get("alert.target(0).node.address(0).category")

        dport = idmef.get("alert.target(0).service.port")
        if not source or not target or not dport:
            return

        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, ruleid=self.name)
        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")):
            if target not in ctx._protected_hosts:
                ctx._protected_hosts[target] = [0, {}]

            ctx._protected_hosts[target][0] = float(idmef.getTime())
            ctx._protected_hosts[target][1][source + str(dport)] = True
        else:
            if target not in ctx._protected_hosts:
                return

            if time.time() - ctx._protected_hosts[target][0] > self._flush_protected_hosts:
                ctx._protected_hosts.pop(target)
                return

            if (source + str(dport)) in ctx._protected_hosts[target][1]:
                return

            ctx = context.Context(("FIREWALL", source), {"expire": 120, "alert_on_expire": _alert},
                                  update=True, ruleid=self.name)
            if ctx.getUpdateCount() == 0:
                ctx.candidates = []

            ctx.candidates.append(idmef)