Skip to content

hernannh/ipflame

Repository files navigation

IP-Flame CTI

Threat Intelligence Dashboard para equipos Blue Team. Escanea logs de servidores web, detecta patrones maliciosos (238 reglas en 14 categorias), enriquece las IPs maliciosas con datos de geolocalizacion/ASN/riesgo, calcula un risk score (0-100) y genera reportes en multiples formatos para integracion con SIEM.

time=2026-04-03T13:06:26.570-03:00 level=INFO msg="Iniciando IP-Flame Multi-Log Engine" version=3.2
time=2026-04-03T13:06:26.571-03:00 level=INFO msg="Patrones cargados" count=238 format=nginx-combined
time=2026-04-03T13:06:26.571-03:00 level=INFO msg="GeoLite2-City cargada"
time=2026-04-03T13:06:26.572-03:00 level=INFO msg="GeoLite2-ASN cargada"
time=2026-04-03T13:06:29.100-03:00 level=INFO msg="Enriquecimiento CTI" local=3421 api=258 note="258 IPs enviadas a ipquery.io para enriquecimiento"
time=2026-04-03T13:06:29.300-03:00 level=INFO msg=Resultados threat_actors=89 hits=1372 patterns=238
time=2026-04-03T13:06:29.350-03:00 level=INFO msg="Dashboard generado" path=output/flamed-ips.html
time=2026-04-03T13:06:29.400-03:00 level=INFO msg="Geo Intelligence dashboard" path=output/dashboard-geo.html
time=2026-04-03T13:06:29.410-03:00 level=INFO msg="Reporte JSON exportado" path=output/report.json
time=2026-04-03T13:06:29.420-03:00 level=INFO msg="IP-Flame finalizado" version=3.2

Screenshots

Wall of Shame — Dashboard operativo

Wall of Shame - Vista general

Wall of Shame - Detalle de threat actors

Wall of Shame - Filtros y paginacion

Wall of Shame - Detalle expandido

Geo Intelligence — Mapa interactivo

Geo Intelligence - Mapa mundial

Geo Intelligence - Stats y distribucion

Reportes y salida

Resultados - JSON y threat actors

Resultados - Pattern summary

Resultados - Terminal output


Indice


Caracteristicas

  • Deteccion de amenazas — 238 patrones en 14 categorias: CMS, config exposure, VCS, RCE/webshells, SQLi, XSS, command injection, Log4Shell/JNDI, SSRF/cloud metadata, scanners, CVEs activos, AI crawlers, protocol abuse, tool fingerprinting
  • CTI hibrido — Resolucion local con GeoLite2 (City + ASN) con fallback automatico a ipquery.io API (incluye deteccion de VPN/Tor/Proxy/Datacenter y risk score). Log explicito cuando se envian IPs a la API externa
  • Risk scoring — Puntuacion 0-100 por IP basada en: volumen de hits, diversidad de patrones, indicadores de anonimizacion (Tor/VPN/Proxy) y score de la API
  • Deteccion case-insensitive — Match en lowercase + URL decode recursivo (2 niveles) para detectar evasiones con encoding
  • Multiples formatos de salida — Wall of Shame HTML, Geo Intelligence dashboard (mapa Leaflet), JSON, JSONL (SIEM), threat-actors.txt (CrowdSec), pattern-summary.txt
  • Geo Intelligence dashboard — Mapa interactivo con Leaflet, distribucion de riesgo, top paises/ISPs/patrones/hosts atacados, indicadores TOR/VPN/Proxy
  • Host destino opcional — Columna condicional que muestra a que dominio/IP de tu infraestructura apunta cada ataque (requiere log-host-field)
  • Webhooks — Alertas a Slack, Telegram, Discord, n8n o endpoint generico, filtradas por nivel de riesgo
  • Modo watch — Monitoreo continuo tipo tail -f con intervalo configurable
  • Soporte multi-formato — Logs nginx/apache combined (W3C), formato key-value personalizado, e IIS W3C Extended
  • Concurrencia — Escaneo paralelo de multiples archivos de log
  • Paginacion y filtros — Dashboard HTML con paginacion configurable (25/50/100/250/todos), filtros por nivel de riesgo y filtro por pais (dropdown auto-poblado desde los resultados)
  • Structured logging — Todos los paquetes usan log/slog (modo texto por defecto, modo JSON con --log-json para SIEM/observabilidad)
  • Variables de entorno — Configuracion via IPFLAME_* como fallback (el archivo de config tiene precedencia)
  • Exit codes — 0=exito, 1=sin archivos de log, 2=error de configuracion (documentados para integracion con cron/systemd)
  • Security hardening — Prevencion de path traversal, limite de longitud de patrones (256 chars), validacion de IPs en respuestas de API
  • Binarios pre-compilados — Linux y macOS (amd64/arm64), zero dependencias, disponibles en GitHub Releases

Inicio rapido

Requisitos

  • Linux (amd64/arm64), macOS (amd64/arm64) o Windows (amd64)
  • Bases de datos GeoLite2 (opcionales, se descargan con update-geoip.sh)

Instalacion desde GitHub Releases

# Linux amd64
curl -Lo ip-flame https://github.com/hernannh/ipflame/releases/latest/download/ip-flame-linux-amd64
chmod +x ip-flame

# Linux arm64 (Raspberry Pi, AWS Graviton)
curl -Lo ip-flame https://github.com/hernannh/ipflame/releases/latest/download/ip-flame-linux-arm64
chmod +x ip-flame

# macOS Apple Silicon (M1/M2/M3)
curl -Lo ip-flame https://github.com/hernannh/ipflame/releases/latest/download/ip-flame-darwin-arm64
chmod +x ip-flame

# Windows amd64 (PowerShell)
Invoke-WebRequest -Uri https://github.com/hernannh/ipflame/releases/latest/download/ip-flame-windows-amd64.exe -OutFile ip-flame.exe

Setup inicial

# Clonar este repositorio (templates + config)
git clone https://github.com/hernannh/ipflame.git
cd ipflame

# Descargar bases GeoIP (opcional pero recomendado)
chmod +x update-geoip.sh
./update-geoip.sh

# Editar configuracion (ajustar web-log= a la ruta de tus logs)
nano config-ip-flame.txt

# Ejecutar
./ip-flame --config config-ip-flame.txt

Verificar integridad

Cada release incluye checksums-sha256.txt:

sha256sum -c checksums-sha256.txt

Docker

docker compose up --build

Uso con binario

./ip-flame [flags]
Flag Default Descripcion
-config config-ip-flame.txt Ruta al archivo de configuracion
-whitelist whitelist.txt Ruta al archivo de whitelist
-watch false Modo watch: monitoreo continuo de logs
-interval 30 Intervalo en segundos entre escaneos (modo watch)
--log-json false Logging estructurado en formato JSON (salida a stderr). Ideal para SIEM/observabilidad

Exit codes

Codigo Significado Uso
0 Exito Escaneo completado correctamente
1 Sin archivos de log No se encontraron archivos que matcheen el glob de web-log
2 Error de configuracion Archivo de config invalido, parametros faltantes o error de parsing

Estos codigos permiten integracion confiable con cron, systemd y scripts de orquestacion:

# Ejemplo con cron: alertar si no hay logs
/opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt
EXIT_CODE=$?
if [ $EXIT_CODE -eq 1 ]; then
  echo "WARN: ip-flame no encontro archivos de log" | mail -s "IP-Flame: sin logs" admin@example.com
fi

Ejecucion puntual (batch)

Escanea los logs, genera todos los reportes y termina:

# Con config por defecto (busca config-ip-flame.txt en el directorio actual)
./ip-flame

# Especificando rutas
./ip-flame --config /etc/ipflame/config.txt --whitelist /etc/ipflame/whitelist.txt

# Con logging JSON (para redirigir a un SIEM o archivo)
./ip-flame --log-json 2>> /var/log/ip-flame-structured.json

Monitoreo continuo (watch)

Mantiene el proceso activo, escanea nuevas lineas de log en cada intervalo y regenera reportes si hay nuevos hits. Soporta rotacion de logs automaticamente.

# Watch con intervalo de 30 segundos (default)
./ip-flame --watch

# Watch con intervalo de 60 segundos
./ip-flame --watch --interval 60

# Watch con logging JSON
./ip-flame --watch --interval 60 --log-json

# Watch en background con nohup
nohup ./ip-flame --watch --interval 60 >> /var/log/ip-flame.log 2>&1 &

Para detener el modo watch: Ctrl+C o enviar SIGINT/SIGTERM al proceso.

Automatizacion con cron (sin modo watch)

Si preferis ejecuciones puntuales en lugar de modo watch:

# Cada hora
0 * * * * /opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt >> /var/log/ip-flame.log 2>&1

# Cada 15 minutos
*/15 * * * * /opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt >> /var/log/ip-flame.log 2>&1

Automatizacion con systemd timer

Alternativa a cron, recomendada en sistemas modernos con systemd. Ofrece mejor logging (journald), control de dependencias y manejo de errores.

1. Crear el service unit/etc/systemd/system/ip-flame.service:

[Unit]
Description=IP-Flame CTI — Threat Intelligence Scanner
After=network.target

[Service]
Type=oneshot
ExecStart=/opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt --whitelist /opt/ip-flame/whitelist.txt
WorkingDirectory=/opt/ip-flame
StandardOutput=journal
StandardError=journal
# Seguridad: ejecutar como usuario sin privilegios
User=ipflame
Group=ipflame
# Hardening opcional
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/ip-flame/output
ReadOnlyPaths=/var/log/nginx /opt/ip-flame/config.txt /opt/ip-flame/whitelist.txt /opt/ip-flame/geoip
PrivateTmp=true

2. Crear el timer unit/etc/systemd/system/ip-flame.timer:

[Unit]
Description=IP-Flame CTI — Escaneo periodico

[Timer]
# Ejecutar cada 15 minutos
OnCalendar=*:0/15
# Distribuir ejecucion aleatoriamente en ventana de 60s (evita thundering herd)
RandomizedDelaySec=60
# Ejecutar inmediatamente si se perdio la ultima ejecucion (ej: servidor apagado)
Persistent=true

[Install]
WantedBy=timers.target

3. Habilitar y arrancar:

# Recargar systemd
sudo systemctl daemon-reload

# Habilitar el timer (sobrevive reboots)
sudo systemctl enable ip-flame.timer

# Arrancar el timer ahora
sudo systemctl start ip-flame.timer

# Verificar estado
sudo systemctl status ip-flame.timer
sudo systemctl list-timers | grep ip-flame

# Ver logs de ejecuciones
sudo journalctl -u ip-flame.service -f

# Ejecutar manualmente (sin esperar al timer)
sudo systemctl start ip-flame.service

Variantes de OnCalendar utiles:

OnCalendar=*:0/15          # Cada 15 minutos
OnCalendar=hourly           # Cada hora
OnCalendar=*-*-* 06,18:00  # A las 06:00 y 18:00
OnCalendar=daily            # Una vez al dia (medianoche)
OnCalendar=Mon *-*-* 03:00 # Lunes a las 03:00

Modo watch como servicio systemd

Si preferis usar el modo --watch en lugar del timer:

# /etc/systemd/system/ip-flame-watch.service
[Unit]
Description=IP-Flame CTI — Watch Mode (monitoreo continuo)
After=network.target

[Service]
Type=simple
ExecStart=/opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt --watch --interval 60
WorkingDirectory=/opt/ip-flame
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
User=ipflame
Group=ipflame
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/ip-flame/output
ReadOnlyPaths=/var/log/nginx /opt/ip-flame/config.txt /opt/ip-flame/whitelist.txt /opt/ip-flame/geoip
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now ip-flame-watch.service
sudo journalctl -u ip-flame-watch.service -f

Uso con Docker

La imagen incluye el binario, templates y config por defecto. Solo necesitas montar los logs y el directorio de salida.

Volumenes

Volumen host Destino en contenedor Modo Necesario Descripcion
Directorio de logs /app/logs :ro Si Logs del servidor web
output/ /app/output rw Si Directorio de salida de reportes
geoip/ /app/geoip :ro Opcional Bases GeoLite2 (sin esto usa ipquery.io)
config-ip-flame.txt /app/config-ip-flame.txt :ro Opcional Solo si necesitas personalizar la config incluida
whitelist.txt /app/whitelist.txt :ro Opcional Solo si necesitas personalizar la whitelist incluida

Importante: El web-log en la config debe apuntar a la ruta dentro del contenedor: web-log=/app/logs/*log*

Ejecucion puntual

# Nginx
docker run --rm \
  -v /var/log/nginx:/app/logs:ro \
  -v ./output:/app/output \
  ip-flame

# Apache
docker run --rm \
  -v /var/log/apache2:/app/logs:ro \
  -v ./output:/app/output \
  ip-flame

# Con GeoIP local y config personalizada
docker run --rm \
  -v /var/log/nginx:/app/logs:ro \
  -v ./geoip:/app/geoip:ro \
  -v ./mi-config.txt:/app/config-ip-flame.txt:ro \
  -v ./output:/app/output \
  ip-flame

Monitoreo continuo (watch) con Docker

# Foreground
docker run --rm --name ip-flame-watch \
  -v /var/log/nginx:/app/logs:ro \
  -v ./geoip:/app/geoip:ro \
  -v ./output:/app/output \
  ip-flame ./ip-flame --watch --interval 60

# Background (daemon)
docker run -d --name ip-flame-watch \
  --restart unless-stopped \
  -v /var/log/nginx:/app/logs:ro \
  -v ./geoip:/app/geoip:ro \
  -v ./output:/app/output \
  ip-flame ./ip-flame --watch --interval 60

# Ver logs del modo watch
docker logs -f ip-flame-watch

# Detener
docker stop ip-flame-watch

Docker Compose

El docker-compose.yml incluido esta configurado para ejecucion puntual:

# Ejecucion puntual
docker compose up --build

# Watch en background
docker compose up -d --build

# Ver logs
docker compose logs -f

# Detener
docker compose down

Para modo watch, agregar el comando en el compose:

command: ["./ip-flame", "--watch", "--interval", "60"]
restart: unless-stopped

Automatizacion con cron (Docker)

# Ejecutar cada hora como contenedor efimero
0 * * * * docker run --rm \
  -v /var/log/nginx:/app/logs:ro \
  -v /opt/ip-flame/geoip:/app/geoip:ro \
  -v /opt/ip-flame/output:/app/output \
  ip-flame >> /var/log/ip-flame.log 2>&1

Automatizacion con Ofelia (cron nativo Docker)

Ofelia es un job scheduler disenado para Docker — reemplaza al cron del host y permite definir schedules directamente en labels de docker-compose. No requiere instalar cron en el host ni dentro de los contenedores.

Opcion A — Labels en docker-compose.yml (recomendada):

services:
  ip-flame:
    build: .
    container_name: ip-flame-run
    restart: "no"
    labels:
      # Ofelia: ejecutar cada 15 minutos
      ofelia.enabled: "true"
      ofelia.job-exec.ip-flame-scan.schedule: "0 */15 * * * *"
      ofelia.job-exec.ip-flame-scan.command: "./ip-flame"
      ofelia.job-exec.ip-flame-scan.no-overlap: "true"
    volumes:
      - ./geoip:/app/geoip:ro
      - /var/log/nginx:/app/logs:ro
      - ./output:/app/output

  ofelia:
    image: mcuadros/ofelia:latest
    container_name: ofelia-scheduler
    restart: unless-stopped
    depends_on:
      - ip-flame
    command: daemon --docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

Nota: El formato de schedule en Ofelia usa 6 campos (incluye segundos): segundo minuto hora dia mes dia_semana.

Opcion B — Archivo de configuracion de Ofelia:

Si preferis no usar labels, crea un archivo ofelia.ini:

[job-exec "ip-flame-scan"]
schedule = 0 */15 * * * *
container = ip-flame-run
command = ./ip-flame
no-overlap = true

[job-exec "ip-flame-geoip-update"]
schedule = 0 0 3 * * 1
container = ip-flame-run
command = /bin/sh -c "apk add --no-cache curl && /app/update-geoip.sh"
no-overlap = true
# docker-compose.yml con ofelia.ini
services:
  ip-flame:
    build: .
    container_name: ip-flame-run
    restart: "no"
    volumes:
      - ./geoip:/app/geoip:ro
      - /var/log/nginx:/app/logs:ro
      - ./output:/app/output

  ofelia:
    image: mcuadros/ofelia:latest
    container_name: ofelia-scheduler
    restart: unless-stopped
    command: daemon --config /etc/ofelia/config.ini
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./ofelia.ini:/etc/ofelia/config.ini:ro

Schedules utiles para Ofelia:

0 */15 * * * *     # Cada 15 minutos
0 0 * * * *        # Cada hora
0 0 */6 * * *      # Cada 6 horas
0 0 0 * * *        # Diariamente a medianoche
0 0 3 * * 1        # Lunes a las 03:00 (para update de GeoIP)

Verificar que Ofelia esta ejecutando los jobs:

docker logs -f ofelia-scheduler

Configuracion

El archivo de configuracion usa formato clave=valor. Las lineas vacias y las que comienzan con # se ignoran.

Parametros disponibles

Parametro Descripcion Ejemplo
web-path= Directorio de salida (se agrega flamed-ips.html automaticamente) web-path=output/
web-log= Glob de archivos de log a escanear (soporta wildcards) web-log=/var/log/nginx/*log*
log-format= Formato del log: nginx-combined, kv o iis-w3c log-format=iis-w3c
geoip-dir= Directorio con las bases GeoLite2 .mmdb geoip-dir=geoip
offending-lines= Patrones de deteccion separados por coma (case-insensitive) offending-lines=wp-login.php,.env,nikto
log-ip-field= (solo kv) Campo que contiene la IP del cliente log-ip-field=CLIENT-IP
log-req-field= (solo kv) Campo que contiene el request HTTP log-req-field=REQ
log-ua-field= (solo kv) Campo que contiene el User-Agent log-ua-field=UA
log-status-field= (solo kv) Campo que contiene el status code HTTP log-status-field=STATUS
log-time-field= (solo kv) Campo que contiene el timestamp log-time-field=TIME
log-host-field= (solo kv) Campo que contiene el Host/dominio destino. Opcional — si no se configura, la columna no aparece en los reportes log-host-field=HOST
webhook= Configuracion de webhook (ver Webhooks) webhook=slack,https://hooks.slack.com/...

Variables de entorno

Todos los parametros de configuracion se pueden definir via variables de entorno con prefijo IPFLAME_. El archivo de configuracion tiene precedencia sobre las variables de entorno (si un parametro esta definido en ambos, se usa el valor del archivo).

Variable de entorno Equivalente en config Descripcion
IPFLAME_WEB_PATH web-path= Directorio de salida
IPFLAME_WEB_LOG web-log= Glob de archivos de log
IPFLAME_LOG_FORMAT log-format= Formato del log
IPFLAME_GEOIP_DIR geoip-dir= Directorio de bases GeoLite2
IPFLAME_LOG_IP_FIELD log-ip-field= Campo IP (formato kv)
IPFLAME_LOG_REQ_FIELD log-req-field= Campo request (formato kv)
IPFLAME_LOG_UA_FIELD log-ua-field= Campo User-Agent (formato kv)
IPFLAME_LOG_HOST_FIELD log-host-field= Campo Host (formato kv)

Esto es util para entornos Docker/Kubernetes donde se prefiere configurar via environment en lugar de montar archivos:

# Ejecucion con variables de entorno (sin archivo de config)
IPFLAME_WEB_PATH=output/ \
IPFLAME_WEB_LOG="/var/log/nginx/*log*" \
IPFLAME_LOG_FORMAT=nginx-combined \
IPFLAME_GEOIP_DIR=geoip \
./ip-flame

# Docker con variables de entorno
docker run --rm \
  -e IPFLAME_WEB_PATH=/app/output/ \
  -e IPFLAME_WEB_LOG="/app/logs/*log*" \
  -e IPFLAME_LOG_FORMAT=nginx-combined \
  -e IPFLAME_GEOIP_DIR=/app/geoip \
  -v /var/log/nginx:/app/logs:ro \
  -v ./output:/app/output \
  ip-flame

Whitelist

El archivo whitelist.txt contiene una IP por linea. Las lineas vacias y las que comienzan con # se ignoran.

# IPs internas / equipo de desarrollo
192.168.1.1
10.0.0.50

Ejemplos de configuracion por servidor

Nginx / Apache (formato combined estandar):

log-format=nginx-combined
web-log=/var/log/nginx/*log*

Nginx detras de Cloudflare (formato kv personalizado):

log-format=kv
log-ip-field=CLIENT-IP
log-req-field=REQ
log-ua-field=UA
log-status-field=STATUS
log-time-field=TIME
log-host-field=HOST
web-log=/var/log/nginx/*log*

Nota sobre log-host-field: Este campo es opcional. Si se configura y los logs contienen el dato, se habilita automaticamente la columna "Host Destino" en el Wall of Shame, el campo target_host en los JSON, y el panel "Hosts mas atacados" en el Geo Intelligence dashboard. Si no se configura, estos elementos no aparecen — sin columnas vacias ni campos innecesarios.

Ejemplo de log_format en nginx.conf para formato kv:

log_format cloudflare
    'CLIENT-IP="$http_cf_connecting_ip" '
    'REAL-IP="$http_cf_connecting_ip" '
    'CF-IP="$remote_addr" '
    'HOST="$host" '
    'TIME="[$time_local]" '
    'REQ="$request" '
    'STATUS=$status '
    'BYTES=$body_bytes_sent '
    'REFERER="$http_referer" '
    'UA="$http_user_agent" '
    'COUNTRY="$http_cf_ipcountry"';

IIS (Internet Information Services) — formato W3C Extended:

log-format=iis-w3c
web-log=C:\inetpub\logs\LogFiles\W3SVC1\*.log

IP-Flame parsea automaticamente la linea #Fields: de cada archivo para detectar la posicion de los campos. Esto significa que funciona con cualquier combinacion de campos que IIS tenga configurada, no solo el formato por defecto.

Formato por defecto de IIS:

#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2026-03-29 10:15:30 192.168.1.1 GET /wp-login.php - 80 - 45.33.32.1 Mozilla/5.0+(Windows+NT+10.0) - 404 0 0 125

Campos que IP-Flame extrae del log IIS:

Campo IIS Uso en IP-Flame
c-ip IP del cliente (IP maliciosa)
date + time Timestamp (se combinan)
cs-method + cs-uri-stem + cs-uri-query Request reconstruido (ej: GET /path?query)
sc-status Status code HTTP
cs(User-Agent) User-Agent (los + se decodifican a espacios)

Nota para Docker: En Windows, montar el directorio de logs de IIS como volumen:

docker run --rm \
  -v C:\inetpub\logs\LogFiles\W3SVC1:/app/logs:ro \
  -v .\config-ip-flame.txt:/app/config-ip-flame.txt:ro \
  -v .\output:/app/output \
  ip-flame

Configurar logging W3C en IIS:

  1. Abrir IIS Manager > Seleccionar el sitio > Logging
  2. Format: W3C
  3. En Select Fields, asegurarse de tener habilitados: c-ip, cs-method, cs-uri-stem, cs-uri-query, sc-status, cs(User-Agent), date, time
  4. Ruta por defecto de los logs: C:\inetpub\logs\LogFiles\W3SVC1\

Archivos de salida

IP-Flame genera 6 archivos en el directorio configurado por web-path:

Archivo Formato Uso Audiencia
flamed-ips.html HTML Wall of Shame — tabla operativa con filtros por riesgo y pais, paginacion, columna Host condicional y detalle expandible por IP SOC / Blue Team
dashboard-geo.html HTML Geo Intelligence — mapa Leaflet interactivo, distribucion de riesgo, top paises/ISPs/patrones/hosts, indicadores TOR/VPN/Proxy Management / Executive
report.json JSON Reporte completo con summary y todos los threat actors Analisis / Herramientas
report.jsonl JSONL Una linea JSON por threat actor Ingestion SIEM (Wazuh, Elastic, Splunk)
threat-actors.txt Texto Lista plana de IPs CrowdSec, fail2ban, iptables
pattern-summary.txt Texto Resumen de patrones ordenados por cantidad de hits Analisis de tendencias

Estructura del JSON

{
  "tool": "ip-flame",
  "version": "3.2",
  "generated_at": "2026-03-29T20:27:15-03:00",
  "summary": {
    "total_threat_actors": 3623,
    "total_hits": 20952,
    "risk_critical": 0,
    "risk_high": 18,
    "risk_medium": 254,
    "risk_low": 3351
  },
  "threat_actors": [
    {
      "ip": "173.212.230.39",
      "country": "France (FR)",
      "city": "Lauterbourg",
      "isp": "Contabo GmbH",
      "asn": "AS51167",
      "risk_score": 50,
      "risk_level": "high",
      "is_vpn": false,
      "is_tor": false,
      "is_proxy": false,
      "is_datacenter": false,
      "hit_count": 1174,
      "first_seen": "19/Mar/2026:07:45:39 +0000",
      "last_seen": "19/Mar/2026:07:45:47 +0000",
      "top_request": "GET /media/.env HTTP/1.1",
      "top_user_agent": "Mozilla/5.0 ...",
      "matched_patterns": [".env", ".sql", "wp-config.php", "..."],
      "hits": [
        {
          "timestamp": "19/Mar/2026:07:45:39 +0000",
          "request": "GET /media/.env HTTP/1.1",
          "status_code": "301",
          "user_agent": "Mozilla/5.0 ...",
          "matched_pattern": ".env"
        }
      ],
      "cti_source": "local"
    }
  ]
}

Integracion con SIEM

IP-Flame genera report.jsonl (una linea JSON por threat actor) disenado para ingestion directa en SIEM. Tambien se puede usar report.json (reporte completo) o el webhook generico para envio en tiempo real.

Wazuh

1. Configurar la lectura del archivo JSONL

Editar /var/ossec/etc/ossec.conf en el manager para monitorear el archivo de salida:

<ossec_config>
  <localfile>
    <log_format>json</log_format>
    <location>/opt/ip-flame/output/report.jsonl</location>
    <label key="source">ip-flame</label>
  </localfile>
</ossec_config>

Si IP-Flame corre en un agente remoto, agregar el bloque <localfile> en el ossec.conf del agente, o usar centralized configuration desde el manager con <agent_config>.

2. Crear el decoder

Crear /var/ossec/etc/decoders/ipflame_decoder.xml:

<decoder name="ipflame">
  <prematch>^{"ip":</prematch>
  <plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>

3. Crear las reglas

Crear /var/ossec/etc/rules/ipflame_rules.xml:

<group name="ipflame,threat_intel,">

  <!-- Regla base: cualquier threat actor detectado por IP-Flame -->
  <rule id="100100" level="3">
    <decoded_as>ipflame</decoded_as>
    <description>IP-Flame: threat actor detectado — $(ip) [$(risk_level)] score:$(risk_score)</description>
    <group>ipflame,</group>
  </rule>

  <!-- Nivel medium -->
  <rule id="100101" level="6">
    <if_sid>100100</if_sid>
    <field name="risk_level">medium</field>
    <description>IP-Flame: threat actor MEDIUM — $(ip) score:$(risk_score) hits:$(hit_count) — $(country)</description>
    <group>ipflame,medium,</group>
  </rule>

  <!-- Nivel high -->
  <rule id="100102" level="10">
    <if_sid>100100</if_sid>
    <field name="risk_level">high</field>
    <description>IP-Flame: threat actor HIGH — $(ip) score:$(risk_score) hits:$(hit_count) — $(country) $(isp)</description>
    <group>ipflame,high,</group>
    <options>alert_by_email</options>
  </rule>

  <!-- Nivel critical -->
  <rule id="100103" level="14">
    <if_sid>100100</if_sid>
    <field name="risk_level">critical</field>
    <description>IP-Flame: threat actor CRITICAL — $(ip) score:$(risk_score) hits:$(hit_count) — $(country) $(isp)</description>
    <group>ipflame,critical,</group>
    <options>alert_by_email</options>
  </rule>

  <!-- Threat actor usando Tor -->
  <rule id="100104" level="12">
    <if_sid>100100</if_sid>
    <field name="is_tor">true</field>
    <description>IP-Flame: threat actor desde TOR — $(ip) score:$(risk_score) — $(country)</description>
    <group>ipflame,tor,</group>
  </rule>

  <!-- Threat actor usando VPN -->
  <rule id="100105" level="8">
    <if_sid>100100</if_sid>
    <field name="is_vpn">true</field>
    <description>IP-Flame: threat actor desde VPN — $(ip) score:$(risk_score) — $(country) $(isp)</description>
    <group>ipflame,vpn,</group>
  </rule>

  <!-- Threat actor con muchos hits (posible scanner automatizado) -->
  <rule id="100106" level="10" frequency="1" timeframe="1">
    <if_sid>100100</if_sid>
    <field name="hit_count" type="pcre2">\d{3,}</field>
    <description>IP-Flame: scanner masivo — $(ip) hits:$(hit_count) — $(country) $(isp)</description>
    <group>ipflame,scanner,</group>
  </rule>

</group>

4. Validar y reiniciar

# Verificar que decoder y reglas no tengan errores de sintaxis
/var/ossec/bin/wazuh-logtest

# Reiniciar el manager
sudo systemctl restart wazuh-manager

# Verificar en los logs que el archivo se esta monitoreando
sudo tail -f /var/ossec/logs/ossec.log | grep ip-flame

5. Verificar en Wazuh Dashboard

Una vez ingresados los datos, en el dashboard de Wazuh se pueden buscar con:

  • Discover: filtrar por rule.groups: ipflame
  • Alertas: los threat actors critical/high aparecen como alertas nivel 10-14
  • Campos disponibles para filtros y visualizaciones:
Campo Wazuh Contenido
data.ip IP del threat actor
data.risk_score Score 0-100
data.risk_level critical / high / medium / low
data.hit_count Cantidad de hits
data.country Pais con codigo ISO
data.isp Proveedor de internet
data.asn Numero de sistema autonomo
data.is_tor true/false
data.is_vpn true/false
data.is_proxy true/false
data.first_seen Primer hit detectado
data.last_seen Ultimo hit detectado
data.matched_patterns[] Patrones que disparo
data.cti_source Fuente CTI: local o api

6. Active response (bloqueo automatico)

Para bloquear automaticamente IPs critical con Wazuh active response:

<!-- En ossec.conf del manager -->
<active-response>
  <command>firewall-drop</command>
  <location>local</location>
  <rules_id>100103</rules_id>  <!-- solo critical -->
  <timeout>43200</timeout>     <!-- 12 horas -->
</active-response>

Elasticsearch / Elastic Stack

1. Index template

Crear un index template para que Elasticsearch mapee correctamente los campos de IP-Flame. Ejecutar en Kibana Dev Tools o via API:

PUT _index_template/ipflame
{
  "index_patterns": ["ipflame-*"],
  "template": {
    "settings": {
      "number_of_replicas": 1
    },
    "mappings": {
      "properties": {
        "ip":             { "type": "ip" },
        "country":        { "type": "keyword" },
        "country_code":   { "type": "keyword" },
        "city":           { "type": "keyword" },
        "isp":            { "type": "keyword" },
        "asn":            { "type": "keyword" },
        "risk_score":     { "type": "integer" },
        "risk_level":     { "type": "keyword" },
        "is_vpn":         { "type": "boolean" },
        "is_tor":         { "type": "boolean" },
        "is_proxy":       { "type": "boolean" },
        "is_datacenter":  { "type": "boolean" },
        "hit_count":      { "type": "integer" },
        "first_seen":     { "type": "keyword" },
        "last_seen":      { "type": "keyword" },
        "top_request":    { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
        "top_user_agent": { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
        "matched_patterns": { "type": "keyword" },
        "cti_source":     { "type": "keyword" },
        "hits": {
          "type": "nested",
          "properties": {
            "timestamp":      { "type": "keyword" },
            "request":        { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
            "status_code":    { "type": "keyword" },
            "user_agent":     { "type": "text" },
            "matched_pattern": { "type": "keyword" }
          }
        }
      }
    }
  }
}

Nota: El campo ip se mapea como tipo ip de Elasticsearch, lo que habilita busquedas por rango CIDR (ej: ip: 172.16.0.0/12).

2. Ingestion con Filebeat

# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /opt/ip-flame/output/report.jsonl
    json.keys_under_root: true
    json.add_error_key: true
    fields:
      event.dataset: ipflame
      event.module: threat_intel
    fields_under_root: true

# Procesadores opcionales: agregar timestamp de ingestion y geopoint
processors:
  - add_host_metadata: ~
  - timestamp:
      field: "first_seen"
      layouts:
        - "02/Jan/2006:15:04:05 -0700"
      ignore_failure: true

output.elasticsearch:
  hosts: ["https://localhost:9200"]
  index: "ipflame-%{+yyyy.MM.dd}"
  # Descomentar si usas autenticacion
  # username: "elastic"
  # password: "changeme"
  # ssl.certificate_authorities: ["/etc/filebeat/ca.crt"]

# Desactivar ILM si se quiere usar el index pattern fijo
setup.ilm.enabled: false
setup.template.name: "ipflame"
setup.template.pattern: "ipflame-*"
# Validar configuracion
sudo filebeat test config
sudo filebeat test output

# Iniciar Filebeat
sudo systemctl enable --now filebeat

3. Ingestion directa con curl (sin Filebeat)

Para entornos simples o pruebas, se puede usar _bulk API:

# Convertir JSONL a bulk format e ingestar
cat output/report.jsonl | while IFS= read -r line; do
  echo '{"index":{"_index":"ipflame-'$(date +%Y.%m.%d)'"}}'
  echo "$line"
done | curl -s -H "Content-Type: application/x-ndjson" \
  -XPOST "http://localhost:9200/_bulk" --data-binary @-

4. Busquedas utiles en Kibana

# Todos los threat actors critical
risk_level: "critical"

# IPs desde Tor
is_tor: true

# Threat actors con mas de 100 hits
hit_count >= 100

# IPs de un rango especifico (gracias al tipo ip)
ip: 172.0.0.0/8

# Threat actors que intentaron acceder a .env
matched_patterns: ".env"

# Combinada: threat actors high+ desde datacenter
risk_level: ("high" OR "critical") AND is_datacenter: true

Splunk

1. Configurar la ingestion

Opcion A — Monitorear archivo JSONL:

# /opt/splunk/etc/system/local/inputs.conf
[monitor:///opt/ip-flame/output/report.jsonl]
disabled = false
sourcetype = ipflame:json
index = threat_intel

Opcion B — Enviar con HTTP Event Collector (HEC):

  1. En Splunk: Settings > Data Inputs > HTTP Event Collector > New Token
  2. Anotar el token generado
  3. Enviar datos desde un script:
cat output/report.jsonl | while IFS= read -r line; do
  curl -s -k "https://splunk:8088/services/collector/event" \
    -H "Authorization: Splunk <HEC_TOKEN>" \
    -d "{\"sourcetype\": \"ipflame:json\", \"index\": \"threat_intel\", \"event\": $line}"
done

2. Definir el sourcetype

# /opt/splunk/etc/system/local/props.conf
[ipflame:json]
INDEXED_EXTRACTIONS = json
KV_MODE = json
TIME_FORMAT = %d/%b/%Y:%H:%M:%S %z
TIME_PREFIX = "first_seen"\s*:\s*"
SHOULD_LINEMERGE = false
LINE_BREAKER = ([\r\n]+)
TRUNCATE = 0
category = Custom
description = IP-Flame CTI Threat Intelligence

3. Busquedas SPL utiles

# Todos los threat actors high y critical
index=threat_intel sourcetype="ipflame:json" (risk_level="high" OR risk_level="critical")
| table ip, risk_score, risk_level, hit_count, country, isp, matched_patterns

# Top 10 threat actors por score
index=threat_intel sourcetype="ipflame:json"
| sort - risk_score
| head 10
| table ip, risk_score, risk_level, hit_count, country, isp

# Threat actors desde Tor o VPN
index=threat_intel sourcetype="ipflame:json" (is_tor=true OR is_vpn=true)
| table ip, risk_score, is_tor, is_vpn, country, hit_count

# Patrones mas frecuentes
index=threat_intel sourcetype="ipflame:json"
| mvexpand matched_patterns
| stats count by matched_patterns
| sort - count

# Mapa geografico de threat actors (requiere campo country_code)
index=threat_intel sourcetype="ipflame:json"
| iplocation ip
| geostats count by risk_level

# Timeline de actividad
index=threat_intel sourcetype="ipflame:json"
| timechart count by risk_level

Webhooks

IP-Flame envia alertas via HTTP POST cuando detecta threat actors. Soporta multiples destinos simultaneos, cada uno con su propio filtro de nivel de riesgo minimo.

Formato de configuracion

webhook=tipo,url[,min_risk_level][,telegram_chat_id]
Parametro Requerido Descripcion
tipo Si slack, telegram, discord, generic
url Si URL completa del webhook
min_risk_level No Nivel minimo para alertar: low, medium (default), high, critical
telegram_chat_id Solo Telegram ID del chat/grupo destino

Solo se envian threat actors cuyo risk_level sea igual o superior al min_risk_level configurado. Si ningun threat actor cumple el filtro, no se envia el webhook.

Slack

  1. Ir a api.slack.com/apps > Crear App > Incoming Webhooks > Activar
  2. Seleccionar el canal destino y copiar la Webhook URL
  3. Agregar a config-ip-flame.txt:
webhook=slack,https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Solo alertar threat actors high y critical:

webhook=slack,https://hooks.slack.com/services/T00/B00/XXX,high

El mensaje en Slack se muestra con emojis por severidad:

🔥 IP-Flame Alert — 3 threat actors detectados

🔴 173.212.230.39 — score:75 (critical) hits:1174 — France Contabo GmbH
🟠 185.177.72.22  — score:50 (high) hits:974 — France Bucklog SARL
🟡 43.207.196.36  — score:40 (medium) hits:312 — Japan Amazon.com

Telegram

  1. Crear un bot con @BotFather y copiar el token
  2. Agregar el bot al grupo o iniciar chat directo
  3. Obtener el chat_id:
    • Para grupos: enviar un mensaje al grupo y consultar https://api.telegram.org/bot<TOKEN>/getUpdates
    • Para chat directo: el chat_id es tu user ID numerico
  4. Agregar a la configuracion (el chat_id va como 4to parametro):
webhook=telegram,https://api.telegram.org/bot123456:ABC-DEF/sendMessage,medium,-100123456789

Discord

  1. En el servidor de Discord: canal destino > Editar Canal > Integraciones > Webhooks
  2. Crear nuevo webhook, nombrar (ej: "IP-Flame"), copiar la URL
  3. Agregar a la configuracion:
webhook=discord,https://discord.com/api/webhooks/123456789012345678/ABCDEFGHIJK...

Solo alertar critical:

webhook=discord,https://discord.com/api/webhooks/123/ABC,critical

Generico (SIEM / custom / n8n)

Para integracion directa con cualquier endpoint que acepte JSON via HTTP POST. IP-Flame envia el payload con header Content-Type: application/json.

webhook=generic,https://my-siem.example.com/api/alerts,medium

Estructura del payload generico:

{
  "tool": "ip-flame",
  "version": "3.2",
  "generated_at": "2026-03-29T20:27:15-03:00",
  "total": 3,
  "threat_actors": [
    {
      "ip": "173.212.230.39",
      "risk_score": 75,
      "risk_level": "critical",
      "hit_count": 1174,
      "country": "France (FR)",
      "asn": "AS51167",
      "isp": "Contabo GmbH",
      "first_seen": "19/Mar/2026:07:45:39 +0000",
      "last_seen": "19/Mar/2026:07:45:47 +0000"
    }
  ]
}

Integracion con n8n

n8n es una plataforma de automatizacion muy utilizada en equipos Blue Team para orquestar workflows de respuesta a incidentes. IP-Flame se integra con n8n usando el tipo generic apuntando a un nodo Webhook de n8n.

1. Crear el workflow en n8n:

  • Agregar un nodo Webhook como trigger
  • Configurar:
    • HTTP Method: POST
    • Path: elegir un path (ej: ipflame-alert)
  • Copiar la Production URL o Test URL que genera n8n (ej: https://n8n.tu-dominio.com/webhook/ipflame-alert)

2. Configurar IP-Flame:

webhook=generic,https://n8n.tu-dominio.com/webhook/ipflame-alert,high

3. Workflow de ejemplo — Triage automatico:

El nodo Webhook de n8n recibe el payload JSON de IP-Flame. A partir de ahi se puede construir un workflow como:

[Webhook: IP-Flame Alert]
    │
    ├─► [IF: risk_level == "critical"]
    │       ├─► [HTTP Request: bloquear IP en firewall/CrowdSec]
    │       ├─► [Slack: notificar canal #incidents]
    │       └─► [TheHive: crear alerta]
    │
    ├─► [IF: risk_level == "high"]
    │       ├─► [Slack: notificar canal #threats]
    │       └─► [Google Sheets / Notion: registrar en tracker]
    │
    └─► [Loop: por cada threat actor]
            └─► [HTTP Request: consultar AbuseIPDB / VirusTotal]
                    └─► [Enriquecer datos y guardar]

4. Acceder a los datos en n8n:

En los nodos posteriores al Webhook, los datos de IP-Flame estan disponibles como:

Expresion n8n Valor
{{ $json.tool }} "ip-flame"
{{ $json.total }} Cantidad de threat actors
{{ $json.threat_actors[0].ip }} IP del primer threat actor
{{ $json.threat_actors[0].risk_score }} Score de riesgo (0-100)
{{ $json.threat_actors[0].risk_level }} "critical", "high", "medium", "low"
{{ $json.threat_actors[0].is_tor }} true / false
{{ $json.threat_actors[0].country }} Pais con codigo ISO

5. Ejemplo con n8n self-hosted en Docker:

Si n8n corre en la misma red Docker que IP-Flame, usar el nombre del servicio como host:

# docker-compose.yml
services:
  ip-flame:
    build: .
    # ...
    depends_on:
      - n8n

  n8n:
    image: n8nio/n8n
    container_name: n8n
    ports:
      - "5678:5678"
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
# En config-ip-flame.txt, usar el nombre del servicio Docker
webhook=generic,http://n8n:5678/webhook/ipflame-alert,high

6. Casos de uso Blue Team con n8n + IP-Flame:

Caso de uso Nodos n8n involucrados
Bloqueo automatico de IPs critical Webhook → IF → HTTP Request (CrowdSec API / iptables)
Alerta multi-canal Webhook → IF por nivel → Slack + Email + Telegram
Enriquecimiento CTI Webhook → Loop → VirusTotal + AbuseIPDB → Merge → DB
Creacion de tickets Webhook → IF → TheHive / Jira / ServiceNow
Reporte diario ejecutivo Schedule Trigger → Read File (report.json) → Summarize → Email
Actualizacion de blocklists Webhook → Code (extraer IPs) → HTTP Request (firewall API)
Correlacion con MISP Webhook → Loop → MISP API (buscar indicadores) → Alerta si match

Multiples webhooks

Se pueden configurar varios webhooks simultaneos, cada uno con su propio filtro de nivel:

# Slack: solo critical (equipo de respuesta inmediata)
webhook=slack,https://hooks.slack.com/services/.../...,critical

# Telegram: high y critical (canal de monitoreo)
webhook=telegram,https://api.telegram.org/bot.../sendMessage,high,-100123456

# n8n: medium+ (workflow de triage automatico)
webhook=generic,https://n8n.internal/webhook/ipflame-alert,medium

# SIEM generico: todos los niveles
webhook=generic,https://siem.internal/api/ipflame,low

Todos los webhooks se envian en cada ejecucion (o tick del modo watch) si hay threat actors que cumplan el filtro.


Integracion con CrowdSec

El archivo threat-actors.txt se genera listo para alimentar CrowdSec:

# Bloquear todas las IPs detectadas por 30 dias
while IFS= read -r ip; do
  [[ "$ip" =~ ^#.*$ || -z "$ip" ]] && continue
  cscli decisions add --ip "$ip" --reason "ip-flame" --duration 720h
done < output/threat-actors.txt

Para automatizar con cron:

# Ejecutar IP-Flame y alimentar CrowdSec cada hora
0 * * * * /opt/ip-flame/ip-flame --config /opt/ip-flame/config.txt && \
  while IFS= read -r ip; do [[ "$ip" =~ ^#.*$ || -z "$ip" ]] && continue; \
  cscli decisions add --ip "$ip" --reason "ip-flame" --duration 720h; \
  done < /opt/ip-flame/output/threat-actors.txt

Risk scoring

Cada IP maliciosa recibe un score de riesgo de 0 a 100 basado en 4 factores:

Factor Puntos max. Criterio
Volumen de hits 25 1 hit = 3pts, 5+ = 10pts, 20+ = 15pts, 50+ = 20pts, 100+ = 25pts
Diversidad de patrones 25 1 patron = 3pts, 2 = 10pts, 3 = 15pts, 5+ = 20pts, 10+ = 25pts
Anonimizacion 30 VPN = 15pts, Proxy = 20pts, Tor = 30pts
API risk score 20 Score de ipquery.io (0-100) escalado a 0-20

Niveles:

Score Nivel Significado
75-100 critical Amenaza activa, multiples vectores, anonimizacion
50-74 high Scanner agresivo o explotacion activa
25-49 medium Reconocimiento o escaneo moderado
0-24 low Actividad aislada, posible ruido

Transparencia de la API

Cuando IP-Flame no puede resolver una IP con las bases GeoLite2 locales, usa la API de ipquery.io como fallback. En este caso:

  • Se registra un log explicito indicando cuantas IPs se envian a la API y por que
  • Los datos enviados son exclusivamente las direcciones IP (no se envian logs, requests ni user-agents)
  • Las respuestas de la API se validan (la IP devuelta debe coincidir con la consultada)
  • El campo cti_source en los reportes indica si los datos provienen de resolucion local o api
time=2026-04-03T13:06:28.500-03:00 level=INFO msg="Enriquecimiento CTI" local=3421 api=258 note="258 IPs enviadas a ipquery.io para enriquecimiento"

Bases de datos GeoIP

IP-Flame usa las bases de datos MaxMind GeoLite2 para resolucion local (sin llamadas a API):

# Descargar GeoLite2 (sin registro requerido)
./update-geoip.sh

Las bases se descargan desde el mirror de P3TERX y se guardan en el directorio geoip/.

Automatizacion con cron (actualizacion semanal):

0 3 * * 1 /opt/ip-flame/update-geoip.sh >> /var/log/ip-flame-geoip.log 2>&1

Si las bases no estan disponibles, IP-Flame usa automaticamente la API de ipquery.io como fallback (free tier ilimitado, batches de hasta 10,000 IPs).


Categorias de deteccion

IP-Flame incluye 238 patrones en 14 categorias, disenados para cubrir el ciclo completo de un ataque web — desde reconocimiento hasta post-explotacion. Los patrones son case-insensitive y se aplica URL decode recursivo (2 niveles) para detectar evasiones con encoding (%2e%2e = .., %252e = double encoding).

Security hardening: Los patrones custom (definidos via offending-lines= en la config) tienen un limite de longitud de 256 caracteres para prevenir ataques ReDoS.

Resumen por categoria

# Categoria Patrones MITRE ATT&CK Descripcion
1 CMS 18 T1190 Explotacion de WordPress, Joomla, Drupal, Magento, phpMyAdmin, Adminer
2 CONFIG 25 T1552.001 Archivos de configuracion, secretos, credenciales y backups expuestos
3 VCS 7 T1213 Repositorios de codigo fuente expuestos (Git, SVN, Mercurial, Bazaar)
4 RCE 22 T1059 Webshells (clasicas + modernas), code injection, path traversal, LFI
5 SQLI 10 T1190 Payloads de SQL Injection: UNION, boolean-based, time-based, exfiltracion
6 XSS 10 T1189 Cross-Site Scripting: script injection, event handlers, cookie theft
7 CMDI 10 T1059.004 Command injection: shell execution, subshell, download & execute
8 LOG4J 5 T1190 Log4Shell (CVE-2021-44228): JNDI injection via LDAP, RMI, DNS
9 SSRF 7 T1552.005 Server-Side Request Forgery: cloud metadata (AWS, GCP, Azure, DO)
10 SCAN 22 T1595 Paneles admin, server status, info disclosure, mail servers
11 CVE 18 T1190 Endpoints de CVEs explotados activamente (Actuator, Ignition, Grafana, etc.)
12 CRAWLER 10 T1593 AI crawlers agresivos y scrapers (GPTBot, ClaudeBot, Bytespider, etc.)
13 PROTO 10 T1190 TLS en HTTP, WebDAV, proxy abuse, Docker socket, etcd
14 TOOLS 18 T1595.002 Fingerprints de herramientas de scanning en User-Agent

Detalle por categoria

CMS — Explotacion de plataformas web (T1190)

Patrones que detectan intentos de acceso a endpoints conocidos de CMS populares. WordPress representa ~43% de la web, lo que lo convierte en el CMS mas atacado.

xmlrpc.php, wp-login.php, wp-admin/, wp-config.php, wp-content/uploads/,
wp-includes/, wp-json/wp/v2/users, wp-json/oembed/, /?author=1, wp-cron.php,
administrator/index.php, /user/login, /downloader/,
/phpmyadmin, /pma/, /phpMyAdmin, /adminer, /dbadmin, /myadmin

CONFIG — Secrets y configuracion expuesta (T1552.001)

Archivos de configuracion que contienen credenciales, tokens API, connection strings. Su exposicion es el vector #1 de compromiso en aplicaciones modernas segun el OWASP Top 10 (A01:2021 Broken Access Control).

.env, .env.local, .env.production, .env.backup, .env.dev, .env.staging,
.env.old, .env.save, .env.bak, /backup, /backups, .sql, .bak, .tar.gz,
.zip, .gz, .rar, config.php, database.yml, settings.py,
docker-compose.yml, docker-compose.override.yml, /.aws/credentials,
/.aws/config, id_rsa, id_ecdsa, id_ed25519, .DS_Store, web.config,
.npmrc, .dockerenv, .bash_history, .mysql_history, .psql_history,
/wp-config.php.bak, /wp-config.php.old, /wp-config.php.save, /config.php.bak

VCS — Repositorios de codigo expuestos (T1213)

El acceso a directorios de control de versiones permite descargar el codigo fuente completo, incluyendo credenciales hardcodeadas y logica de negocio.

.git/config, .git/HEAD, .git/COMMIT_EDITMSG, .gitignore, .git/objects/,
/.svn/entries, /.svn/wc.db, /.hg/, /.bzr/

RCE — Remote Code Execution y Webshells (T1059)

Webshells clasicas (c99, r57) y modernas (Behinder, Godzilla, AntSword), junto con tecnicas de code injection y path traversal para LFI/RFI.

cmd.php, shell.php, c99.php, r57.php, b374k, alfa.php, wso.php,
indoxploit, p0wny, weevely, antsword, behinder, godzilla,
eval(, base64_decode(, assert(, system(, exec(, passthru(, shell_exec(,
../../../, %2e%2e%2f, %2e%2e%5c, /proc/self/environ,
/etc/passwd, /etc/shadow, passwd%00, /cgi-bin/, .cgi, XDEBUG_SESSION,
/vendor/phpunit, /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php

SQLI — SQL Injection (T1190)

Payloads que explotan inyeccion SQL para extraer datos, bypass de autenticacion o ejecucion de comandos via base de datos. Cubre las 3 tecnicas principales: UNION-based, boolean-based y time-based.

UNION SELECT, UNION ALL SELECT, OR 1=1, ' AND ',
information_schema, SLEEP(, BENCHMARK(, WAITFOR DELAY,
/bin/sleep, INTO OUTFILE, INTO DUMPFILE, LOAD_FILE(

Nota: Estos patrones pueden generar falsos positivos en aplicaciones que usan SQL en query strings. Usar whitelist para IPs internas.

XSS — Cross-Site Scripting (T1189)

Payloads que intentan inyectar JavaScript en el contexto del navegador para robo de sesiones, keylogging o redireccion maliciosa.

<script, javascript:, onerror=, onload=, onmouseover=, onfocus=,
alert(, prompt(, confirm(, document.cookie, document.domain

CMDI — Command Injection (T1059.004)

Tecnicas de inyeccion de comandos del sistema operativo a traves de parametros HTTP. Incluye separadores de comandos, subshells y download-and-execute.

;ls, ;cat , |cat , ;id, |id, $IFS, /bin/sh, /bin/bash,
;wget , ;curl , |wget , |curl , $({

LOG4J — Log4Shell / JNDI Injection (T1190)

Payloads del CVE-2021-44228 (Log4Shell), una de las vulnerabilidades mas explotadas de la historia. Detecta la inyeccion JNDI tanto en formato original como URL-encoded.

${jndi:, %24%7bjndi, ${jndi:ldap, ${jndi:rmi, ${jndi:dns

Importancia: Log4Shell sigue siendo explotado activamente. El URL decode recursivo de IP-Flame detecta variantes con double encoding (%2524%257Bjndi).

SSRF — Server-Side Request Forgery y Cloud Metadata (T1552.005)

Intentos de acceder a servicios de metadata de cloud providers para obtener credenciales IAM, tokens de servicio y configuracion interna. Es el vector principal de escalamiento en incidentes cloud.

/latest/meta-data/, /metadata/v1/, /metadata.google.internal,
/metadata/instance, 169.254.169.254, /computeMetadata/v1/, gopher://
Patron Cloud Provider Dato expuesto
/latest/meta-data/ AWS EC2 (IMDSv1) Credenciales IAM, tokens de sesion
/metadata/v1/ DigitalOcean Token de API del droplet
/metadata.google.internal Google Cloud Service account tokens
/metadata/instance Azure Managed identity tokens
169.254.169.254 Todos Link-local metadata endpoint
/computeMetadata/v1/ GCP Metadata con header requerido
gopher:// N/A Protocol smuggling para SSRF

SCAN — Reconocimiento y paneles de administracion (T1595)

Endpoints que revelan informacion del servidor, interfaces de administracion expuestas, y servicios de mail que son target de credential stuffing.

/admin, /login, /console, /manager/html, /host-manager/html,
/jenkins, /solr/, /server-status, /nginx_status, /.htaccess,
/web.config, /elmah.axd, /trace.axd, /Autodiscover/Autodiscover.xml,
/owa/auth/, /boaform/admin, /GponForm/, /cgi-bin/luci,
/mail/, /webmail/, /roundcube, /zimbra

CVE — Vulnerabilidades explotadas activamente (T1190)

Endpoints especificos de CVEs con exploits publicos. Incluye Spring Boot Actuator, Laravel Ignition, Grafana, Kubernetes API y mas.

/actuator/env, /actuator/health, /actuator/mappings, /actuator/beans,
/actuator/, /_ignition/execute-solution, /api/v1/totp/,
/.well-known/openid-configuration, /cgi-bin/%%32%65%%32%65/,
/api/v1/pods, /api/v1/namespaces, /api/v1/secrets, /apis/apps/v1,
/healthz, /portainer, /metrics, /telescope/requests, /horizon/,
/ManagerServlet, /CFIDE/administrator, /ColdFusion/administrator,
/solr/admin/, /spring-security-oauth-problem

CRAWLER — AI Crawlers y Scrapers agresivos (T1593)

User-Agents de bots de IA y scrapers que consumen recursos y extraen contenido sin autorizacion.

GPTBot, ClaudeBot, CCBot, anthropic-ai, Bytespider,
PetalBot, AhrefsBot, SemrushBot, MJ12bot, DotBot

PROTO — Protocol abuse y containers (T1190)

Trafico anomalo a nivel de protocolo: TLS handshakes en puertos HTTP, metodos WebDAV, proxy abuse, y acceso a sockets de containers.

\x16\x03\x01, \x16\x03\x00, \x16\x03\x03, \x80\x4c\x01,
CONNECT , PROPFIND, SEARCH ,
/.well-known/acme-challenge/../, /docker.sock,
/var/run/docker.sock, etcd

TOOLS — Herramientas de scanning en User-Agent (T1595.002)

Fingerprints que identifican herramientas ofensivas en el header User-Agent. La presencia de estas herramientas indica reconocimiento activo o escaneo automatizado.

python-requests, Go-http-client, qqtang, masscan, zgrab, nuclei,
nikto, sqlmap, dirsearch, gobuster, wfuzz, nmap scripting engine,
httpx, ffuf, feroxbuster, katana, subfinder, jaeles, Tsunami,
CensysInspect, Shodan

Dashboards

IP-Flame genera dos dashboards HTML independientes, cada uno para una audiencia distinta. Branding: Sockets AR — Threat Intelligence Dashboard v3.2.

Wall of Shame (flamed-ips.html)

Dashboard operativo para el SOC / Blue Team:

  • Tabla de threat actors ordenada por risk score
  • Filtros interactivos por nivel de riesgo (Critical / High / Medium / Low)
  • Filtro por pais — Dropdown auto-poblado desde los resultados, combinable con el filtro de riesgo
  • Paginacion configurable (25 / 50 / 100 / 250 / Todos)
  • Columna "Host Destino" condicional (solo si log-host-field esta configurado)
  • Detalle expandible por IP con todos los hits, timestamps, status codes coloreados y patrones matcheados
  • Tags de amenaza por IP: TOR, VPN, PROXY, DATACENTER
  • Risk score visual con barra de progreso y nivel

Geo Intelligence (dashboard-geo.html)

Executive summary visual para management y reportes:

  • Mapa interactivo con Leaflet (dark theme CartoDB) — marcadores por pais con tamanio proporcional a hits y color por nivel de riesgo maximo, popups con detalle
  • KPI cards — threat actors, hits, paises, hosts atacados, patrones detectados
  • Distribucion de riesgo — donut chart (CSS puro, sin dependencias)
  • Top paises atacantes — barras horizontales con cantidad de IPs y hits
  • Top patrones detectados — barras con hits por patron
  • Top hosts atacados — barras (condicional, solo con log-host-field)
  • Top ISPs atacantes — barras con cantidad de IPs por ISP
  • Indicadores de amenaza — conteo de threat actors TOR, VPN, Proxy, Datacenter

Dependencias del Geo dashboard: Leaflet 1.9 (~40KB, CDN), Tailwind CSS (CDN), CartoDB dark tiles (OpenStreetMap). No requiere API keys ni backend.


Licencia

Desarrollado por Hernan Herrera — Sockets AR.

About

Threat Intelligence scanner for Blue Teams — Detects 238 malicious patterns across 14 categories in web server logs, enriches IPs with GeoIP/ASN/VPN/Tor data, calculates risk scores (0-100), and generates interactive HTML dashboards + JSON/JSONL for SIEM integration.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors