Accueil

brute_force.pl

Par Serge.

Ce script permet de détecter toute tentative de connexion SSH en essayant toute une série de nom d'utilisateur et de mot de passe: technique dite "brute force".

Sommaire

Utilisation

Tout d'abord, modifiez la variable my @WHITELIST pour ajoutez les adresse IP que vous ne voulez jamais blacklister (pour eviter de vous auto-blacklister).

Ensuite, le script execute un script externe à chaque détection d'attaque. Dans mon cas je relance mon script de firewall (/etc/rc.d/rc.firewall) qui relis le fichier des IPs blacklister pour les prendre en compte. Vous pouvez bien sur faire executer le script de votre choix, pour cela modifiez la variable my $EVENT en début du script

Enfin, lors de son execution vous devez passez 3 arguments à ce script:

  1. Le fichier de log ou les tentative de connection ssh apparaissent, /var/log/messages pour la slackware.
  2. Le fichier de cache pour le fonctionement du script en lui même que vous choisissez, par exemple /var/cache/force.db
  3. Le fichier dans lequel le script va ajouter l'adresse des IP à blacklister, par exemple /var/blacklist

Installation

Copier ce script dans un répertoire de votre choix (/usr/local/sbin par exemple) et changez les permissions:

chmod 700 /usr/local/sbin/ssh_force.pl
chown root:root /usr/local/sbin/ssh_force.pl

Puis editez, en root la crontab (tapez contrab -u) pour y placez cette ligne:

#ssh_force
*/1 * * * * /usr/local/sbin/ssh_force.pl /var/log/messages /var/cache/force.db /var/blacklist

pour que le script soit executer chaque minute.

Le script

#! /usr/bin/perl -W

#
#
# Find and return IP of ssh brute attacks
# This is done by incrementally reading the log file

use strict;

#
# Min time between two check.
#
my $MINRESET = 55;

# How many tries before blacklist IP
my $THRESOLD = 5;

# IPs or IP mask that will never be blacklisted
my @WHITELIST=("127.0.0.1", "192.168.0", "82.244.5.110");

# Command to run if we have blacklisted some IPs
my $EVENT="/etc/rc.d/rc.firewall restart";
if ( @ARGV < 3 )
        {
        print <<EOF
        usage: ssh_user.pl <sshlog> <db file>

        where:
        <sshlog>          Log file where ssh auth comes.
        <db file>         File for logging statistics and timestamp data.
        <blacklist>       File to store blacklisted IPs
EOF
        ;
        exit;
        }

my $logFile  = $ARGV[0];
my $dbFile   = $ARGV[1];
my $blacklist = $ARGV[2];
my $event=0;

# Be sure that logfile exist
(my @lf = stat $logFile) || die( "Cannot stat log file `".$logFile."'!" );

# If blacklist file does not exist, we create it
my @bf = stat ($blacklist);
if (! @bf)
        {
 open ( BLACKLIST, ">".$blacklist) || die ("Cannot write blacklist file `".$blacklist."'!" );
        close ( BLACKLIST );
        }

# dbfile store the last position in logfile

my @st = stat $dbFile;
my $timeSinceUpdated=0;
my $logPosition=0;
my $dontblack;
my %count;
my $ip_cur;

# Create dbfile if not exist
if ( ! @st )
        {
        $timeSinceUpdated = 99999999;
        $logPosition      = 0;
        }
else
        {
        # If dbfile exist, get the last cur pos and last check time
        $timeSinceUpdated = time()-$st[9];
        open( DBFILE, $dbFile ) || die( "Cannot open db file `".$dbFile."'!" );
        $logPosition=<DBFILE>;
        close( DBFILE );
        if ( $logPosition > $lf[7] )
                {
                # Log has been truncated since last run.
                $logPosition = 0;
                }
        }

if ( $timeSinceUpdated > $MINRESET )
# We have to do the job
        {
        open( LOGFILE, $logFile ) || die( "Cannot open log file `".$logFile."'!" );
        seek( LOGFILE, $logPosition, 0 );
        while( <LOGFILE> )
                {
                chomp();
                @_ = split();
                if ( /sshd/ && /Failed password for/)
                        {
                        $dontblack=0;
                        # If user is invalid, IP is in 13 position, if user exist IP is in 11 position
                        if ( $_[8] =~ /invalid/)
                                {
                                if ( $_[12] =~ /\d+\.\d+\.\d+\.\d+/ )
                                        {                               
                                        ip_cur=$_[12];
                                        $count{$ip_cur}++;
                                        }
                                }
                        else
                                {
                                if ( $_[10] =~ /\d+\.\d+\.\d+\.\d+/ )
                                        {
                                        $ip_cur=$_[10];
                                        $count{$ip_cur}++;
                                        }
                                }
                        open ( BLACKLIST, $blacklist) || die ("Cannot open blacklist file `".$blacklist."'!" );
                        while ( <BLACKLIST> )
                                {
                                # IP is already blacklisted
                                if ( /$ip_cur/ )
                                        {
                                        $dontblack=1;
                                        }
                                }
                        close ( BLACKLIST );
                        foreach my $whiteip (@WHITELIST)
                                {
                                # IP is in whitelist
                                if ( $ip_cur =~ /$whiteip/)
                                        {
                                        $dontblack=1;
                                        }
                                 }
                        if ($dontblack == "0" &&  $count{$ip_cur}>=$THRESOLD)
                                        {
                                        # Ip must be blacklisted
                                        open ( BLACKLIST, ">>".$blacklist) || die ("Cannot write blacklist file `".$blacklist."'!" );
                                        print BLACKLIST $ip_cur."\n";
                                        $event=1;
                                        close ( BLACKLIST );
                                        }
                        }
                }
        # Store the pos and check time
        open( DBFILE, ">".$dbFile ) || die( "Cannot write to db file `".$dbFile."'!" );
        print DBFILE tell(LOGFILE)."\n";
        close( DBFILE );
        }

if ($event==1)
        {
        # We must run the command
        system ($EVENT);
        }

Thèmes : #administration #scripts #serge

Sauf indication contraire, ce document est placé sous licence CC-BY-SA 3.0.