MISP
Интеграция с Malware Information Sharing Platform (MISP)
Данное руководство описывает настройку интеграции Solar TI Feeds Agent с MISP. Интеграция обеспечивает автоматическую загрузку индикаторов компрометации (IoC) из Solar TI Feeds в MISP через промежуточное хранение в локальной базе данных.
Предварительные требования
- Установленный и настроенный Solar TI Feeds Agent
- Учётные данные для доступа к API MISP (токен аутентификации)
- Доступ к серверу Solar TI Feeds с действительным JWT-токеном
Конфигурация интеграции
Интеграция реализована двумя пайплайнами, которые обеспечивают надёжное получение, промежуточное хранение и доставку индикаторов в MISP, включая повторную обработку неудачных попыток. Аутентификация в MISP выполняется через HTTP-заголовок Authorization с токеном.
Основные компоненты интеграции:
| Компонент | Назначение |
|---|---|
FeedsAPIGenerator | Загрузка данных из Solar TI Feeds API |
FeedsDBSink | Сохранение данных в локальную SQLite-базу |
FeedsDBGenerator | Чтение данных из базы для обработки |
FeedsFailedDBGenerator | Повторная обработка ошибочных записей |
Mapper | Преобразование JSON-данных в плоскую структуру, необходимую MISP |
MispSink | Отправка подготовленных событий напрямую в API MISP |
Переменные окружения
Для работы интеграции необходимо определить следующие переменные окружения (например, в docker-compose.yml):
Подключение к Solar TI Feeds API
| Переменная | Назначение |
|---|---|
TIC_AGENT_API_URL | Адрес сервера Solar TI Feeds API |
TIC_AGENT_API_TOKEN | JWT-токен для аутентификации в Feeds API |
Подключение к MISP
| Переменная | Назначение |
|---|---|
TIC_AGENT_SERVICE_URL | Полный URL сервера MISP (например, https://misp.example.com) |
TIC_AGENT_SERVICE_TOKEN | Токен аутентификации для API MISP |
Дополнительные параметры (расписание, путь к БД и пр.) задаются в файле internal/templates.pkl.
Структура пайплайнов для MISP
Pipeline 1: feeds-api (загрузка данных)
| Компонент | Параметры | Описание |
|---|---|---|
FeedsAPIGenerator | server = templates.serverJwtApiCfg | Запрос индикаторов из Solar TI Feeds API |
schedule = templates.scheduleCronMinCfg | ||
FeedsDBSink | – | Сохранение всех полученных данных в SQLite |
Pipeline 2: feeds-misp (обработка и выгрузка)
| Компонент | Параметры | Описание |
|---|---|---|
FeedsDBGenerator | schedule = templates.scheduleCronMinCfg | Чтение индикаторов из БД |
delay = 10.s | ||
FeedsFailedDBGenerator | feedGenName = "feeds-misp-generator" | Повторная обработка индикаторов, отправка которых ранее завершилась ошибкой |
schedule = templates.scheduleCronMinCfg | ||
delay = 1.min | ||
Mapper | jsonpath | Преобразование исходных данных в структуру MISP. Формирует поля id, type, value, action, first_seen, last_seen, zone, reports, threat_actors, malwares, tools, info, comment |
rules | ||
rulesOrder | ||
MispSink | server (адрес и токен) | Отправка подготовленных событий напрямую в API MISP |
customTags |
Условия повторной обработки:
Индикаторы, не отправленные из-за ошибок, автоматически помечаются в БД и подхватываются FeedsFailedDBGenerator через минуту для повторной попытки.
Справочник параметров для MispSink
Параметры ServerCfg (подключение к MISP)
| Параметр | Тип данных | Обязательность | Описание | Пример |
|---|---|---|---|---|
credentials | HeaderAuth | Да | Аутентификация через заголовок. name = "Authorization", value содержит токен. | credentials = new HeaderAuth { name = "Authorization" value = read("env:TIC_AGENT_SERVICE_TOKEN") } |
address | String | Да | Полный URL API MISP | address = read("env:TIC_AGENT_SERVICE_URL") |
insecureSkipVerify | Boolean | Нет | Отключение проверки SSL-сертификата | insecureSkipVerify = true |
Параметры MispSink
| Параметр | Тип данных | Обязательность | Описание |
|---|---|---|---|
server | ServerCfg | Да | Конфигурация подключения к MISP (адрес и токен) |
customTags | Listing<String> | Нет | Список кастомных тегов, добавляемых ко всем отправляемым событиям |
Полный пример конфигурационного файла для интеграции с MISP
📄 Нажмите, чтобы показать/скрыть misp_pipeline.pkl
amends "package://pkg.pkl-lang.org/github.com/pipelane/pipelaner/pipelaner@1.3.1#/Pipelaner.pkl"
import "package://pkg.pkl-lang.org/github.com/pipelane/pipelaner/pipelaner@1.3.1#/source/Components.pkl"
import "../internal/agent.pkl"
import "../internal/templates.pkl"
pipelines {
new Components.Pipeline {
name = "feeds-api"
inputs {
new agent.FeedsAPIGenerator {
name = "feeds-api-generator"
schedule = templates.scheduleCronMinCfg
server = templates.serverJwtApiCfg
}
}
sinks {
new agent.FeedsDBSink {
name = "feeds-db-sink"
inputs {
"feeds-api-generator"
}
}
}
}
new Components.Pipeline {
name = "feeds-misp"
inputs {
new agent.FeedsDBGenerator {
name = "feeds-misp-generator"
schedule = templates.scheduleCronMinCfg
delay = 10.s
}
new agent.FeedsFailedDBGenerator {
name = "feeds-failed-misp-generator"
feedGenName = "feeds-misp-generator"
schedule = templates.scheduleCronMinCfg
delay = 1.min
}
}
transforms {
new agent.Mapper {
name = "feeds-misp-mapper"
inputs {
"feeds-misp-generator"
"feeds-failed-misp-generator"
}
jsonpath = new Mapping {
["feed_names"] = "$.feeds[*]..name"
["actions"] = "$.feeds[*]..action"
}
rules = new Mapping {
["id"] = "id"
["type"] = "type"
["value"] = "value"
["action"] =
"""
any(actions, {# in ["UPDATE", "CREATE"]}) ? "UPDATE" : "DELETE"
"""
["first_seen"] = "first_seen"
["last_seen"] = "last_seen"
["zone"] = "zone"
["related_objects"] =
"related_objects != nil && len(related_objects) > 0 ? related_objects : []"
["reports"] =
"""
let reports = filter(map(related_objects, {#.type == "REPORT" ? replace(#.value,"\\n"," ") : ""}), {# != ""});
len(reports) > 0 ? reports : []
"""
["threat_actors"] =
"""
let actors = filter(map(related_objects, {#.type == "THREAT_ACTOR" ? #.value : ""}), {# != ""});
len(actors) > 0 ? actors : []
"""
["malwares"] =
"""
let malwares = filter(map(related_objects, {#.type == "MALWARE" ? #.value : ""}), {# != ""});
len(malwares) > 0 ? malwares : []
"""
["tools"] =
"""
let tools = filter(map(related_objects, {#.type == "TOOL" ? #.value: ""}), {# != ""});
len(tools) > 0 ? tools : []
"""
["info"] =
"""
let relations = concat(threat_actors, malwares, tools);
len(relations) > 0 ? (value + " " + join(relations, ",")) : value
"""
["comment"] =
"""
let relations = concat(threat_actors, malwares, tools, reports);
join(relations, ",")
"""
}
rulesOrder {
"id"
"type"
"value"
"action"
"first_seen"
"last_seen"
"zone"
"related_objects"
"reports"
"threat_actors"
"malwares"
"tools"
"info"
"comment"
}
}
}
sinks {
new agent.MispSink {
name = "misp-sink"
inputs {
"feeds-misp-mapper"
}
server = new agent.ServerCfg {
credentials = new agent.HeaderAuth {
name = "Authorization"
value = read("env:TIC_AGENT_SERVICE_TOKEN")
}
address = read("env:TIC_AGENT_SERVICE_URL")
insecureSkipVerify = true
}
customTags = new Listing {
"agent:local_test"
}
}
}
}
}
settings = templates.baseSettings
Мониторинг результатов работы интеграции
После запуска агента убедитесь в корректности работы:
| Проверка | Действие |
|---|---|
| Проверка состояния БД | Убедитесь, что SQLite-база наполняется индикаторами, а успешно отправленные записи помечаются соответствующим образом. |
| Анализ логов | Проверьте логи агента (в директории, заданной шаблонами) на наличие ошибок подключения к MISP или Feeds API. |
| Верификация в MISP | В интерфейсе MISP должны появляться новые события с индикаторами. |
| Контроль очереди повторов | При временных сбоях индикаторы автоматически повторно отправляются через 1 минуту. Убедитесь, что после восстановления связи они доставляются. |
Примечание: Логи агента также можно просмотреть в реальном времени с помощью команды
docker logs {CONTAINER_NAME}.