misp-fixevent-webhook/README.md

501 lines
18 KiB
Markdown
Raw Permalink Normal View History

2025-02-13 16:41:25 -03:00
## Descripción
Este proyecto permite en tiempo real realizar correcciones (limpieza) en los atributos dentro de cada evento en MISP antes de ser publicado en la plataforma. Esto se lleva a cabo a través de la funcionalidad de Workflows que integra MISP.
Como resultado este proyecto implementa una API en un servidor para recibir los datos de cada evento para ser procesados.
2025-03-03 16:49:15 -03:00
(Se necesita el servicio gratuito de lookup de IP's, dominios, url y hashes que ofrece Kaspersky© Threat Intelligence Portal para la limpieza de falsos positivos)
2025-02-13 16:41:25 -03:00
## Características:
2025-03-03 16:49:15 -03:00
- Limpieza de falsos positivos de cada evento generado en MISP (IP, Domain, SHA256, URL)
2025-02-13 16:41:25 -03:00
- Normalización de correlación y activación de tag IDS en cada atributo. Solo se activa tag IDS para el tipo de atributo que corresponde, como a su vez solo se activa la correlación para los tipos de atributos que deben ser correlacionados.
- Normalización de tags para eventos que contengan "tlp: white" ( Se agrega tag tlp:clear en cada caso)
- Utiliza dentro de Workflows, el trigger "event-publish"
## Requisitos
- Se requiere una cuenta en la plataforma Kaspersky© Threat Intelligence Portal. La cuenta es gratuita. ([https://opentip.kaspersky.com])
## Requisitos de Hardware recomendados
- 8/16 GB RAM
- 4 vCPU
- 100 GB almacenamiento
## Componentes
2025-03-07 15:29:49 -03:00
Este proyecto utiliza un BD local SQLite en modo WAL, FastAPI.
2025-02-13 16:41:25 -03:00
## Configuración inicial
1. En el archivo config.py se debe definir los datos de conexión a MISP, como también la API KEY asociada a Kaspersky TIP:
``` python
MISP_CONFIG = {
"misp_url":"URL_MISP",
"misp_authkey":"AUTHKEY_MISP"
}
# Se si quiere agregar a exclusión de MISP cada atributo al deshabilitar correlación
NO_CORRELATIVOS_EXCLUSION = False
# Config Lookup KTIP
KTIP_CONFIG = {
"api_key":"APIKEY_KTIP",
"url_base": "https://opentip.kaspersky.com/api/v1/search/"
}
# Rango de dias para verificar si IoC es falso positivo
RANGO_DIAS = 7
# Se debe establecer Manual
JWT_TOKEN_GEN = "BEARER_TOKEN"
2025-03-07 15:29:49 -03:00
# Máximo de atributos a procesar por evento (2000 es el recomendado)
MAX_ATTRS = 2000
def cargar_fp_en_set(ruta_archivo: str) -> set:
"""
Lee un archivo de texto línea a línea y devuelve un set con cada línea limpia.
"""
conjunto = set()
with open(ruta_archivo, "r", encoding="utf-8") as archivo:
for linea in archivo:
linea_limpia = linea.strip()
if linea_limpia: # Evita líneas vacías
conjunto.add(linea_limpia)
return conjunto
2025-02-13 16:41:25 -03:00
# Falsos positivos comunes
# FP Comunes
2025-03-07 15:29:49 -03:00
FP_COMUNES = cargar_fp_en_set("fp.txt")
2025-02-13 16:41:25 -03:00
# Organizaciones que se puede omitir la revisión de eventos
ORG_OMITIR = []
2025-03-03 16:49:15 -03:00
NO_CORRELACIONES = [
"comment", # Comentarios descriptivos
2025-02-13 16:41:25 -03:00
"email-subject", # Asuntos de correos electrónicos
"email-dst", # Emails de destinatarios
"email-src", # Emails de remitentes
"hostname", # Nombres de host
"port", # Puertos
"link", # Enlaces
"phone-number", # Números de teléfono
"user-agent", # Agentes de usuario
"size-in-bytes", # Tamaños en bytes
"vulnerability", # Vulnerabilidades (CVE)
"whois-registrant-email", # Correos de registrantes WHOIS
"whois-registrant-name", # Nombres de registrantes WHOIS
"regkey", # Claves de registro de Windows
"regkey|value", # Claves de registro con valores
"text", # Texto libre
"datetime", # Fechas y horas
"campaign-name", # Nombres de campaña
2025-03-03 16:49:15 -03:00
"attachment", # Archivos adjuntos
"email", # Emails de remitentes
"email-body", # Cuerpo de Email
"email-attachment" # Archivos adjuntos (variante)
2025-02-13 16:41:25 -03:00
]
2025-03-03 16:49:15 -03:00
IDS_CORRELACIONES = [
2025-02-13 16:41:25 -03:00
"ip-src", # IP de origen
"ip-dst", # IP de destino
"domain", # Dominio
"domain|ip", # Dominio con IP asociada
"url", # URL completas
"uri", # URI (fragmentos de rutas)
"http-method", # Métodos HTTP (GET, POST, etc.)
"email-attachment", # Nombres de archivos adjuntos en correos
"filename", # Nombres de archivo
"filename|md5", # Nombre de archivo con su hash MD5
"filename|sha1", # Nombre de archivo con su hash SHA1
"filename|sha256", # Nombre de archivo con su hash SHA256
"md5", # Hash MD5
"sha1", # Hash SHA1
"sha256", # Hash SHA256
"authentihash", # Hash Authentihash
"impfuzzy", # Hash ImpHash (ejecutable PE)
"tlsh", # Hash TLSH
"ssdeep", # Hash SSDEEP (fuzzy hash)
"mutex", # Nombres de mutex
"registry-key", # Claves de registro (si son relevantes)
"registry-key|value", # Claves de registro con valores
"ip-src|port", # IP de origen con puerto
"ip-dst|port", # IP de destino con puerto
"asn", # ASN (Autonomous System Number)
"cidr", # Rango CIDR (IPs)
"mac-address", # Dirección MAC
"x509-fingerprint-md5", # Huella de certificados X509 (MD5)
"x509-fingerprint-sha1", # Huella de certificados X509 (SHA1)
"x509-fingerprint-sha256", # Huella de certificados X509 (SHA256)
"ja3-fingerprint-md5", # Huella JA3 (TLS handshake)
"btc", # Dirección de Bitcoin
"iban", # Número de cuenta bancaria (IBAN)
"bank-account-nr", # Número de cuenta bancaria
"payment-card-number" # Número de tarjeta de pago
]
2025-03-07 15:29:49 -03:00
CONFIG_WL = {
"filtros_buscar": ["osint", "google", "ipv4", "1000","domains","websites","microsoft","amazon","cloudflare","tranco","cisco","azure","office"],
"max_reg": 10000
}
2025-03-03 16:49:15 -03:00
2025-02-13 16:41:25 -03:00
```
En config.py puedes realizar los ajustes:
- MISP_CONFIG: Configuración asociada a MISP
- NO_CORRELATIVOS_EXCLUSION: Si es True, cada atributo que sea corregida su correlación, ósea que se desactive, será agregado valor a la lista de exclusión de correlaciones.
- KTIP_CONFIG: Configuración de conexión a servicio de Lookup de Kaspersky. Se debe solo configurar "api_key".
- RANGO_DIAS: Establece según la fecha del atributo (IoC) cuantos días tomar como rango para verificar falso positivo
- JWT_TOKEN_GEN: Token personal generado.
2025-03-07 15:29:49 -03:00
- MAX_ATTRS: Cantidad de atributos a procesar por evento. Por defecto el máximo son 2000. No se recomienda aumentar este valor mas alla de los 4000 Attrs.
2025-02-13 16:41:25 -03:00
2025-03-07 15:29:49 -03:00
- FP_COMUNES: Falsos positivos conocidos que se obtienen de un archivo txt.
2025-02-13 16:41:25 -03:00
- ORG_OMITIR: Organizaciones que se puede omitir la revisión de eventos.
2025-03-03 16:49:15 -03:00
- NO_CORRELACIONES: Lista de tipos de atributos que no deben correlacionarse dentro de MISP.
2025-02-13 16:41:25 -03:00
2025-03-03 16:49:15 -03:00
- IDS_CORRELACIONES: Lista de tipos de atributos que deberán tener el flag IDS activado dentro de MISP. Por defecto estos atributos son correlacionados dentro de MISP.
2025-02-13 16:41:25 -03:00
2025-03-07 15:29:49 -03:00
- CONFIG_WL: Configuración de filtros para obtener falsos positivos de WarningList de MISP.
2025-02-13 16:41:25 -03:00
# Configuración Inicial
## Instalación en entorno virtual
1. Se crea entorno virtual de Python
``` shell
cd /home/user/misp-fixevent-webhook
python3 -m venv venv
source venv/bin/activate
```
2. Instalar bibliotecas de Python:
``` shell
pip install -r requirements.txt
```
2025-03-07 15:29:49 -03:00
3. Se debe desactivar entorno para configurar playwright inicialmente.
```shell
deactivate
# Instala dependencias en Ubuntu
sudo venv/bin/playwright install-deps
# instala dependencias de playwright
sudo venv/bin/playwright install
```
4. Se debe crear archivo .sh o editar el archivo existente (start_api.sh) y anexarlo como servicio para que inicie con el sistema operativo:
2025-02-13 16:41:25 -03:00
``` shell
#!/bin/bash
# Activate
source /home/user/misp-fixevent-webhook/venv/bin/activate
# Enter folder
cd /home/user/misp-fixevent-webhook/
# Actualizar bibliotecas si aplica
pip install --upgrade -r requirements.txt > /dev/null 2>&1
# Si vas a utilizar proxy reverso...
uvicorn main:app --host 0.0.0.0 --port 8000
# Si no vas a utilizar proxy reverso puedes utilizar certificados genéricos
uvicorn main:app --host 0.0.0.0 --port 8000 --ssl-keyfile key.pem --ssl-certfile cert.pem
```
Debe activar SSL en proyecto
## Agregar como servicio
1. Para agregar como servicio necesita crear dentro del directorio /etc/systemd/system (En caso de Ubuntu) un archivo .service(misp_webhooks.service). Podemos crearlo con nano (sudo) usando el siguiente formato:
``` shell
sudo nano /etc/systemd/system/misp_webhooks.service
[Unit]
Description=MISP WebHooks Service
After=network.target
[Service]
Type=simple
ExecStart=/home/user/misp-fixevent-webhook/start_api.sh
Restart=always
[Install]
WantedBy=multi-user.target
```
2. Se deben entregar permisos de ejecución a archivo .sh:
```shell
chmod +x /home/user/misp-fixevent-webhook/start_api.sh
```
3. Se recargan servicios:
```shell
sudo systemctl daemon-reload
```
3. Luego registramos este archivo para que se ejecute al iniciar el sistema:
``` shell
sudo systemctl enable misp_webhooks.sevice
```
4. Ahora podemos iniciar, detener, reiniciar servicio...
``` shell
# Iniciar
sudo systemctl start misp_webhooks.sevice
# Detener
sudo systemctl stop misp_webhooks.sevice
# Reiniciar
sudo systemctl restart mmisp_webhooks.sevice
```
## Servicios (Endpoints) de API
- /webhoook/misp_event_fixer/
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/1_docs.png)
## Documentación
Debes agregar
Puedes acceder a la documentación:
SwaggerUI
```
http://URL_PROYECTO:8000/docs
```
Redocly
```
http://URL_PROYECTO:8000/redoc
```
## Configuración en Servidor MISP
Desde MISP necesitamos configurar el Workflow para utilizar nuestra API. Debemos verificar si tenemos "misp-modules" instalados. Estos módulos corren en el puerto 6666. Podemos verificar si el puerto esta activo:
```shell
telnet localhost 6666
```
Si no hay respuesta, necesitamos instalar las siguientes librerías (Ubuntu):
```shell
sudo apt install git python3 python3-pip python3-dev libpq5 libjpeg-dev build-essential libssl-dev libffi-dev zlib1g-dev libmagic-dev libxml2-dev libxslt1-dev libpoppler-cpp-dev libzbar0 tesseract-ocr
```
Una vez instaladas, podemos instalar misp-modules en nuestro servidor MISP (como root).
Desde la versión 2.5, no se incluye misp-modules (Para más información: https://misp.github.io/misp-modules/install/)
1. Creamos directorio dentro de MISP:
``` shell
sudo su
cd /var/www/MISP
mkdir misp-modules
cd /misp-modules
```
2. Creamos entorno virtual y activamos:
``` shell
python3 -m venv venv
source venv/bin/activate
```
3. Instalamos librerías:
``` shell
pip install \
misp-modules \
git+https://github.com/cartertemm/ODTReader.git \
git+https://github.com/abenassi/Google-Search-API \
git+https://github.com/SteveClement/trustar-python.git \
git+https://github.com/sebdraven/pydnstrails.git \
git+https://github.com/sebdraven/pyonyphe.git
```
4. Creamos un .sh (run.sh) para llamar como servicio cada vez que parta el equipo:
``` shell
sudo nano run.sh
```
5. Dentro del archivo definimos las rutas (según sea el caso):
```shell
#!/bin/bash
# Activate
source /var/www/MISP/misp-modules/venv/bin/activate
# Enter folder
cd /var/www/MISP/misp-modules/venv/bin/
# Ejecutar misp-modules
misp-modules
```
6. Configuramos servicio:
```shell
sudo nano /etc/systemd/system/misp-modules.service
```
7. Dentro del archivo definimos las rutas (según sea el caso):
```shell
[Unit]
Description=MISP Modules Service
After=network.target
[Service]
Type=simple
ExecStart=/var/www/MISP/misp-modules/run.sh
Restart=always
[Install]
WantedBy=multi-user.target
```
7. Se deben entregar permisos de ejecución a archivo .sh:
```shell
chmod +x /var/www/MISP/misp-modules/run.sh
```
8. Se recargan servicios:
```shell
sudo systemctl daemon-reload
```
2025-03-03 16:49:15 -03:00
9. Luego registramos este archivo para que se ejecute al iniciar el sistema:
2025-02-13 16:41:25 -03:00
``` shell
sudo systemctl enable misp-modules.sevice
```
10. Configuramos carpeta de MISP como owner original "www-data"
```shell
sudo chown -R www-data:www-data /var/www/MISP
```
2025-03-03 16:49:15 -03:00
11. Arrancamos APP:
```shell
sudo systemctl start misp-modules.sevice
```
2025-02-13 16:41:25 -03:00
## Activando / Configurando Workflow en MISP
1. Accedemos a MISP y nos dirigimos a "Administration"->"Server Settings & Maintenance"->"Plugin":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/2_plugin.png)
2. Dentro de Plugin activamos "Enrichment":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/3_enrich.png)
3. Luego "Action" y "Workflow":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/4_action.png)
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/5_workflow.png)
4. Para poder llamar a nuestro webhook desde MISP necesitamos modificar una propiedad de MISP desde el MISP CLI desde terminal:
```shell
sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting Security.rest_client_enable_arbitrary_urls true
```
5. Iniciamos sesión en nuestro MISP y nos dirigimos a "Administration"->"Worflows" de MISP:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/6_workflow_set.png)
6. El webhook está diseñado para llamarse en el proceso previo a publicar un evento en MISP, este trigger se llama "event-publish" y debemos activarlo yendo a "List Triggers"->"Event Publish" y presionamos el botón de play:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/7_ev_publish.png)
7. Luego en la misma ventana, vamos a la sección de "List Modules" y activamos el módulo de "Webhook":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/8_list_modules.png)
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/9_webhook_play.png)
8. Para agregar más control en el flujo (Para el caso de Eventos que no tengan atributos => 0) vamos a activar dentro del "List Modules" en "Logic" el módulo "IF::Count":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/9_ifcount_play.png)
9. Finalmente desde la misma ventana, en "Blocking" activamos "Stop execution":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/9_stop_execution_play.png)
## Configuración Webhook
1. Ahora vamos a ir a la configuración de nuestro trigger "event-publish" para configurar los datos para enviar al webhook. Nos dirigimos al símbolo "</>":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/10_webhook_edit.png)
2. Desde la lista de "Actions", Agregamos "Webhook" al plano de diseño arrastrando:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/11_webhook_add.png)
3. Desde la lista de "Logic", Agregamos "IF :: Count" al plano de diseño arrastrando:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/11_ifcount_add.png)
4. Desde la lista de "Actions", Agregamos "Stop execution" al plano de diseño arrastrando:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/11_stop_execution_add.png)
5. Conectamos "Event Publish" con "IF :: Count":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/12_eventpublish_ifcount.png)
6. En el módulo IF :: Count configuramos "Data selector to count" con el valor "All Attributes", esto quiere decir que contara todos los atributos del evento:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/13_ifcount.png)
7. En el mismo módulo en "Condition" seteamos como "Equals to" y en "Value" queda en 0:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/13_ifcount_2.png)
8. Si el evento no tiene atributos, se detendrá la ejecución de "publish" en el evento. Debemos conectar en el resultado afirmativo del módulo IF :: Count el módulo "Stop execution":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/13_ifcount_3.png)
9. En caso contrario, que Evento SI tenga atributos, lo conectamos al módulo "Webhook" para que procese los datos:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/13_ifcount_webhook.png)
10. Ahora necesitamos configurar los datos que tenemos que mandar al Webhook. Los datos son los siguientes:
- URL: https://IP_SERVIDOR_API:8000/webhook/misp_event_fixer/
- Payload: {
"event_id": "{{ Event.id }}",
"event_uuid": "{{ Event.uuid }}",
"event_attribute_count": "{{ Event.attribute_count }}"
}
- Header: Authorization: Bearer <MI_JWT_TOKEN>
11. Vamos a puntos arriba mano derecha y editamos el módulo para agregar esta información:
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/14_webhook_edit.png)
12. Ingresamos la información mencionada en el punto 10 y para finalizar presionamos el botón "Close":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/14_webhook_config_1.png)
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/14_webhook_config_2.png)
13. Guardamos el Workflow en MISP haciendo clic en "Save":
![alt text](https://git.csirt.gob.cl/public/misp-fixevent-webhook/raw/branch/main/img_static/14_webhook_save.png)
Con estos pasos realizados, desde ahora en adelante dentro de MISP, cada evento generado por la organización local o de instancias remotas, será revisado y corregido por nuestro servicio web.
Cualquier duda o consulta envíanos un correo a: misp@anci.gob.cl