суббота, 20 июля 2019 г.

Парсим лог Exim (борьба с Brute force)

Обратил внимание, что в логах Exim присутствуют вот такие сюжеты:

2019-07-19 07:08:51 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=alison@com.ua)
2019-07-19 07:08:51 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=staples@com.ua)
2019-07-19 07:09:00 LOGIN authenticator failed for (User) [103.231.139.130]: 535 Incorrect authentication data (set_id=blackbox@com.ua)
2019-07-19 07:09:52 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=phrases@com.ua)
2019-07-19 07:09:55 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=hahaha@com.ua)
2019-07-19 07:10:07 LOGIN authenticator failed for (User) [103.231.139.130]: 535 Incorrect authentication data (set_id=aviation@com.ua)
2019-07-19 07:10:54 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=techniques@com.ua)
2019-07-19 07:10:58 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=packard@com.ua)
2019-07-19 07:11:13 LOGIN authenticator failed for (User) [103.231.139.130]: 535 Incorrect authentication data (set_id=1254@com.ua)
.............................
2019-07-19 07:19:07 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=fester@com.ua)
2019-07-19 07:19:26 LOGIN authenticator failed for (User) [122.155.174.36]: 535 Incorrect authentication data
2019-07-19 07:19:27 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=252525@com.ua)
2019-07-19 07:20:08 LOGIN authenticator failed for (User) [103.231.139.130]: 535 Incorrect authentication data (set_id=641@com.ua)
2019-07-19 07:20:08 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=gangsta@com.ua)
2019-07-19 07:20:31 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=oscar@com.ua)
2019-07-19 07:20:46 LOGIN authenticator failed for (User) [185.234.218.126]: 535 Incorrect authentication data (set_id=feed)
2019-07-19 07:21:10 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=fucku2@com.ua)
2019-07-19 07:21:15 LOGIN authenticator failed for (User) [103.231.139.130]: 535 Incorrect authentication data (set_id=personalfinance@com.ua)
2019-07-19 07:21:35 LOGIN authenticator failed for (User) [185.137.111.23]: 535 Incorrect authentication data (set_id=brother@com.ua)
2019-07-19 07:22:11 LOGIN authenticator failed for (User) [185.137.111.123]: 535 Incorrect authentication data (set_id=freeze@com.ua)
Естественно, мне такое понравиться не могло. Хотя у взломщиков, использующих формат @com.ua и нету особых шансов, но зачем они мне будут грузить сервер?

Принял решение блокировать с помощью файрвола, для этого нужны IP наших героев и мы будем получать их из лога.
Преимущества такого подхода:
  1. Ротация логов естественным образом решает вопрос времени жизни блокировки.
  2. Установка порога вхождения в блокировку (например 3 раза в логе) защищает пользователей ошибшихся паролем.
Вот такая строка выдаст отсортированный список IP:
awk '/LOGIN authenticator failed / {print $8}' /var/log/exim/mainlog | tr -d '[]:' | sort
Получаю следующий вывод:

45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
45.227.253.213
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
5.135.188.105
51.68.229.24
51.68.229.24
61.154.64.91
61.154.64.91
61.154.64.91
61.154.64.91
61.154.64.91
61.154.64.91
78.128.113.67
78.128.113.67
78.128.113.67
78.128.113.67
78.128.113.67
Осталось передать его файрволу для блокировки, в моем случае просто заполнить таблицу IPFW. Сделаю это на Python:

#!/usr/bin/env python3.6
# -*- coding: utf8 -*-
import subprocess,os,sys,string
srcips=str(subprocess.check_output("awk '/LOGIN authenticator failed / {print $8}' /var/log/exim/mainlog | tr -d '[]:' | sort",shell=True)).split('\\n')
ips=[]
for i in srcips:
    if (i !="'") and (i not in ips) and (srcips.count(i)>2):
        ips.append(i)
        subprocess.call(["/sbin/ipfw", "table", "5", "add", i])
Получилось как-то так. Добавляем в crontab и успокаиваемся на достигнутом.

P.S.

Чтоб не усложнять скрипт не делал проверку на наличие записей в таблице файрвола, если она уже есть он просто выдаст сообщение.

P.P.S.

Естественно, при использовании другого файрвола скрипт надо адаптировать к нему.

P.P.S.2

Прошли выходные и можно подвести первый итог:

awk '/LOGIN authenticator failed / {print $1, $2, $8}' /var/log/exim/mainlog
2019-07-23 05:00:11 [185.137.111.123]:
2019-07-23 05:00:34 [185.137.111.23]:
2019-07-23 05:01:21 [185.137.111.123]:
2019-07-23 05:01:27 [185.137.111.132]:
2019-07-23 05:01:43 [185.137.111.23]:
2019-07-23 06:00:06 [185.137.111.123]:
2019-07-23 06:00:49 [185.137.111.132]:
2019-07-23 06:01:14 [185.137.111.23]:
2019-07-23 06:01:18 [185.137.111.123]:
2019-07-23 07:00:09 [185.137.111.123]:
2019-07-23 07:00:15 [185.137.111.132]:
2019-07-23 07:00:51 [185.137.111.23]:
2019-07-23 07:01:15 [185.137.111.123]:
2019-07-23 07:01:56 [185.234.216.164]:
2019-07-23 07:02:02 [185.137.111.23]:
2019-07-23 07:02:04 [185.137.111.132]:
Как видим активность наших друзей проявляется теперь только в 2 первые минуты каждого часа - это связано с тем, что у меня  другой скрипт в 0 минут каждого часа очищает используемую скриптом таблицу IPFW и тоже потом ее заполняет другими нехорошими IP, а вышеприведенный скрипт запускается во 2-ю минуту каждого часа, поставлю запуск на 1-ю минуту, думаю 1-й скрипт будет успевать отрабатывать. Как вариант можно в начале скрипта сделать паузу до 5 секунд, чтоб 1й скрипт успел очистить таблицу и они паралельно ее заполняли(подумаю об этом завтра по активности товарищей).
Вот так выглядит на данный момент таблица файрвола:

ipfw table 5 list
--- table(5), set(0) ---
45.227.253.214/32 0
103.231.139.130/32 0
122.155.174.36/32 0
185.137.111.23/32 0
185.137.111.123/32 0
185.137.111.132/32 0
185.234.216.105/32 0
185.234.216.164/32 0
185.234.218.126/32 0
193.169.252.174/32 0
203.163.247.143/32 0
Переделал скрипт в модуль для запуска как автономно, так и из других скриптов

Комментариев нет:

Отправить комментарий