Привет, хабровчане! С вами снова Иван — разработчик, который пишет на Python, и хаброписатель, который пишет для блога МТС.

Если вы работаете в сфере кибербезопасности или интересуетесь ей, то, скорее всего, знаете о существовании индикаторов компрометации. «Да, они есть, и что дальше?» — скажете вы. Ответ: их нужно где-то хранить. Для этой задачи есть различные платформы, одни платные, другие — нет. Сегодня мы сфокусируемся на MISP — у этого продукта множество фанатов, и их можно понять. Но вручную вносить все индикаторы скучно, не так ли? Поэтому мы добавим нотку автоматизации, и тут нам поможет Python. Как именно, узнаете дальше.

Что такое MISP

MISP (Malware Information Sharing Platform) — платформа с открытым исходным кодом, предназначенная для сбора, хранения, распространения и использования индикаторов компрометации (иоков), которые связаны с анализом инцидентов кибербеза и вредоносных программ. Проект был разработан специалистами в области кибербезопасности для быстрого обмена структурированной информацией на ежедневной основе. У платформы есть документация misp-book, которая пишется на GitHub.

Индикатор компрометации (Indicator Of Compromise, IOC) — это объект, который с большой вероятностью указывает на нарушение безопасности системы. В качестве примера такого индикатора можно привести URL какой-либо страницы, hash файла или IP-адрес сервера. В MISP около 190 различных типов IOC!

А вот какие у MISP преимущества:

  • Автоматизация. MISP автоматизирует экспорт иоков в определённых форматах для их дальнейшего использования в системах защиты.

  • Минимализм. Хранить и использовать информацию максимально просто.

  • Визуализация иоков. Доступна для более глубокой аналитики.

  • Обмен информацией. На платформе можно настроить получение данных от различных организаций.

  • Бесплатный доступ. MISP — open-source-проект, загрузить его может каждый. API-платформы и формат данных открыты.

  • Киберразведка. Можно тегировать события и IOCs, добавлять фиды и осуществлять интеграцию с другими инструментами для более глубокого анализа.

Как ни странно, MISP не только платформа, но и формат данных. Он представляет из себя JSON, использующийся для обмена событиями и атрибутами.

Теперь давайте к характеристикам проекта на GitHub:

Параметр

Описание

Особенности

Стабильный релиз, большое комьюнити и простая модель хранения данных

Количество звезд на GitHub

5,9 тыс.

Открытых Issues

2,7 тыс.

Версия

2.5.18

Год релиза

2011

Pull Requests (PRs)

92

Участие в разработке

Основные разработчики проекта и комьюнити

Лицензия

Общая публичная лицензия GNU Affero версии 3

Установить MISP можно с помощью виртуального образа (VMware или VirtualBox, подходит только для тестирования), Vagrant, Docker, Ansible, Puppet, misp-cloud и RPM.

Фиды

Первый шаг при использовании MISP — настройка фидов, то есть источников, из которых получают иоки.

Если придерживаться классического пути, сделать это можно перейдя в Sync Actions → Feeds:

Дальше нужно кликнуть на Add Feed:

Теперь настраиваем фид. Доступно три формата: MISP, Freetext и Simple CSV:

Мало-мало-мало фидов

Иногда может быть недостаточно предлагаемых форматов. Например, вы загружаете иоки в виде IP-адресов и хотите исключить определенные подсети. Конечно, можно использовать регулярное выражение (параметр Exclusion Regex, который доступен при выборе Simple CSV), но оно может оказаться очень большим и не совсем понятным. Или, например, вы написали парсер, который ходит и усердно собирает урожай иоков, но как загрузить эту добычу в MISP? Хороший вопрос.

И тут в чатик входит Python. В первом случае он поможет лаконичнее отфильтровать ip-адреса (есть модуль ipaddress), а во втором — и паука-парсера запустит, и иоки импортирует.

Автоматизация при помощи Python

Не буду долго томить — сразу посмотрим, как это делается. Все начинается с PyMISP — библиотеки для автоматизации работы с MISP при помощи REST API. Она позволяет взаимодействовать с событиями, атрибутами и выполнять поиск по платформе.

Запуск PyMISP

Для корректной работы библиотеки понадобится аутентификационный ключ. Чтобы выпустить его, сначала перейдем в Administration → List Auth Keys.

Нажмем на кнопку с надписью Add authentication key:

Сохраните созданный ключ — он еще нам понадобится.

Подключиться к платформе можно так:

from pymisp import PyMISP

misp_url = "URL_ВАШЕГО_MISP(С HTTP/HTTPS)"
misp_verify_certificate = False
misp_key = "ВАШ_AUTHENTICATION_KEY"
misp = PyMISP(url=misp_url, key=misp_key, ssl=misp_verify_certificate)

Параметр ssl (передается переменная misp_verify_certificate) отвечает за то, должен ли Python проверять сертификат MISP-платформы. Подчеркну: параметр ssl=False отключает проверку SSL-сертификата. В примере я использую False исключительно потому, что тестирую локально. Никогда не повторяйте в рабочей среде! В проде рекомендуется использовать достоверный сертификат и установить значение True.

Вот и все. Теперь можно обращаться к переменной misp и осуществлять различные действия. Как? Давайте покажу.

Пример автоматизации

Допустим, у меня появилась потребность загрузить в MISP иоки. Для примера я нашел репозиторий awesome-lists с IP-адресами ProtonVPN (файл protonvpn_ip_list.csv). Для удобства воспользуюсь Raw-форматом файла. Вот как выглядят наши иоки:

А теперь погрузимся в код. Сначала импортируем необходимые модули:

logging.info("Скачиваем IOCs")
response = requests.get("https://raw.githubusercontent.com/mthcht/awesome-lists/refs/heads/main/Lists/VPN/ProtonVPN/protonvpn_ip_list.csv")
response.raise_for_status()  # Вызывает ошибку если вернулся неуспешный код ответа

Файл мы скачали, но чтобы загрузить данные из него в MISP, их нужно сначала преобразовать. Поэтому мы создадим список iocs, а дальше будем наполнять его словарями из трех ключей: type (тип иока), value (значение) и comment (комментарий).

logging.info("Преобразуем IOCs для MISP")
iocs = []
for row in csv.DictReader(response.text.splitlines()):
   iocs.append(
       {
           "type": "ip-src",
           "value": row["src_ip_entry"],
           "comment": f'Country entry: {row["src_country_entry"]}',
       }
   )

Наполним скопом наше событие:

logging.info("Загружаем IOCS")
_ = misp.add_attribute(event_id, iocs)

Готово! Но чтобы оно синхронизировалось и его можно было экспортировать —  нужно выполнить публикацию:

logging.info("Публикуем событие")
misp.publish(event)
logging.info("Код выполнился успешно!")

Выполним код и посмотрим, что он нам выведет:

29-08-2025 15:29:28 | INFO | Отключаем уведомления
29-08-2025 15:29:28 | INFO | Подключаемся к MISP
29-08-2025 15:29:29 | INFO | Создаём событие в MISP
29-08-2025 15:29:29 | INFO | Скачиваем IOCs
29-08-2025 15:29:29 | INFO | Преобразуем IOCs для MISP
29-08-2025 15:29:29 | INFO | Загружаем IOCS
29-08-2025 15:29:34 | INFO | Публикуем событие
29-08-2025 15:29:34 | INFO | Код выполнился успешно!

Теперь заглянем в MISP. Там должно появиться новое событие:

Ура! Все на месте. Внутри событие наполнено иоками:

Как-то так это и работает. Если есть желание запустить код самостоятельно, он доступен по ссылке.

Пока мы коснулись лишь мараскиновой вишни на вершине молочного коктейля. Сама платформа MISP довольно обширна и содержит объекты (например, галактики), о которых сегодня я не сказал. PyMISP в свою очередь предоставляет целый арсенал классов и функций для комфортной автоматизации платформы.

Если будут вопросы, пишите их в комментариях. С радостью постараюсь на них ответить. А в свою очередь спрошу: используете ли вы MISP? Если да, как он вам? А что насчет PyMISP? Есть ли у вас кейс, когда для импорта иоков пришлось подтягивать тяжелую артиллерию в виде языка программирования?

Комментарии (0)