Привет, хабровчане! С вами снова Иван — разработчик, который пишет на 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 |
Участие в разработке |
Основные разработчики проекта и комьюнити |
Лицензия |
Установить 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? Есть ли у вас кейс, когда для импорта иоков пришлось подтягивать тяжелую артиллерию в виде языка программирования?