Wazuh + OpenCTI = Integration?
Разворачиваем OpenCTI с интеграцией Wazuh
Дефендеры и прочие blue-team, а вы обогащаете данные в своем Wazuh?
Разумеется, Wazuh используют не везде, но в силу бюджетов его можно встретить даже в крупном бизнесе.
Сравнительно удобно, бесплатно и можно запихать в Docker.
Так вот, переходим к теме.
Представим, что правила у нас написаны, алерты настроены и от вечного внедрения уже можно перейти к добавлению функционала.
Например, алерты при обнаружении IoC. А для этого нам нужна какая-то Threat Intelligence платформа.
В голову приходят только MISP и OpenCTI, последний мы и будем использовать.
Типы событий / группы правил возможные для отработки с OpenCTI API
Event type | metadata | Rationale |
---|---|---|
sysmon event1 | win.eventdata.hashes | Check existing IoC in process image file hash |
sysmon event3 | win.eventdata.hashes | Check existing IoC in in destination IP |
sysmon event6 | win.eventdata.hashes | Check existing IoC in in loaded driver file hash |
sysmon event7 | win.eventdata.hashes | Check existing IoC in loaded DLL file hash |
sysmon event 15 | win.eventdata.hashes | Check existing IoC in downloaded file hash |
sysmon event 22 | win.eventdata.queryName | Check existing IoC in queried hostname |
sysmon event 23 | win.eventdata.hashes | Check existing IoC in deleted file hash |
sysmon event 24 | win.eventdata.hashes | Check existing IoC in clipboard content file hash |
sysmon event 25 | win.eventdata.hashes | Check existing IoC in process file hash |
sysmon process-anomalies | win.eventdata.hashes | – |
ids | dest_ip, src_ip | – |
osquery, osquery_file | osquery.columns.sha256 | – |
Тестовое развертывание
Для теста потребуется:
- API-ключ Alienvault OTX
- Wazuh
- Например wazuh-docker
- OpenCTI
- Интеграция OpenCTI с Wazuh
- Windows машина с sysmon и wazuh-agent
Получаем API-ключ Alienvault OTX
- Регистрируемся на Alienvault OTX, переходим в alienvault.com/api и забраем наш ключ.
Разворачиваем OpenCTI
- Клонируем репозиторий
|
|
- Настраиваем переменные:
Устанавливаем jq:
|
|
Добавляем переменные в .env
:
|
|
В полученный файл необходимо добавить свои переменные, будь это API-токен, почта или что-то ещё. Можно указать прямо в файле, но лучше, если сами переменные хранятся в глобальном окружении.
Так же не забываем заменить GENERATE_UUID на валидные UUID, которые можно сгенерировать либо с помощью утилиты uuidgen
или онлайн-генератором uuidgenerator.net.
- Добавлю сразу, что помимо самого OpenCTI и интеграции в Wazuh нам необходимы т.н. external-import connectors, и для примера будем использовать коннектор от alienvault
- Чтобы не плодить множество compose-файлов, забираем отсюда часть от
connector-alienvault:
доrestart: always
, так же добавляем часть в конец
|
|
Что у нас должно получиться (GIST):
Click to view the spoiler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
version: '3'
services:
redis:
image: redis:7.0.9
restart: always
volumes:
- redisdata:/data
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.6.2
volumes:
- esdata:/usr/share/elasticsearch/data
environment:
# Comment out the line below for single-node
- discovery.type=single-node
# Uncomment line below below for a cluster of multiple nodes
# - cluster.name=docker-cluster
- xpack.ml.enabled=false
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms${ELASTIC_MEMORY_SIZE} -Xmx${ELASTIC_MEMORY_SIZE}"
restart: always
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
minio:
image: minio/minio:RELEASE.2023-02-27T18-10-45Z
volumes:
- s3data:/data
ports:
- "9000:9000"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
command: server /data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
restart: always
rabbitmq:
image: rabbitmq:3.11-management
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS}
volumes:
- amqpdata:/var/lib/rabbitmq
restart: always
opencti:
image: opencti/platform:5.7.1
environment:
- NODE_OPTIONS=--max-old-space-size=8096
- APP__PORT=8080
- APP__BASE_URL=${OPENCTI_BASE_URL}
- APP__ADMIN__EMAIL=${OPENCTI_ADMIN_EMAIL}
- APP__ADMIN__PASSWORD=${OPENCTI_ADMIN_PASSWORD}
- APP__ADMIN__TOKEN=${OPENCTI_ADMIN_TOKEN}
- APP__APP_LOGS__LOGS_LEVEL=error
- REDIS__HOSTNAME=redis
- REDIS__PORT=6379
- ELASTICSEARCH__URL=http://elasticsearch:9200
- MINIO__ENDPOINT=minio
- MINIO__PORT=9000
- MINIO__USE_SSL=false
- MINIO__ACCESS_KEY=${MINIO_ROOT_USER}
- MINIO__SECRET_KEY=${MINIO_ROOT_PASSWORD}
- RABBITMQ__HOSTNAME=rabbitmq
- RABBITMQ__PORT=5672
- RABBITMQ__PORT_MANAGEMENT=15672
- RABBITMQ__MANAGEMENT_SSL=false
- RABBITMQ__USERNAME=${RABBITMQ_DEFAULT_USER}
- RABBITMQ__PASSWORD=${RABBITMQ_DEFAULT_PASS}
- SMTP__HOSTNAME=${SMTP_HOSTNAME}
- SMTP__PORT=25
- PROVIDERS__LOCAL__STRATEGY=LocalStrategy
ports:
- "8080:8080"
depends_on:
- redis
- elasticsearch
- minio
- rabbitmq
restart: always
worker:
image: opencti/worker:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- WORKER_LOG_LEVEL=info
depends_on:
- opencti
deploy:
mode: replicated
replicas: 3
restart: always
connector-export-file-stix:
image: opencti/connector-export-file-stix:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_STIX_ID} # Valid UUIDv4
- CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
- CONNECTOR_NAME=ExportFileStix2
- CONNECTOR_SCOPE=application/json
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_LOG_LEVEL=info
restart: always
depends_on:
- opencti
connector-export-file-csv:
image: opencti/connector-export-file-csv:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_CSV_ID} # Valid UUIDv4
- CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
- CONNECTOR_NAME=ExportFileCsv
- CONNECTOR_SCOPE=text/csv
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_LOG_LEVEL=info
restart: always
depends_on:
- opencti
connector-export-file-txt:
image: opencti/connector-export-file-txt:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_TXT_ID} # Valid UUIDv4
- CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
- CONNECTOR_NAME=ExportFileTxt
- CONNECTOR_SCOPE=text/plain
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_LOG_LEVEL=info
restart: always
depends_on:
- opencti
connector-import-file-stix:
image: opencti/connector-import-file-stix:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${CONNECTOR_IMPORT_FILE_STIX_ID} # Valid UUIDv4
- CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
- CONNECTOR_NAME=ImportFileStix
- CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
- CONNECTOR_SCOPE=application/json,text/xml
- CONNECTOR_AUTO=true # Enable/disable auto-import of file
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_LOG_LEVEL=info
restart: always
depends_on:
- opencti
connector-import-document:
image: opencti/connector-import-document:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${CONNECTOR_IMPORT_DOCUMENT_ID} # Valid UUIDv4
- CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
- CONNECTOR_NAME=ImportDocument
- CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
- CONNECTOR_SCOPE=application/pdf,text/plain,text/html
- CONNECTOR_AUTO=true # Enable/disable auto-import of file
- CONNECTOR_ONLY_CONTEXTUAL=false # Only extract data related to an entity (a report, a threat actor, etc.)
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_LOG_LEVEL=info
- IMPORT_DOCUMENT_CREATE_INDICATOR=true
restart: always
depends_on:
- opencti
connector-alienvault:
image: opencti/connector-alienvault:5.7.1
environment:
- OPENCTI_URL=http://opencti:8080
- OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
- CONNECTOR_ID=${ALIENVAULT_CONNECTOR_ID}
- CONNECTOR_TYPE=EXTERNAL_IMPORT
- CONNECTOR_NAME=AlienVault
- CONNECTOR_SCOPE=alienvault
- CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
- CONNECTOR_UPDATE_EXISTING_DATA=false
- CONNECTOR_LOG_LEVEL=info
- ALIENVAULT_BASE_URL=https://otx.alienvault.com
- ALIENVAULT_API_KEY=${ALIENVAULT_API_KEY}
- ALIENVAULT_TLP=White
- ALIENVAULT_CREATE_OBSERVABLES=true
- ALIENVAULT_CREATE_INDICATORS=true
- ALIENVAULT_PULSE_START_TIMESTAMP=2020-05-01T00:00:00 # BEWARE! Could be a lot of pulses!
- ALIENVAULT_REPORT_TYPE=threat-report
- ALIENVAULT_REPORT_STATUS=New
- ALIENVAULT_GUESS_MALWARE=false # Use tags to guess malware.
- ALIENVAULT_GUESS_CVE=false # Use tags to guess CVE.
- ALIENVAULT_EXCLUDED_PULSE_INDICATOR_TYPES=FileHash-MD5,FileHash-SHA1 # Excluded Pulse indicator types.
- ALIENVAULT_ENABLE_RELATIONSHIPS=true # Enable/Disable relationship creation between SDOs.
- ALIENVAULT_ENABLE_ATTACK_PATTERNS_INDICATES=true # Enable/Disable "indicates" relationships between indicators and attack patterns
- ALIENVAULT_INTERVAL_SEC=1800
restart: always
depends_on:
- opencti
volumes:
esdata:
s3data:
redisdata:
amqpdata:
Запускаем OpenCTI
Подгружаем переменные:
|
|
Запускаем контейнеры:
|
|
Запускаем Wazuh
Если нет Wazuh, то разворачиваем его в Docker
|
|
Добавляем интеграцию wazuh-opencti:
- Из интергации нам потребуются два файла, которые необходимо расположить в
/var/ossec/integrations
. Если позволяет навык, можно добавить из через отдельный volume, либо забрать напрямую из контейнера в с помощью wget.
Запускаем из контейнера:
|
|
- Добавляем настройки в wazuh-manager:
|
|
- Добавляем правила обнаружения:
|
|
Дополнительно добавим небольшое правило для логирования событий запроса DNS:
|
|
Особое внимание уделите группам правил, в вашем случае они могут отличаться.
Разворачиваем Windows и ставим sysmon
- Запускаем powershell от администратора и запускаем установку sysmon:
|
|
- Устанавливаем Wazuh Agent
|
|
- Добавляем настройки в ossec.conf
|
|
- Запускаем wazuh-agent
|
|
Тестирование
Так как у нас есть правила на ICMP запросы, их мы и проверим:
|
|
В случае корректной настройки в Security Events мы увидим следующее:
Возможные проблемы:
При развертывании Wazuh в Docker нет python3 и request:
|
|
Возможно, для production не лучший выход, но для тестового развертывания подойдет.
Итог
Данная статья не претендует на звание исчерпывающего руководства, и больше преследовалась цель показать, что сравнительно небольших усилиях можно сильно упростить себе жизнь. Разумеется, ICMP-запросами это не ограничивается, но для этого нужно писать правила.
Reference:
OpenCTI Connectors
OpenCTI Datasets
OpenCTI Public Knowledge Base
OpenCTI Data Connectors - Add Data Connectors to Your OpenCTI Stack!
Wazuh SIEM — OpenCTI Threat Intel Integration
Github OpenCTI Integration (Not work)
Running OpenCTI using Docker