"У нее на футболке написано: «Мы ненавидим ненависть». "
Тибор Фишер - "Путешествие на край комнаты"
Для сетевого контроля своей сети очень полезно использовать систему обнаружения вторжений. Промышленным стандартом является простая и удобная система Snort.
Snort - система обнаружения вторжения, способная анализировать трафик в реальном масштабе времени. }{ уже не раз писал об этой программе, поэтому я не буду описывать процесс установки и настройки программы. Последнюю версию всегда можно скачать на официальном сайте программы, что, кстати, очень актуально, так как в предыдущих версиях недавно была обнаружена уязвимость. Там же скачиваем набор правил для анализа и мануалы по их самостоятельному написанию 🙂
Итак, Snort установлен и настроен, теперь пора автоматизировать анализ его логов. Не собираетесь ведь вы вручную их анализировать? 🙂 Для получения статистики по атакам можно использовать замечательный скрипт snortalog. Он выведет вам топ самых популярных атак на ваш сервер. Ваша персональная Чартова дюжина 🙂
Для Snort-а существует множество различных надстроек и утилит, но во всех этих утилитах мне страшно не хватало оперативного сообщения об атаке. Я не жадный - письма на e-mail и смс-ки на мобильник мне вполне хватит :).
Сказано - сделано 🙂 Так как я использую несколько snort-датчиков, причём не только на сервере с FreeBSD, но и в виде сервиса на рабочих машинах под Windows, я решил написать скрипт на Perl-е. Я не специализируюсь в программировании на Perl-е и, возможно, многое можно было сделать лучше, но главный плюс моего скрипта - это его простота, а также то, что он работает.
Скрипт анализирует файл alert ( в который Snort записывает предупреждения о возможных атаках) и отсылает предупреждение на заданный e-mail. Для получения sms-ок можно использовать существующую возможность уведомления о входящей почте (для чего и вводится модификация переменной $adminmail_from - чтобы в имени отправителя сохранялось описание атаки) или использовать sms-гейт вашего оператора (просто внесите нужные изменения в функцию send_email).
#!/usr/bin/perl -w
############################################################
#
# for analyse Snort alerts (with option '-A full')
#
# XIII
############################################################
#
# <noonv13@gmail.com>
#
# version: 1.0
#
# используем сокеты для непосредственного общения с smtp-серверами
use Socket;
################################################################
# здесь устанавливаем пути к файлам
# $alerts_file - alert.ids - файл алертов Snort-a
# $alertstr_file - alert.str - наш файл для хранения числа строк, уже проанализированных скриптом
# path to Snort alerts -file
$alerts_file = "c:/util/Snort/log/alert.ids";# "/var/log/snort/alert";
# path to my string-number of alerts ( enable it for wtiting ! )
$alertstr_file = "c:/util/Snort/log/alert.str"; # "/var/log/snort/alert.str";
# здесь перечислим те предупреждения, которые мы будем игнорировать
# просто пару дней погоняй скрипт с полной отсылкой алертов и
# сам поймёшь, что бы ты хотел игнорировать :)
@alerts4ignor = #("XXXXXXXXXXXXXXXXX"); # place it for send all alerts :)
("ICMP L3retriever Ping",
"ICMP redirect host",
"unicode share access");
# $adminmail - e-mail для отправки алертов
# $smtp - наш smtp-сервер
# $subject - тема письма - на неё нужно будет настроить фильтр в своём почтовике
# $host_name - имя датчика, которое будет добавлено в тело письма
$adminmail = 'root@host.ru';
$adminmail_from = ""; # keep it "" (empty) if script mast generate FROM %)
$smtp = "smtp.rgs.ru";
$subject = "[!] snort alert [!]";
$host_name = "Frankensteine";
################################################################
# открываем файл и считываем число строк, уже проанализированных нашим скриптом
open FILE0, $alertstr_file or die "Can't open $alertstr_file $!\n";
$counter = 0;
$lines_for_ignor = 0;
while ( <FILE0> )
{
$lines_for_ignor = $_;
#printf $lines_for_ignor;
$counter++;
}
if($counter >1)
{
printf "[!] error in file $alertstr_file!\n";
}
printf "[i] ignor lines: $lines_for_ignor\n";
close FILE0 or die "Can't close FILE: $!\n";
#
# #########################################
#
# открываем файл алертов
open FILE, $alerts_file or die "Can't open $alerts_file $!\n";
$counter = 0;
$sendalert = 0; # flag for send alert on e-mail
@lines = ("","","","","","","","","",""); # for store lines of alert
$message=""; # message for send
$alert=""; # alert message ( usually - first string )
print "\n";
$OS = $^O;
$readed_lines = 0;
#
# main cycle %)
#
while ( <FILE> )
{
# пропускаем нужное количество строк
#
# ignor lines here 8)
#
$readed_lines++;
if($readed_lines < $lines_for_ignor)
{
next
}
if($_ le "\r\n")
{
print "[i] here alert! str: $counter\n";
$sendalert = 1; # set default for send alert
$i=0;
# анализируем - есть ли предупреждение в списке игнорируемых и если нет - отправляем письмо
analyse_alert();
if($sendalert)
{
if ($counter) # check on empty rules %)
{
send_email();
}
else
{
print "[i] here nothing to send\n";
}
}
$counter = 0;
clear_mas();
}
else
{
$lines[$counter]=$_;
$counter++;
}
}
close FILE or die "Can't close FILE: $!\n";
# сохраняем в файл число проанализированных строк файла алертов
#
open FILE0, ">$alertstr_file" or die "Can't open $alertstr_file for writing$!\n";
print FILE0 "$readed_lines";
close FILE0 or die "Can't close FILE: $!\n";
####
# exit here
printf "OS: $OS\n";
#########################################
#
sub clear_mas
{
$i=0;
foreach $lvar (@lines)
{
$lvar="";
$i++;
}
}
#
# analyse alert
#
sub analyse_alert
{
foreach $ignor (@alerts4ignor)
{
foreach $lvar (@lines)
{
if( $lvar =~ /$ignor/ )
{
print "[i] ignor this alert :)\n";
$sendalert = 0;
}
}
}
}
# функция отправки e-mail-ов
# сначала формируем предупреждение и переменную для поля FROM:
# затем общаемся с smtp-сервером и отправляем письмо
#
sub send_email
{
printf "[i] send e-mail on $adminmail\n";
$message="";
#
$i=0;
foreach $lvar (@lines)
{
#
# get alert string here :)
#
if(!$i) # ($lvar =~ /[\*\*]/)
{
$alert = $lvar;
}
$message = $message.$lvar;
$i++;
}
#
# example of alert:
# [**] [1:466:5] ICMP L3retriever Ping [**]
#
$alert2 = $alert;
$alert2 =~ s/\[\*\*\]//g; # remove [**]
$alert2 =~ s/ //g; # remove ' '
$alert2 =~ s/\[\d+:\d+:\d+\]//g; # remove [1:466:5]
$alert2 =~ s/\$/_/g; # replace bad symbols
$alert2 =~ s/\n//g; # replace '\n'
if($adminmail_from)
{
$email_from = $adminmail_from;
}
else
{
$email_from=$alert2."_".$adminmail;
}
$email_to=$adminmail;
$email_subject=$subject;
$attachment = "";
##
$host=$smtp;
print "$host\n";
$port="25";
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
$iaddr = inet_aton($host);
$paddr = sockaddr_in($port, $iaddr);
connect(SOCK, $paddr);
send (SOCK, "HELO $host\r\n", 0);
$data=<SOCK>;
send (SOCK, "MAIL FROM: <$adminmail>\r\n", 0);
$data=<SOCK>;
send (SOCK, "RCPT TO:<$email_to>\r\n", 0);
$data=<SOCK>;
send (SOCK, "DATA\r\n", 0);
$data=<SOCK>;
send (SOCK, "From:<$email_from>\nTo:<$email_to>\nSubject:$email_subject\n\n$host_name\n$message\r\n", 0);
$data=<SOCK>;
send (SOCK, "\.\r\n", 0);
$data=<SOCK>;
send (SOCK, "QUIT\n\r", 0);
$data=<SOCK>;
close(SOCK);
}
Осталось прописать запуск скрипта в crontab с нужной вам регулярностью (например - каждую минуту) и ждать писем. Для датчиков под Windows автозапуск скрипта можно реализовать, используя отличную утилиту nncron - вариант cron-a для win. Остальное уже на ваш вкус, например, я в своём почтовике настроил фильтр, чтобы все alert-ы скидывались в нужную папку и проигрывалось знаменитое "we are under attack!".
Уф! Вот и всё! Как и обещал - всё очень просто :).
Теперь, попивая на природе пиво с друзьями, вы всегда получите предупредительную sms-ку. На вопрос друзей можете этак лениво ответить - "да вот какой-то умник, возомнивший себя хакером, пытается взломать мой сервер". К сожалению, я уже не смог остановиться и в новую версию скрипта добавил немного функциональности; чтобы он не просто оповещал нас об атаке, но и предпринимал некоторые активные действия. Но об этом - в следующий раз.
До встречи в сети!
Ссылки:
- Snort :
http://www.snort.org - Домашняя страница Snortalog:
http://jeremy.chartier.free.fr/snortalog/ - nncron:
- http://www.nncron.ru
- Последнюю версию Snortalert-а всегда можно найти здесь:
http://www.noonv.h1.ru/se/snortalert.pl