Грязное место провайдера: проект blondemine

Грязное место провайдера: проект blondemine

В нашей компании имеется распределенная сеть продаж. Связь офиса с магазином обеспечивает маршрутизатор, на котором настроен VPN до центра. И вот, с определенного момента, эта связь стала крайне некачественной, из-за шквала пакетов по 53-му DNS порту. Связь хоть и улучшилась после введения блокирующих правил файрволла, но атаки не прекратились.

Я обратился к провайдеру, с просьбой решить проблему на его стороне. На что получил ответ вынесенный в заголовок: «Ну вы же понимаете, интернет — это грязное место». И тогда я решил бороться с этим явлением самостоятельно.

В результате была собрана система сбора и анализа несанкционированных сетевых пакетов. А чтобы не утомлять читателя техническими подробностями, самое интересное я расскажу сразу, а тем кто пожелает ее повторить или улучшить рекомендую дочитать до конца.

В результате почти двух месяцев работы, в систему поступило почти 200 миллионов записей. Большая часть (98%) — это атаки типа DNS amplification, которые не раз обсуждались на хабре [1], [2]. Причем атаки начинаются не сразу, а по прошествии некоторого времени, достаточного для попадания нового публичного адреса в базу сканирующих интернет ботов. В оставшейся части событий выделяется большой сегмент атак на 23-й порт. Как я выяснил — это китайские DVR системы Hikvision, разбросанные по всему миру и сканирующих весь интернет на предмет telnet подключений. На трети из них, кстати, как раз заводские логин и пароль. А все остальное — это уже рукотворные переборы портов, попытки залогиниться, опросить по snmp и прочее.

Как я до этого дошел

Для начала надо было настроить на всех удаленных маршрутизаторах файрвол. Вывел “образцовый” набор правил, проверил и начал настраивать. На восьмом маршрутизаторе мне это наскучило и я заглянул в журнал устройства: “vk.com не может подключится к компьютеру менеджера”, “youtube.ru не соединяется с кассой” и прочее, прочее. Но были и интересные записи: “src=1.1.1.1:34567 dst=Zyxel:23 dropped [4 times]”, “src=2.2.2.2:45678 dst=Zyxel:80 dropped [12 times]”.

Я решил просканировать эти адреса Nmap-ом: открыты 80-й и 22-й порты. Браузер сообщил, что первый адрес – это веб-камера в переговорной какого-то украинского предприятия (судя по geoip и whois), а второй это некий индийский ubiquiti маршрутизатор. Заводской логин и пароль сработали только на веб-камере, а вот с маршрутизатором заводские настройки оставили “всего лишь” на ssh!

Это ж какой «блондинкой» надо быть, чтобы выставить напоказ всему интернету устройство с заводским логином и паролем? И решил я таких «блондинок» собирать в одном месте и изучать. А в перспективе реализовать следующий алгоритм:

cбор атакующих — пассивный анализ — активный анализ — ответное действие

Шаг первый: сбор атакующих Центральный журнал

В маршрутизаторах Zyxel есть возможность отправлять журнал на центральный сервер syslog. Для этого я установил Linux Debian, а на него rsyslog:

Однако, простой установки, мало. Необходимо разрешить syslog-у принимать сообщения извне:

Ну а чтобы сей порт ловил данные из интернета, нужна еще трансляция на пограничном маршрутизаторе. В моем случае на Cisco я сделал так:

Теперь надо настроить удаленный маршрутизатор на отправку сообщений. В моем случае это Zyxel zywall 2Plus или USG20.

Модели этих маршрутизаторов отличаются достаточно сильно, как снаружи, так и изнутри. Однако весь смысл настройки сводится к отключению всех журналов, кроме файрволла, и отправке событий на syslog сервер. Вот как это выглядит на Zyxel USG 20: настройка firewall:

настройка событий журнала syslog:

настройка адреса и типа сервера syslog:

Еще в настройках устройства обязательно выставить значимое имя хоста — для удобства сортировки.

Первые результаты

Если все оставить так, то на syslog сервере будет создан текстовый файл local5 со всеми событиями соответствующими последнему правилу файрволла — то есть атаки на этот маршрутизатор:

Файл будет расти неограниченно, пока не съест весь логический раздел, поэтому надо настраивать ротацию журнала. Это можно сделать при помощи скриптов logrotate — разбивать журнал на дни, ежедневно архивировать и удалять старые архивы. Однако мне пришла идея получше — брать из записи только нужное, разбивать на поля и переносить их в базу данных.

База данных и обработчик журнала

В качестве СУБД я установил postgresql — потому что о работе с ней я ничего на тот момент не знал, а познакомиться очень хотелось.

После установки, подключился к postgres:

Cоздал нового пользователя:

Первая таблица “wedro” должна содержать время события, имя маршрутизатора, адрес атакующего и атакованный порт. И все бы хорошо, но адрес атаковавшего хранить в текстовом виде мне показалось неправильным. В итоге я установил расширение IP4R — получилось не с первой попытки, но если будет интересно, расскажу. В результате таблицу создал так:

Обработчик журнала

Теперь настало время создать обработчик журнала local5, который мою базу будет наполнять. Написан он был не за один день и даже претерпел пять редакций, так что приведу последнюю рабочую версию:

Суть данного “скрипта” такова:

  • журнал обрабатываем построчно
  • берем только строки с фразами «Access Control» и «default»
  • (!) удаляем четырехзначный год и пробелы во времени события
  • из пятого поля удаляем “src=”, а адрес пишем в переменную HA (HackerAddress)
  • из шестого поля удаляем “dst=”, а порт пишем в переменную OP (OurPort)
  • проверяем длину имени маршрутизатора и номер порта на корректность
  • собираем полученые данные в строку для запроса на вставку
  • подрезаем полученый файл с запросом на два символа и завершаем “;”
  • переименовываем и вставляем в базу

Восклицательный знак я поставил, для отдельного комментария. Дело в том, что формат журналов Zywall2Plus и USG20 отличаются тем, что один пишет год, а другой почему-то этого не делает. Чтобы привести эти записи к общему виду, я год удаляю из всех записей, а потом добавляю значение года из системы. Это вообще-то не очень правильно, и спустя некоторое время я понял, что сделать надо было по-другому. На каждый формат журнала надо было бы сделать некий шаблон обработки в виде модуля. Однако времени не было и писал как получится.

Чтобы база наполнялась автоматически, в настройке ротации журналов /etc/logrotate.d/ надо создать правило для local5, задающее ротацию по объему файла:

Однако ротация почему-то срабатывала не всегда, и я сделал в планировщике cron принудительную ротацию каждые 5 минут:

Результат

В итоге база действительно наполняется автоматом — за два дня порядка четырех миллионов записей с нескольких маршрутизаторов.

Шаг второй: пассивный анализ

С самого начала стало ясно, что записей с 53-м портом слишком много, чтобы разглядеть что-то еще. В результате, ничего лучше, чем их удалять, я не пока придумал. На таблицу wedro был повешен триггер на AFTER INSERT:

Результат

При такой регулярной чистке база перестала расти угрожающими темпами и появилась возможность в ней что-то найти. Правда также появилась необходимость в AUTOVACUUM-е для освобождения когда-то занятых ресурсов.

Уникальные адреса

Атаки с одних и тех же адресов достаточно часто повторяются. Поэтому я решил, что их надо собирать в отдельную таблицу. Так как данные обновляются каждые пять минут, смысла делать это в виде триггера нет — в результате пришлось освоить установку и работу планировщика pgagent.

Специально для этого были созданы еще две таблицы ipid и wedro_old:

А в pgagent-е было заведено ежечасное задание по наполнению этих таблиц:

Шаг третий: активный анализ Камеры и DVR-ы Hikvision

В оставшихся записях оказалось довольно много атак на 23-й порт telnet. Причем ряд адресов делал это многократно и никаких других портов не сканировал. Если набрать такой адрес в браузере, откроется форма ввода учетных данных:

в некоторых случаях заводские admin/12345 пускают в интерфейс цифрового магнитофона Hikvision. Интересно также, что на ряде устройств имеется не задокументированный открытый порт 9527. Вот и пример для фазы активного анализа:

Ищем адреса атаковавших только 23-й порт:

Используем полученный список в Nmap-е для поиска уязвимых DVR-ов:

Выражения limit и offset использованы здесь из-за ограничений сканера на количество целей. На неограниченном списке он дает сбой.

Шаг четвертый: действие

Для найденных на предыдущем шаге узлов я также написал скрипт на expect для проверки заводских учетных данных и отключения сканера 23-го порта. Однако я достаточно далеко отошел от своей первоначальной цели — активного предотвращения несанкционированного доступа к моим маршрутизаторам. И думаю настало время подвести общий итог.

Заключение

Интернет это действительно «грязное» место и моя система позволяет это оценить количественно. Думаю, из того что я здесь привел, понятно что система далека от совершенства и нуждается в доработках: нужен интерфейс, шаблоны устройств, объединение всех модулей в единый установочный пакет и еще много чего. Но система уже работает, собрана из доступных и бесплатных компонентов. Я не исключаю, что системы подобные моей, существуют и в коммерческом исполнении. Однако я сомневаюсь, что все модули таких систем будут доступны для настройки и изменения.

📎📎📎📎📎📎📎📎📎📎