Volver a la wiki

Auditoría Suprema 2 · Cola monitoring A: sondas, validación de targets y evasión SSRF

Cuándo

04-09-2026 · commit 98ddfd3a (PR #496, v1.104.0). Tercer dominio de la cola MEDIA/BAJA de la Auditoría Suprema 2 (task #286) — primer PR de tres para monitoring (bloque A: sondas y targets; quedan B —CNS e insights— y C —ITSM y notificaciones—). Implementación en Sonnet con las decisiones fijadas de antemano; revisión de Fable 5.1 con dos correcciones: SNMP v1 no existe ni en el SaaS ni en el Agente y no debía aceptarse al validar, y un presupuesto de sonda agotado antes del primer intento debía dar un error de presupuesto explícito, no el “no validated IPs” que sugiere otra causa.

Síntomas visibles

Doce hallazgos MEDIA en el mismo commit:

  1. PUT /targets/{id} devolvía 500 genérico (no 400) al desmarcar las 4 sondas de un target — el código no estaba declarado en el response de ninja.
  2. El ajuste “Smoothing” de Chart Defaults se guardaba pero no tenía efecto: _get_smoothing_level leía una clave de Valkey que nadie escribe desde la migración a ui_prefs.
  3. hours sin acotar producía 500 (nan/inf) en /vm/ping y /vm/stats, y un valor como 1e9 llegaba tal cual a VictoriaMetrics.
  4. Las claves de OID (snmp_extras_*, snmp_fast_*, VendorProfile.monitoring_oids) no se validaban contra el patrón del ingest — una clave con mayúsculas o : producía una métrica que no nacía nunca, y el alta de perfil de fabricante no tenía ninguna validación.
  5. El ping y el chequeo HTTP manuales pisaban la semántica de last_status: un equipo con ICMP bloqueado pero sonda TCP viva se marcaba down, y un 500 de la web marcaba el equipo entero como caído.
  6. El techo de 30s del SNMP síncrono era inerte en el camino asyncio.run (el que usan las vistas síncronas bajo daphne) — solo aplicaba en la rama async.
  7. El timeout_ms configurado en el target nunca llegaba al SNMP: from_config leía una clave de config que nadie escribe, y en la práctica siempre se usaban 5s fijos.
  8. Observatory y Wireless compartían la misma clave de sweep en deep_discover_job_key; lanzar un barrido mientras corría el otro devolvía already_running con el total ajeno.
  9. El comando de servidor ping_targets sondaba IPs privadas (terreno del Agente, no del servidor) y persistía resultados Blocked destination del guard como si fuesen una medida real.
  10. La sonda HTTP no tenía presupuesto agregado: un dominio con 8 registros A caídos podía consumir ~80s de un hilo síncrono, y try_each_ip reintentaba ante CUALQUIER excepción, no solo fallos de conexión.
  11. El config del target (http_method, http_headers, http_expected_codes, snmp_port, snmp_interface, snmp_version, timeout_ms) no validaba sus claves conocidas — valores inválidos salían a la red sin comprobar.
  12. Batería de evasión SSRF incompleta en net_guard: 198.18.0.0/15 (benchmarking), 224.0.0.0/4 (multicast) y localhost. (forma FQDN con punto final) se colaban por no estar en las listas de rangos/hosts bloqueados.

Causa raíz

No hay un patrón único — es la cola de una auditoría grande, agrupable en:

Fix aplicado

Commit 98ddfd3a (PR #496):

Lecciones

Preventivos futuros

Véase también

Subir