n8n. Автоматизация ИБ со вкусом смузи

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

В компаниях, где отлажены процессы ИБ, а также в центрах реагирования и мониторинга используется ПО, позволяющее автоматизировать принятия решений по возникающим инцидентам, но даже при этом многим до сих пор приходится писать скрипты для автоматизации рутинных операций. Что делать, если автоматизировать рутину вам хочется, но не хочется покупать дорогостоящее специализированное решение, разбираться с ним и потом долго настраивать его под свои нужды? А еще больше не хочется изобретать велосипед со скриптами и делать нечто свое, попутно изучая программирование и работу с БД?  

8429ad5577981866fa6e6ba2194e9891.png

Источник

TL; DR: Telegram, REST API, Shodan, DNS-over-HTTPS. Пишем бота в Telegram  для парсинга инфы с shodan и поиска эксплойтов на exploit-db. Находим баг в работе n8n. 

Ответ есть — добро пожаловать во фронтенд со смузи и гироскутерами. 

8e2b3cd32939b12703e356eee6d9aaec.png

Источник

Как всегда, в поиске верного решения нам поможет волшебно-бесплатный мир open source. Мы в «ЛАНИТ-Интеграции» рассмотрели несколько решений подобного типа и выбрали среди них наиболее универсальное. Давайте разбираться, как работает и что умеет решение для гибкой автоматизации workflow n8n. 

n8n — это просто конструктор, набор ингредиентов для приготовления. Цель n8n — помочь обычному человеку в выполнении его рутинных рабочих процессов (workflow), интегрируя в единый оркестр целое множество различных сервисов и скриптов сущностей. Это совсем не похоже на программирование. Но чтобы сделать по-настоящему мощный комбайн автоматизации под свои нужды, желательно иметь опыт программирования уровня «Pascal в школе», навыки поиска и копирования кода со stackoverflow и хотя бы обзорное представление о работе Web«а (frontend — это просто!). n8n поможет приготовить чашку кофе в кофеварке прямо по команде из любимого Telegram.  

n8n выполняет роль серверной части процессов автоматизации, этакий клей между различными сущностями (скрипты, файлы, мессенджеры, веб-сайты, системы отчетности, CRM-системы, системы IP-телефонии, системы мониторинга — то есть практически все). Он помогает связать любое приложение с API и без него с любым другим приложением, при этом можно реализовать практически любую логику. Но самое главное — он имеет возможность реализации собственной логики путем программирования на JavaScript и возможность запуска скриптов на сервере. Настройка workflow интуитивна и проста в моднейшем веб-интерфейсе, рабочий процесс очень прост в настройке. Взаимосвязи между сущностями и n8n реализуются с помощью различных архитектурных концепций, основной из которых является REST API. Данные могут поступать в различных форматах, для REST API обычно используются JSON/XML. Так как это open source, можно написать свой собственный компонент n8n или скрипт на любом языке. n8n — это отличный выбор для тех, кто только хочет познакомиться с автоматизацией.

Поскольку обзор возможностей решения — это немного скучно и очень длинно, вы можете самостоятельно изучить туториалы, посмотреть варианты интеграций и изучить примеры workflow для того, чтобы почерпнуть несколько идей. Еще есть отличные статьи с примерами на medium и хорошая статья по установке в блоге LogRocket. Для старта вполне достаточно. Статья у нас будет техническая, чтобы показать случайно взятый пример автоматизации, минимум теории и максимум практики. Данное решение надо трогать руками, так что объяснений тоже будет минимум. 

Идея


Многие слышали про OSINT и пользовались разнообразными инструментами для сбора информации о ресурсах в целях инструментальной оценки их защищенности. Все пользовались мобильными приложениями с простым и понятным интерфейсом. Показалось интересным скрестить простой интерфейс Telegram со сложными инструментами типа Shodan и masscan, заодно проверив, чего стоит n8n в деле автоматизации. Это было первое, что пришло в голову после знакомства с n8n, и необходимо было выяснить, как он справится с этой задачей. 

Цель — продемонстрировать процесс автоматизации случайно выбранной предметной области путем написания простейшего бота для Telegram, который по информации от shodan может получить список возможных уязвимостей/эксплоитов по IP/URL. Для этого необходимо реализовать получение информации об открытых портах, сервисах на этих портах и возможных эксплоитов для данных сервисов. Полученную информацию в дальнейшем необходимо будет валидировать вручную, это выходит за рамки данной статьи. 

Установка


n8n написан на Node.JS, может работать как на Windows, так и на Linux. Всю информацию о рабочих процессах он хранит локально в БД SQLite. Может быть развернут как в докер-контейнере, так и прямо на хосте. Рассмотрим вариант установки прямо на хост Linux, для простоты. Есть опыт установки на CentOS 8.2  и Ubuntu 20.40 Desktop, отличия в установке минимальны. 

Установка необходимых пакетов:

sudo apt-get install nodejs npm build-essential python –y

Установка поддержки БД:

sudo npm install sqlite3 --save

Установка n8n глобально на хост:

sudo npm install n8n -g

Запуск n8n с параметром --tunnel:

n8n start --tunnel

Параметр --tunnel нужен для правильной работы веб-хуков если на сервере отсутствует адрес, доступный из сети Интернет. 

После запуска видим адрес, по которому доступен редактор, http://localhost:5678/, если доступ будет с другой машины в сети, то вместо localhost используем IP-адрес (не забыв открыть порт 5678 на файрволе). 

ca4fc39a2a1c2dc49a9088a865719ca2.png


Для быстрого старта необходимо ознакомиться с этим разделом документации, она очень простая. После создания пустого workflow у нас есть не удаляемая стартовая нода. Нода — это единичный блок в рабочем процессе. Рабочий процесс начинается либо со стартовой ноды при запуске workflow, либо с триггера, в случае если процесс активный и пришло сообщение от внешней системы (API, скрипт на хосте). Триггер получает тем или иным способом информацию о событии от внешней системы и обрабатывает ее. Ноды взаимодействуют между собой с помощью соединений. Нода может иметь несколько соединений с другими нодами. Нода производит все действия с информацией — получение, обработку/изменение, вывод во внешние системы. Полный перечень нод есть в документации. На этом краткий обзор закончим, перейдем к практике. 

Создание бота в Telegram


Создание ботов Telegram — очень интересный процесс. Бот зачастую выступает шлюзом для удобного получения любой информации. Однако создание серверной части бота Telegram требует знаний и опыта работы с Telegram API, что может быть сложной задачей, если у вас нет времени или желания вникать. Использование таких решений без кода, как n8n, позволит эффективно создавать внутреннюю логику работы ботов без необходимости углубляться в механику. 

Про создание ботов в telegram написано огромное количество материалов. Опираемся на официальную документацию и на вот эту статью по созданию telegram бота для n8n. С помощью бота BotFather создаем своего бота, получаем его токен. Добавляем несколько команд и их описание:

hostinfo - Show host info from Shodan

scan — <127.0.0.1> Show output of masscan for some open ports. Please, be patient…

whatweb — Show whatweb output

exploit — Show searchsploit output

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

Создание первого workflow


Запускаем n8n в режиме »--tunnel», для корректного получения обновления от серверов telegram. При первом запуске в веб-интерфейсе видим пустой лист с одной лишь нодой Start. Добавляем на лист триггер telegram, в настройках забиваем Credentials (токен доступа, полученный ранее). В Updates выбираем либо *, либо Message. Так как это триггер, его не нужно соединять со стартовой нодой. 

d7d8c2396003745fdb576e2380b570ed.png


Сохраняем workflow и делаем его активным с помощью переключателя в верхнем правом углу. Нажимаем Execute Workflow и пишем что-либо в окно чата с ботом. Видим, что статус »Waiting for webhook call…» меняется на Execute Workflow. На ноде триггера появляется зеленый круг, сигнализирующий об успешном выполнении триггера. В свойствах триггера видим результат — полученное сообщение об обновлении в формате JSON с содержанием сообщения и кучей полей. 

49700981bbf3052a671c8f7a65a12d67.png


Далее добавляем на поле ноду Switch, которая отвечает за обработку команды, полученной от бота. Соединяем ее линией с триггером Telegram. В свойствах ноды Switch видим простейший выбор из 4-х вариантов. Выбираем Mode — Rules, Data Type — string, в Value после нажатия на шестеренку выбираем Add Expression и видим следующее окно:

24c8b4750d3557c13efac83a827e167a.png


Проваливаемся по списку входных данных — Current Node → Input Data → JSON → message → text для выбора содержимого сообщения. В нижней части результат Expression — содержимое нашего сообщения. Закрываем окно, в настройках Switch добавляем правило роутинга, сообщение должно содержать первую команду «host». Выбираем выход »0» для дальнейшей ветки обработки. Для четырех команд бота у нас должно быть четыре правила роутинга. Получился вот такой workflow:

448628d76bb963b7d330ede4e96fd4d0.png


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

У любого workflow есть два варианта работы — testing (при нажатии на кнопку Execute Workflow) и production — когда активен переключатель Active в верхнем правом углу. В тестовом варианте работы workflow выполняется только один раз, в варианте работы production он работает постоянно и запускается при старте сервиса n8n. В тестовом режиме мы можем видеть данные для обработки в веб-интерфейсе n8n, в отличие от режима production. 

Перечень активных процессов можно увидеть через меню, выбрать пункт Open:

b920075a3aa0c2ff3c8d407d4dbc0908.png


Как я нашел баг


Немного отвлечемся от процесса создания нашего workflow и углубимся во внутренности работы триггера telegram. В данном случае для получения обновлений от API Telegram используется механизм веб-хуков. В отличие от традиционного метода обмена информацией по протоколу HTTP «запрос — ответ», механизм веб-хуков работает асинхронно. Заключается он в том, что серверу n8n необходимо «зарегистрироваться» на сервере Telegram с указанием URL-адреса, на котором он будет получать HTTPS-запрос POST, содержащий сериализованное обновление в формате JSON. Регистрация производится методом setWebhook при переводе workflow в активный режим либо при тестовом прогоне workflow. В этот момент сервер n8n отправляет с помощью запроса setWebhook свой URL-адрес для интеграции с API Telegram с целью получения обновлений. В момент остановки сервиса либо в момент окончания тестового процесса производится удаление интеграции с веб-хуком для того, чтобы уведомить API Telegram о том, что никто не сможет принять запросы об обновлении.

Так как в условиях тестирования у нас нет общедоступного URL-адреса для веб-хука, нам нужно его получить при помощи утилиты localtunnel. Для этого как раз при запуске мы указывали параметр –tunnel. Полученный URL мы видим в консоли, он же и отправляется API Telegram для обработки обновлений. URL генерируется динамически, и на каждый запуск сервиса он разный. 

Все началось с того, что я заметил странную работу триггера Telegram — при остановке и последующем запуске сервиса не приходили обновления от бота. Они приходили, если еще раз сделать workflow активным. Я еще раз изучил API Telegram и воспользовался методом getWebhookInfo для просмотра текущего URL веб-перехватчика. Оказалось, что после остановки сервиса n8n на хосте не производится отмена регистрации старого URL-адреса. Также при новом запуске сервиса не производится установка нового URL. Баг был отправлен разработчику, подтвержден и был исправлен в релизе n8n@0.79.3.

Получаем информацию от Shodan


В качестве примера давайте получим данные о хосте от широко известного в узких кругах поисковика Shodan. У него есть REST API, а у нас есть желание упростить себе жизнь в части инструментального анализа уязвимостей, получая информацию прямо в чат (или куда-то еще). Для этого нам необходимо зарегистрироваться и получить API -ключ для Shodan в настройках нашего аккаунта. 

В любом случае перед тем, как делать любой workflow, необходимо ответить себе на вопросы: что он будет делать, как он будет это делать, что потребуется для этого. В идеале рекомендую нарисовать простую блок-схему процесса на листке бумаги, чтобы было легче. 

Но так мы уже определились с целями, то приступим к реализации. 

b9bf681e71526cb072ccd18ee02aeb5d.png


Формат нашей команды — »/host example.com», где первая часть — это команда, вторая часть IP или корневой URL. Так как API Shodan выдает нам информацию только по IP-адресу, корневой URL переводить в IP мы будем с помощью новой технологии DoH в реализации Google. Можно сделать это множеством способов, но используем этот модный и стильный способ взаимодействия с DNS. Получаем IP-адрес и через Shodan API получаем и обрабатываем информацию, отправляя выжимку из нее в тот же чат в telegram. Звучит все просто. Для начала нам нужно знать, что подали на вход команды — IP или URL. JavaScript, функции на котором можно легко писать прямо в интерфейсе n8n, нам в этом поможет. Для этого добавим ноду типа Function и соединим ее с нодой sw_cmd

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

411d46ad4c96aa6e645dbfe1c3ead964.jpg


Источник

Ищем, как отличить IP от URL и на stackoverflow находим нужное регулярное выражение. Пишем код в ноде func_isIP:

items[0].json.IP = items[0].json.message.text.split(' ')[1];

items[0].json.isIP = false;

if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(items[0].json.IP)) {  

  items[0].json.isIP = true;

  return (items);

}  

return (items);


Код получает на вход сериализованное JSON-сообщение, из него берет вторую часть после пробела, прогоняет ее регулярным выражением и в новую переменную isIP присваивает значение true, если это IP-адрес. Опережая комментарии про проверку ввода пользователя — не в данной статье, в ней мы минимально затрагиваем тему программирования. В случае неверного или нестандартного ввода в n8n есть процесс обработки ошибок, который необходимо настраивать. 

Далее добавляем ноду IF_is_IP для выбора дальнейшей ветки алгоритма. В зависимости от содержимого, нам надо будет с помощью ноды типа HTTP Request выполнить запрос через API. Добавляем ноду http_req_shHost, соединяем с нодой IF_is_IP и настраиваем параметры запроса в соответствии с документацией производителя API (в данном случае Shodan). Аналогично настраиваем еще одну ноду http_req_DoH для получения информации от DNS. Методы запроса и методы аутентификации описаны в документации, все делаем в соответствии с ней. 

85e4e75f48e507d80506c0cb3308458a.jpg

Источник

Нужные переменные прокликиваем мышкой из Input Data, перед этом выполнив тестовый запуск workflow для получения ответа на запрос. Конструируем запрос:

112deb58fdbf3af1d6a5314688496903.png


Результат выполнения запроса DoH URL: ya.ru в формате JSON:

d8938c874c52ad4d630d6e086f53d82f.png


Ноду http_req_DoH соединяем с копией ноды http_req_shHost и мышкой прокликиваем ее новые параметры, меняя значение IP в параметрах запроса, чтобы получилось нужное значение: api.shodan.io/shodan/host{{$node[«http_req_DoH»].json[«Answer»][1][«data»]}}? key=. Далее конструируем отчет, который будет отправлен в чат нодой Telegram2 (отправка сообщения в чат), выбирая нужные поля из Input Data:

2a71a45cf3cfe294aa5433bb18f5d96d.png


В чате видим сообщение с данным отчетом:

f867def1a962899cbedcc7cd7be2783e.png


Сканируем порты с помощью masscan


Так как область, которую мы автоматизируем, не ограничивается получением информации через различные API (а многие API еще и стоят денег за каждый запрос), давайте попробуем скрипты. Для работы с ними в n8n есть нода типа Execute Command, добавим ее в нужную ветку sw_cmd под именем cmd_masscanPorts. Перед этим извлечем IP-адрес из строки сообщения с помощью функции func_getIP.

d495c3e4e43fc59b117022aa3bdf18b7.png


Поставим на хост с n8n известный сканер masscan. Если у нас n8n работает в докер-контейнере, то ставить masscan нужно в контейнер. Установка довольно проста. После установки тестируем команды, с помощью которых мы будем сканировать порты. У меня получилась строка вида masscan  -p 1–1024,8080 127.0.0.1. Диапазон портов ограничен до 1–1024,8080, чтобы сократить время ожидания. В свойствах ноды cmd_masscanPorts мы настраиваем входные данные от функции func_getIP (значок шестеренки, Add Expression). 

89e510d7f93759bad95e35f6df96c212.png


Получается команда masscan  -p 1–1024,8080 {{$node[«func_getIP»].json[«IP»]}}. Запускаем для теста workflow, вводим команду /scan 92.53.96.181 Обращаем внимание, что нода cmd_masscanPorts может выдавать для обработки как результат выполнения (stdout), так и результат ошибки или ход выполнения сканирования (stderr). Тестируем выполнение workflow, смотрим на выходные данные. Добавляем снова ноду для отправки сообщения в чат Telegram3, проверяем, видим в чате (спустя некоторое время выполнения команды masscan) стандартный вывод команды:

b90323f9a481a68daf5464cc69262bf9.png


Отлично, мы научились выполнять скрипты и обрабатывать их вывод. 

Определяем версии веб-компонентов с помощью whatweb


Как и в прошлом разделе, ставим whatweb на хост с n8n. Конструируем команду, пришлось отключить цветовое выделение, так как вывод некорректно обрабатывался при отправке сообщения в telegram. Получилась команда вида whatweb itlanit.ru --color=never. Результаты также отправляем сообщением в чат. 

19fd1a866d7b81cee6a0be9cc6035a50.png


Ищем эксплойты с помощью searchsploit


Искать эксплойты по версиям софта можно разными способами. Платные запросы через API оставим в стороне. Посмотрим, как можно это делать бесплатно без смс и регистрации, заодно вспомним основы JS. Ставим на хост searchsploit, изучаем документацию, смотрим примеры команд и их вывод. Подозрение сразу вызывает два параметра, которые могут быть полезны:

   -j, --json     Show result in JSON format

   -w, --www     Show URLs to Exploit-DB.com rather than the local path


089a8b9602fc4d5efd579b78f1454b81.png


Добавляем ноду функции, которая должна вырезать нам имя софта из команды /exploit notepad, аналогично примеру выделения IP адреса из пункта про Shodan. При этом не забываем, что у нас может быть в запросе как название, так и версия софта, а значит из сообщения нам надо отбросить только команду. То есть надо выполнить простые операции со строками и массивами в JS. Итоговая функция func_getName:

temp = items[0].json.message.text.split(' ');

temp = temp.slice(1, temp.length);

items[0].json.soft = temp.join(' ');

return items;


Добавляем ноду Execute Command, в команде указываем выражение:  

searchsploit -j -w {{$node[«func_getName»].json[«soft»]}}


И у нас опять есть проблема, в результате получаем JSON, но в формате простого текста. Для преобразования используем метод json.parse в функции func_getJSON:

items[0].json.p_json = JSON.parse(items[0].json.stdout);

return items;


Теперь у нас есть JSON, который можно разбирать и конструировать из него сообщение. Отметим, что количество эксплойтов может быть произвольным, а значит нам понадобится цикл для обработки. Итоговый код func_getMsg:

items[0].json.msg_text = '*Exploits list: *\n';

items[0].json.p_json.RESULTS_EXPLOIT.forEach(function (RESULTS_EXPLOIT){

  items[0].json.msg_text = items[0].json.msg_text + RESULTS_EXPLOIT.Title + ' \n '+ RESULTS_EXPLOIT.URL + '\n';

  });

return items;


Звездочки добавлены для разметки Markdown, URL умеет распознавать сам Telegram. Добавляем ноду для отправки сообщения Telegram. Вот наше итоговое сообщение в чате:

d47e37af0ba48e6085b17e4fca4d1bac.png


На этом закончим. У нас получился бот, который умеет собирать информацию из разных источников. 

Как еще можно применить n8n для выполнения рутинных операций специалиста по информационной безопасности? Например, получать обновления о найденных уязвимостях из RSS-фидов, и парсить обновления по ключевым словам — наименованию ПО, которое используется в организации. Если найдена новая уязвимость в ПО, то отправлять сообщение администратору безопасности. Также допустим, если мы собираем хэш-суммы файлов на рабочей станции, то n8n может дополнительно проверять их на VirusTotal, и проверять, не пропустил ли установленный антивирус нового зловреда и отправлять уведомление администратору.

Плюсы

  • Open source.
  • Низкий порог входа.
  • Хорошая документация.
  • Возможность расширения функционала: код на JS, хостовые скрипты.
  • Отзывчивое сообщество.


Минусы

  • Отсутствие русскоязычной документации.
  • Отсутствие компонентов интеграции с типовыми отечественными сервисами (1С, Bitrix, Яндекс, Mail.ru).
  • Отсутствие кнопки «Сделать хорошо».


Подводя итог, я могу сказать, что продукт мне понравился. Да, он не является уникальным, и у него много конкурентов (Zapier, IFTT, automate.io и т.п.), но видно, что концепт продукта был хорошо продуман, особенно в части простоты использования и возможности расширения функционала. 

В статье рассмотрены разнообразные кейсы применения n8n. Надеюсь, статья была полезной, и подтолкнула читателя к каким-либо идеям автоматизации своей деятельности. Готов ответить на вопросы в комментариях или по email arudakov@lanit.ru.

У нас еще есть вакансии!

© Habrahabr.ru