• Партнер

  • "У нее на футболке написано: «Мы ненавидим ненависть». "
    Тибор Фишер - "Путешествие на край комнаты"

    Для сетевого контроля своей сети очень полезно использовать систему обнаружения вторжений. Промышленным стандартом является простая и удобная система 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-ку. На вопрос друзей можете этак лениво ответить - "да вот какой-то умник, возомнивший себя хакером, пытается взломать мой сервер". К сожалению, я уже не смог остановиться и в новую версию скрипта добавил немного функциональности; чтобы он не просто оповещал нас об атаке, но и предпринимал некоторые активные действия. Но об этом - в следующий раз.

    До встречи в сети!

    Ссылки:

    Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии