Les scripts de détection

Voici les scripts de détection. Ils nécessitent la librairie DBI, et File::Tail

detection_agression.pl

#!/usr/bin/perl
##################################################################################
use File::Tail;
use DBI();
use strict;
use POSIX qw(setsid);
use Sys::Syslog qw(:DEFAULT setlogsock);
 
 
my $rotation_max=1000;
my $syslog_facility="local6";
my $syslog_ident="detection_agression";
my $syslog_priority="warning";
 
########################################################################
#
#	Variables normales
#
my (%attr,$option,$verbose,$key,$value,$action);
my $syslog_socktype = 'unix'; # inet, unix, stream, console
my $syslog_options="pid";
 
my (%attr,$option,$verbose,$key,$value,$action);
 
my $ip;
my $line;
my $file;
my $timestamp;
my $nb_rotations=0;
my $dbh;
my ($interne,$destination,$raison);
my $resultat;
my $debug=0;
 
if (! $debug)
	{
	# On vide le buffer et on se lance en daemon
	$| = 1;
	daemonize();
	setlogsock $syslog_socktype;
	openlog $syslog_ident, $syslog_options, $syslog_facility;
	db_connect();
	}
 
$file=File::Tail->new("/var/log/messages");
while (defined($line=$file->read))
	{
	chop($line);
	undef $ip;
	undef $raison;
	$interne="0";
	$destination="0.0.0.0";
	#
	#	Détection des Infractions
	#
	if ($line =~ /QUARANTAINE/o)
		{
		$ip=$line;
		$ip=~ s/^.*SRC=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
		$raison="IDEM";
		}
	elsif ($line =~ /sshd/io)
		{
		$raison="Echec SSH";
		if ($line =~ /sshd.*Failed password for illegal user from .* port .* ssh2/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		elsif ($line =~ /sshd.*Failed password for \S+ from .* port .* ssh2/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		elsif ($line =~ /sshd.*Invalid user.* from/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		elsif ($line =~ /sshd.*Illegal user.* from/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		elsif ($line =~ /sshd.*Did not receive identification string from/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		}
	elsif ($line =~ /vsftpd/io)
		{
		$raison="Echec VSFTPD";
		if ($line =~ /vsftpd.*: authentication failure; logname= uid=0 euid=0 tty= ruser=.* rhost=[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/io)
			{
			$ip=$line;
			$ip=~ s/^.*from ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$/$1/;
			}
		}
	elsif ($line =~ /proftpd/io)
		{
		$raison="Echec PROFTPD";
		if ($line =~ /proftpd.*: \S+ \(\S+\) - USER \S+: no such user found from \S+ \[[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\]/io)
			{
			$ip=$line;
			$ip=~ s/^.*\[([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\].*$/$1/;
			}
                elsif ($line =~ /proftpd.*: \S+ \(\S+\[[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\]\) - USER \S+ (Login failed): No such user found./io)
                        {
                        $ip=$line;
                        $ip=~ s/^.*\[([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\].*$/$1/;
                        }
		}
	elsif ($line =~ /snort/gio)
		{
		if ($line =~ /WEB-(CGI|ATTACKS|PHP|MISC|IIS|FRONTPAGE|COLDFUSION)/go)
			{
			$ip=$line;
			$ip=~ s/^.*TCP} ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):[0-9]+ .*$/$1/;
			$destination=$line;
			$destination=~ s/^.* ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):[0-9]+ $/$1/;
			$raison=$line;
			$raison=~ s/^.*\] (WEB-(CGI|ATTACKS|PHP|MISC|IIS|FRONTPAGE|COLDFUSION).+) \[Classification.*$/$1/;
			$raison=~ s/[^a-zA-Z0-9\/\-\.:, ]/_/g;
			}
		}
	#
	#	Si une IP est contrevenante
	#
	if (($ip) && ($ip =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/io))
		{
		if ($debug)
			{print "$ip\t$timestamp\t$interne\t$raison\t$destination\n";}
		else
			{
			$resultat=$dbh->do("INSERT DELAYED INTO ip_dangereuses
				SET	ip = \"$ip\",
					timestamp=NOW(),
					interne=\"$interne\",
					raison=\"$raison\",
					destination=\"$destination\"
				");
			if (!$resultat)
				{
				syslog $syslog_priority, "%s", "Reconnexion a la base de donnees";
				sleep(10);
				$dbh->do("COMMIT");
				$dbh->disconnect();
				db_connect();
				}
			}
		}
	$nb_rotations++;
	if (($nb_rotations > $rotation_max) && (! $debug))
		{
		$nb_rotations=0;
		$dbh->do("COMMIT");
		}
	}
$dbh->do("COMMIT");
$dbh->disconnect();
 
############################################################################
#
#	Routines
#
sub db_connect() {
$dbh = DBI->connect(    "DBI:mysql:database=gestion_reseau;host=serveur_mysql.univ-tlse1.fr", 
                        "utilisateur", 
                        "mot_de_passe",
                        {'RaiseError' => 1}
                );
if (!$dbh)
	{
	die ("Erreur de connexion à la base gestion_reseau");
	}
}
 
sub daemonize {
	chdir '/'		  or die "Can't chdir to /: $!";
	open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
	open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
	open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
	defined(my $pid = fork)   or die "Can't fork: $!";
	exit if $pid;
	setsid  		  or die "Can't start a new session: $!";
	umask 0;
	my $myname=$0;
	$0=$myname;
}

Schéma de la Base de données

--
-- Table structure for table `ip_dangereuses`
--
 
DROP TABLE IF EXISTS `ip_dangereuses`;
CREATE TABLE `ip_dangereuses` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `ip` VARCHAR(15) NOT NULL DEFAULT '',
  `destination` VARCHAR(15) NOT NULL DEFAULT '',
  `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `interne` tinyint(4) NOT NULL DEFAULT '0',
  `raison` VARCHAR(50) NOT NULL DEFAULT '',
  PRIMARY KEY  (`id`),
  KEY `idx_ip` (`ip`),
  KEY `idx_destination` (`destination`),
  KEY `idx_timestamp` (`timestamp`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

script init

Voici le script /etc/init.d/quarantaine

#!/bin/sh
#
# detection_agression         Start/Stop quarantaine.
#
# chkconfig: 2345 40 60
# description:  quarantaine is a very lightweight network intrusion detection tool \
# processname: detection_agression.pl
 
# Source function library.
. /etc/init.d/functions
 
lockfile="/var/lock/subsys/detection_agression"
prog="Detection"
executable="/usr/local/etc/quarantaine/detection_agression.pl"
RETVAL=0
 
start() {
	echo -n $"Starting $prog: "
	daemon $executable $OPTIONS
	RETVAL=$?
	echo
	[ $RETVAL -eq 0 ] && touch $lockfile
        return $RETVAL
}
 
stop() {
	echo -n $"Stopping $prog: "
	killproc  $executable
	RETVAL=$?
	echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile
	return $RETVAL
}
 
dostatus() {
	status $executable
}
 
restart() {
	stop
	start
}
 
condrestart() {
	[ -e $lockfile ] && restart
}
 
# See how we were called.
case "$1" in
  start)
	start
	;;
  stop)
	stop
	;;
  status)
	dostatus
	;;
  restart|reload)
	restart
	;;
  condrestart)
	condrestart
	;;
  *)
	echo "Usage: $0 {start|stop|status|restart|condrestart}"
	exit 1
esac
 
exit $RETVAL