Me hice mi propio visor de logs con IA local que al loro carga logs, agrupa errores, importa desde Splunk y un LLM local me diagnostica el ataque en un clic solo con una GPU de 16GB y mucha curiosidad.

Soy analista de seguridad sin experiencia laboral como analista pero en Helpdesk llevo más de 5 años

Aquí me construyo mi propia herramienta para no hacerlo más a mano con un Notepad ++ y aunque uso Klogg para cargas de logs muy grandes me apetecía hacer una herramienta “inteligente” que si pudiera integrar LLM

Un SOC empresarial te da un SIEM de millones de euros que automatiza eso.

Me puse a construir yo mismo la herramienta que me ahorre ese trabajo, con IA local que no envía un solo dato a la nube y puedes consultar logs complejos como los de Zscaler o los logs de las consultas SPL en Splunk.

0x00 Introducción

Cuando pasas tardes aprendiendo a filtrar logs, mirando contexto, agrupando errores, decidiendo si algo es un incidente, lo suyo en un trabajo real es filtrar con rapidez.

Casi siempre estas ideas surgen de una necesidad.

¿Puedo automatizar la parte mecánica del triage y dejar que un LLM local me dé las pistas, sin depender de un SIEM caro?

Si y No…pipeline no existe como tal y no hay grandes integraciones pero…

0x01 La Herramienta

Vista general del visor de logs

Es una aplicación web que corre en local construida solo con Python estándar y JavaScript, sin un céntimo de gasto con IA local.

  • Sube logs de muchos formatos como Apache, Zscaler, Windows, JSON) y los admite comprimidos (.gz, .bz2, .xz, .zip).
  • Filtra por IP, ruta, texto, nivel, código y rango de fechas.
  • Agrupa errores en vez de cientos de líneas “ERR” iguales, muestra las plantillas únicas con su recuento.
  • Muestra contexto clic en una línea y ves las anteriores y posteriores del archivo original.
  • Tail en vivo para exportar CSV/JSON, presets de filtros, modo presentación.
  • Aguanta millones de líneas: usa SQLite como backend cuando el dataset es grande, sin quedarse sin memoria aunque la máxima carga es de 500MB

Filtrado en acción

Agrupación de errores por plantillas únicas

Esto ya existe en cualquier SIEM, pero aquí está en mi casa es gratis.

0x02 Diagnóstico rápido: la IA entra en juego

Botón Diagnóstico rápido

Un log de miles de líneas puede tener 200 errores distintos.

Leerlos uno a uno no es viable.

Aquí se observa como el server llama.cpp empieza con el encoding

Server llama.cpp arrancando con el encoding

Aquí es donde el LLM local marca la diferencia y da las instrucciones y la información de la que dispone que bebe de un RAG alimentado en este caso con la documentación oficial de Zscaler como solución EDGE/SASE en mi PC

RAG alimentado con la documentación oficial de Zscaler

Con el botón Diagnóstico rápido

  • El visor agrupa los errores en plantillas únicas
  • Envía eso al LLM local (Qwen 3.8 27B en mi propia GPU).
  • El modelo razona y devuelve una conclusión accionable con las plantillas más frecuentes y su línea de ejemplo.
**Próximos pasos concretos:**

1. **Verificar servicios:** `sc query ZscalerClient` / `sc query ZSAUpm` / `sc query ZSAZdp`. Si aparecen como "no found", la instalación está rota.
2. **Reparar/reinstalar como Administrador (elevado):**
   - Descarga el último `ZscalerClient.msi` del portal admin.zscaler.com.
   - Ejecuta: `msiexec /i ZscalerClient.msi REINSTALL=ALL RECONFIGURE=1 /qn` **o** usa el flag `/reinstall`.
   - Alternativa rápida: `ZscalerClient.exe /repair` desde `C:\Program Files\Zscaler Client\`.
3. **Limpiar restos antes de reinstalar:**
   - Borra `HKLM\SOFTWARE\Zscaler Inc.` y `HKLM\SOFTWARE\Zscaler` (cuidado: solo si el paso 2 falla).
   - Elimina carpeta `C:\Program Files\Zscaler Client\` y `C:\ProgramData\Zscaler\`.
4. **Comprobar políticas GPO / MDM:** Si el endpoint está en dominio, verifica que no haya una política de Zscaler (config push) que esté forzando un estado de "revert" → explica el log `[isValidRevertZccCall] Unexpected call received`.
5. **Exclusión EDR/AV:** Asegúrate de que tu endpoint protection no bloquee escritura en `HKLM\SOFTWARE\Zscaler` ni creación de servicios (los errores 0x426 y "Failed to set permissions" lo sugieren).
6. **Post-reparación:** Revisa `ZscalerClient.log` tras reiniciar; los errores `0x00000002` deben desaparecer y el servicio debe arrancar en estado RUNNING.

> **TL;DR:** El agente Zscaler quedó huérfano (registro + servicios + config ausente). Un `reinstall` limpio con permisos de administrador resuelve el 95 % de los casos; si persiste, auditar GPO y EDR.

Te cita la plantilla más crítica con su línea de ejemplo exacta y posibles soluciones que no anulan la capacidad analítica que es al final quien decide si es grave se puede solucionar por algún soporte EDGE/SASE o se presentan riesgos de seguridad.

0x03 Analizar línea a línea

Sección Analizar en el drawer de una línea

Además del diagnóstico global, al abrir una línea concreta hay un botón de Analizar que envía solo esa línea al LLM local

El LLM explica qué es, la causa probable y pasos de solución.

Modal de análisis de la línea

Puedo elegir el idioma (español, inglés o “auto”).

Y van en caché, así que repetir la misma pregunta es instantáneo.

0x04 Conectando con Splunk

Sección Importar de Splunk

Mi visor también importa directamente desde Splunk con solo pegarle una query SPL y te devueve el resultado como un dataset más listo para trabajar.

En este caso con una consulta sencilla de buscar todos los eventos de un índice

index=botsv3 earliest=0

Cabe recalcar que el SPL es quien filtra y agrega y el visor solo trae lo que pides así nunca se satura la GPU ni el modelo.

En este caso eligiendo una línea cualquiera encontramos la información

Resultado del dataset importado desde Splunk

Es filosofía de menos datos pero más significado y así eres más ágil en las consultas.

0x05 El ataque

Para demostrarlo, voy a por un ataque password spray que no es más que una misma IP probando contraseñas contra muchas cuentas, para no activar el bloqueo por intentos de una sola.

Pego la query contra el índice de Azure AD de BOTSv3

search index=botsv3 sourcetype="ms:aad:signin" | spath
| where loginStatus!="Success" AND failureReason!="null"
| stats count by userPrincipalName, ipAddress, failureReason
| sort - count | head 10

Tabla de fallos de login por IP y usuario

Un detalle técnico que es importante es que en ms:aad:signin los datos (userPrincipalName, ipAddress, failureReason) van dentro del campo _raw como JSON, no como campos top-level.

Sin | spath, la query devuelve 0 filas y no entiendes por qué.

Línea de fallo de login con síntesis del LLM

En este caso cogemos una línea que hay un fallo de login y si no sé de que se trata el LLM me hará una síntesis para poder empezar a investigar.

En el ejemplo señala a fyodor@froth.ly (16 intentos) y klagerfield (8 intentos) desde la misma IP 199.66.91.253, distinguiendo entre cuenta deshabilitada (ruido) y Invalid username or password (fuerza bruta).

Informe del LLM sobre la línea señalada

Eso es pulverización de contraseña una sola IP probando contra varias cuentas. Un analista novato habría tardado horas en ver el patrón en la tabla cruda. Yo lo vi en un clic, sin mandar un dato a la nube.

Aquí arroja el LLM su informe de la línea señalada

## Análisis del log

**Qué pasa:** 8 intentos fallidos de autenticación para la cuenta `pcerf@froth.ly` desde la IP **51.38.191.81** (Hetzner Cloud, DE). El motivo es credenciales inválidas (usuario o contraseña incorrectos), tanto en el flujo cloud como on-premises.

**Causa probable:**
- **Ataque de fuerza bruta / credential stuffing** automatizado desde un VPS/contenedor (la IP es un rango de Hetzner, típico de scripts).
- Alternativa menos probable: el usuario está tecleando mal sus credenciales en un entorno con redirección a on-prem (AD FS / hybrid), pero 8 fallos seguidos apunta a automatización.

**Pasos de solución concretos:**

1. **Bloquear/limitar la IP**
   - En Azure AD → *Protection* → *Named locations*, crea una política que bloquee o exija MFA para `51.38.191.81`.
   - Si usas firewall (Azure Front Door, NSG, o WAF), bloquea esa IP directamente.

2. **Revisar el usuario afectado**
   - Entra ID → *Sign-in logs* → filtra por `pcerf@froth.ly`: confirma si hay éxitos posteriores o solo fallos.
   - Si no hubo acceso legítimo, fuerza reset de contraseña y revisa tokens/sesiones activas (`Azure AD` → *Devices* / *My apps* → revocar sesiones).

3. **Endurecer la autenticación**
   - Exige **MFA condicional** para accesos desde IPs no corporativas o ubicaciones nuevas.
   - Configura **Smart Lockout** (política de bloqueo tras N fallos) en Azure AD / on-prem AD: p. ej., 5 fallos → lockout 15 min.

4. **Monitorizar y alertar**
   - Crea una alerta (Azure Monitor / Sentinel) para `failureReason` con `count ≥ 5` en 10 min desde la misma IP.
   - Revisa el resto de logs: si otras cuentas también fallan desde esa IP, es un ataque distribuido → considera bloquear el rango completo del proveedor.

5. **Si es on-prem (hybrid)**
   - Verifica que AD FS / ADFS no esté expuesto directamente a Internet sin MFA; usa proxy con rate-limiting.
   - Revisa `Event ID 4771/4776` en el DC para confirmar si los intentos llegan al dominio local.

> **Resumen:** Con alta probabilidad es un bot haciendo fuerza bruta desde un VPS de Hetzner. Bloquea la IP, exige MFA y activa lockout; si no hay negocio real en esa IP, ignora tras el bloqueo.

0x06 Human in the loop

La IA no decide pero me da pistas y yo aplico mi criterio.

El LLM local es el mentor pero soy quien valida, quien decide si una IP es un atacante o un falso positivo o quien escala.

La herramienta acelera si…pero el criterio sigue siendo humano.

Esto es el Human In The Loop y en este caso sirve para hacer mas rápido el descarte

0x08 Conclusión

Hoy en día no necesitas un SIEM de millones de euros al menos para practicar en el entorno ya que con:

  • Una RTX 5060 Ti de 16GB y un LLM local (Qwen 3.8 27B variante M o XL)
  • Python y Splunk con licencia de desarrollador
  • El dataset público BOTSv3
  • Obsidian como cerebro llkamacpp como orquestador backend
  • Y muchas ganas de aprender y de trabajar

El cloud ayuda (modelos más potentes, más contexto) pero para trabajar con los logs de tu propio entorno, el LLM local basta y además es privado asi que nada sale de la máquina.

Lecciones

  • El clustering + LLM local convierte miles líneas en un diagnóstico de minutos
  • No hace falta enviar tus logs a la nubela
  • Un analista novato con una herramienta propia vale más que uno sin herramientas
  • La velocidad del triage es el superpoder del SOC
  • La IA no sustituye tu criterio: te da pistas (Human in the Loop)

El stack completo

  • Python (visor de logs unificado) + JavaScript
  • Splunk + dataset BOTSv3
  • Qwen 3.8 27B en GPU local (RTX 5060 Ti 16GB)
  • Obsidian Vault como cerebro (playbooks, RAG)
  • llama.cpp

Para esto hace falta mucha curiosidad, ganas de aprender y de trabajar. La titulitis no sirve de nada si no eres capaz de abrir un terminal y construir algo, aunque sea con IA

La IA ha venido a quedarse y usarla en tu beneficio no te hace menos, te hace más rápido.

Y saber implementarla en local, siendo dueño de tus datos, es ORO.