# Copyright (C) 2010 David Rupprechter # www.dotlike.net # # 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; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # GeoIP information for portscans/network scans detected by OSSEC and Snort sensors # # please download http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz and place # the content of the archive in /usr/share/GeoIP/ to get more detailled geographical information # please report bugs to rupprechter at dotlike dot net # for more information please visit www.dotlike.net/portscangeoinfo.php import os import re import shlex, subprocess import sys from PreludeCorrelator.context import Context from PreludeCorrelator.pluginmanager import Plugin from PreludeCorrelator.idmef import IDMEF strout = None class PortscanGeoinfoPlugin(Plugin): def run(self, idmef): classification = idmef.Get("alert.classification.text") NMAPFSCAN = "PSNG_TCP_FILTERED_PORTSCAN" NMAPSCANUDP = "PSNG_UDP_FILTERED_PORTSCAN" NMAPPSNG = "ICMP PING NMAP" TCPPSCAN = "(portscan) TCP Portscan" NMAPSCAN = "PSNG_TCP_PORTSCAN" SSHSCAN = "SSH insecure connection attempt (scan)." SSHSCAN2 = "Possible attack on the ssh server (or version gathering)." if classification != NMAPPSNG and classification != NMAPFSCAN and classification != TCPPSCAN and classification != NMAPSCAN and classification != SSHSCAN and classification != SSHSCAN2 and classification != NMAPSCANUDP: return source = idmef.Get("alert.source(*).node.address(*).address") for saddr in source: ctx = Context(("NETWORK_INFO_PORTSCAN_ATTACKER", saddr), { "expire": 600, "alert_on_expire": True }, update = True, idmef=idmef) if ctx.getUpdateCount() == 0: ctx.Set("alert.correlation_alert.name", "Network scan of host(s) detected" ) ctx.Set("alert.classification.text", "Network information for scanning host") ctx.Set("alert.assessment.impact.severity", "high") # only create one alert per source # GeoIP # only do GeoIP lookup if IP address is not private if saddr.find("10.", 0, 4) != -1 or saddr.find("172.", 0, 4) != -1 or saddr.find("192.", 0, 4) == -1: # if GeoIP City Database exists if os.path.exists("/usr/share/GeoIP/GeoLiteCity.dat") == True: import GeoIP gi = GeoIP.open("/usr/share/GeoIP/GeoLiteCity.dat",GeoIP.GEOIP_STANDARD) geoinfo = gi.record_by_addr(saddr) geo = re.sub(r'\'', r'', re.sub(r': ', r':', str(geoinfo)) ) idmef = IDMEF() idmef.Set("alert.classification.text", "Geographical Information for portscanning host") idmef.Set("alert.correlation_alert.name", geo ) idmef.Set("alert.assessment.impact.severity", "high") idmef.Set("alert.assessment.impact.description", "Geographical information for portscanning host " + saddr) idmef.alert() ctx.update(idmef=idmef) # else if only GeoIP Country Database exists elif os.path.exists("/usr/share/GeoIP/GeoIP.dat") == True: import GeoIP gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE) idmef = IDMEF() idmef.Set("alert.classification.text", "Geographical Information for portscanning host") idmef.Set("alert.correlation_alert.name", str(gi.country_code_by_addr(saddr)) ) idmef.Set("alert.assessment.impact.severity", "high") idmef.Set("alert.assessment.impact.description", "Geographical information for portscanning host " + saddr) idmef.alert() ctx.update(idmef=idmef)