#!/bin/sh ############################################################################# ## Script de déconexion/reconnexion automatique pour virus de type blaster ## ## ## ## Principe : ## ## -> détection des attaques grâce aux logs du firewall ## ## lecture par *_scan.awk ## ## -> à partir du nombre d'attaques et de l'heure de dernière attaque ## ## déconnecte ou reconnecte des machines ## ## ## ## Frédéric Pauget 02/2003 ## ## 07/2004 adaptation pour scan de plusieurs types d'attaques ## ############################################################################# is_up() { # Supression de la machine dans la table arp /usr/sbin/arp -d $1 2> /dev/null # Teste si la machine founie est up if fping -c1 $1 > /dev/null 2>&1 ; then # Elle a répondu au ping return 0 fi if /usr/sbin/arp $1 2>/dev/null | egrep -q '(no entry|incomplete)' ; then # Elle n'est pas dans la table ARP return 1 else # Elle est dans la table ARP return 0 fi } if [[ $1 ]] && [[ $1 = "--real-run" ]]; then dry=false else dry=true fi BLACKLIST_FINAL='/tmp/virus_blacklist' # Logs du firewall FW_LOGS=/var/log/firewall/filtre.log # Prétraitement logs tail -7200 $FW_LOGS > /tmp/fw_logs_light # Fonction utile : retourne l'IP d'une machine ip() { echo $(host $1 2>/dev/null | awk '{print $3}') } # Fonction principale scan() { # signification des arguments : # 1 : nombre d'attaques pour être considéré infecté # 2 : nombre de secondes sans attaques pour être considéré sain # 3 : script de scan # 4 : repertoire de stockage fichiers nb_att=$1 nb_sec=$2 SCRIPT=$3 # Liste des attaques INFECTES=$4/infectes # Machines décontaminées RECO=$4/reconectes # Machines blacklistées BLACKLIST=$4/blacklist # Fichiers temporaires supplémentaires DIFF=/tmp/virus_diff TMPFILE=/tmp/virus_scan # Doit exister, même vides touch $RECO touch $BLACKLIST if ! [[ -e $INFECTES ]]; then dry=true echo "dry-run mode forcé (fichier absent)" touch $INFECTES fi # Test préliminaire if [[ ! -e $SCRIPT ]] ; then echo "Erreur : $SCRIPT non trouvé" exit 255 fi # Conversion blacklist hostname -> IPs if [[ "$(head -1 $BLACKLIST)" == "komaz" ]]; then echo "Ancienne blackliste vide" touch $BLACKLIST.ip else echo "Conversion blackliste..." for i in $(cat $BLACKLIST | sort | uniq) do ip $i done > $BLACKLIST.ip fi echo "Détection des infectés..." $SCRIPT $BLACKLIST.ip /tmp/fw_logs_light > $TMPFILE # sort un fichier du type : # Mois Jour Heure hostname nb d'attaques depuis les dernier logrotate echo "Traitement..." mv $INFECTES $INFECTES.old sort -r $TMPFILE > $INFECTES echo -n "" > $TMPFILE # Différencee entre le fichier obtenu la au dernier lancement et le nouveau diff -U 1000 $INFECTES.old $INFECTES | egrep -v '\-\-\-|\+\+\+|@@' > $DIFF if ! [[ -s $DIFF ]]; then echo "Aucun changement par rapport au dernier scan." cp $INFECTES $DIFF fi # Traitement par host for host in $(awk '{print $4}' $DIFF | sort | uniq) do if grep -q "\+.* $host " $DIFF && grep -q "\-.* $host " $DIFF ; then # En + et - : variation nb=$(echo $(awk '$4=="'$host'" {print $5}' $INFECTES) - $(awk '$4=="'$host'" {print $5}' $INFECTES.old) | bc) echo -ne "Variation ($nb) " if grep -q "^$host$" $BLACKLIST ; then # Déja blacklisté, on remet echo -ne "\033[1;31m(RESTE) " echo $host >> $TMPFILE elif [[ $nb -gt $nb_att ]] ; then # Nouveau echo -ne "\033[1;31m(NOUVEAU) " echo $host >> $TMPFILE else # Pas assez de tentatives echo -n "(PASSE) " fi elif grep -q "\+.* $host " $DIFF ; then # Que en + donc c'est un nouveau nb=$(awk '$4=="'$host'" {print $5}' $INFECTES) if [[ $nb -gt $nb_att ]] ; then echo -ne "\033[1;31mNOUVEAU ($nb) " echo $host >> $TMPFILE else echo -ne "PASSE ($nb) " fi elif grep -q "\-.* $host " $DIFF ; then # Que en -, c'est un coup de logrotate, on remet les blacklistés. if grep -q "^$host$" $BLACKLIST ; then echo "RESTE : $host" echo $host >> $TMPFILE else echo "Vieux : $host" fi else # Pas de variation if grep -q "^$host$" $BLACKLIST ; then echo -n "Pas de variation " # UP or not ? if is_up $host ; then # UP last=$(date -d "$(awk '$4=="'$host'" {print $1" "$2" "$3}' $INFECTES)" +%s 2>/dev/null) # Cas ou c'est vraiment trop vieux if [[ -z $last ]] ; then last=0 fi now=$(date +%s) t=$(echo "$now-$last" | bc) if [[ $t -gt $nb_sec ]] ; then # Reconexions automatique echo -n " reconnexion" echo $host >> $RECO else echo $host >> $TMPFILE fi else # Down echo -ne "\033[1;41m(NO_PING)" echo $host >> $TMPFILE fi echo -ne "\033[0m : " else echo -n "Reste connecté " fi fi echo -ne "\033[0m" awk '$4=="'$host'" {print $1" "$2" "$3" "$4}' $INFECTES done # Opérations finales sort $TMPFILE > $BLACKLIST } ####################################################################### # Scan des attaques sur le 135 : # 10 tentatives pour être considéré infecté # 1h sans attaque pour être considéré désinfecté echo -e "\033[1;33m###############################\nScan attaques port 135 ou 6667\033[1;0m" scan 10 3600 /usr/scripts/analyse_komaz/rpc_scan.awk /var/tmp/rpc # Scan des floods : # 100 tentatives pour être considéré infecté # 1h sans attaque pour être considéré désinfecté echo -e "\033[1;33m###############################\nScan floods\033[1;0m" scan 100 3600 /usr/scripts/analyse_komaz/flood_scan.awk /var/tmp/flood # Constitution de la blackliste finale cat /var/tmp/rpc/blacklist /var/tmp/flood/blacklist | sort | uniq > $BLACKLIST_FINAL.new if ! [[ -s $BLACKLIST_FINAL.new ]]; then # Il n'y a personne, il faut au moins une machine sinon squid aime pas. echo 'komaz' > $BLACKLIST_FINAL.new fi if ! $dry ; then if diff -q $BLACKLIST_FINAL $BLACKLIST_FINAL.new ; then echo "Pas de changement dans la blackliste" else # Synchro blacklist /usr/bin/rsync -C -a -e "ssh -i /usr/scripts/analyse_komaz/keys/synchro_virus" $BLACKLIST_FINAL.new root@sila.crans.org:/etc/squid/blacklist_infectes # Reload de squid /usr/bin/ssh -o StrictHostKeyChecking=no -i /usr/scripts/analyse_komaz/keys/reload_squid root@sila.crans.org squid reload fi else echo "Dry mode : blackliste non copiée sur sila et squid non relancé" echo "Utiliser l'option --real-run pour tout faire." fi # On ne garde que la dernière version de la blacklist mv $BLACKLIST_FINAL.new $BLACKLIST_FINAL