Volver a la wiki

Auditoría Suprema · Monitoring sub-área 2 (protocolos/probes SNMP·ping·HTTP) — fixes s107

Contexto

Quinta tanda de la Auditoría Suprema (ver [[concept—onboarding—mapa-maestro-ecosistema-crearack]]) y segunda sub-área de monitoring (tras [[feature—monitoring—auditoria-sa1-s106]]). Cubre los probes / protocolos: los servicios que sondean la red desde el servidor — SNMP, ping ICMP, HTTP — más la correlación/agrupación de resultados (~1.3k LOC en 6 ficheros).

Resultado: 39 crudos → 37 dedup → 36 confirmados (4 ALTA / 17 MEDIA / 15 BAJA), 1 rechazado por verificación adversarial. 67 agentes, 3.73M tokens. Datos: auditoria-suprema/monitoring-sa2.{md,json}. PR #64→#65 (merge cd274098, CI verde, sin migraciones).

Decisión de Edu: “todo de una vez” (Regla 22, patrón [[feature—blueprints—auditoria-s105]] + sa1).

El hallazgo estrella: SSRF en los probes HTTP (ALTA)

HttpService.check / check_async / _check_ssl_cert conectaban a la URL recibida sin validar el destino. El endpoint /targets/{id}/http/check (operations.py) comprobaba is_private_ip(target.ip_address) pero después probaba config["http_url"] — un campo distinto, controlado por el usuario. Vector: target con ip_address público (pasa el guard) + http_url=http://169.254.169.254/latest/meta-data/ (metadata cloud), http://127.0.0.1:8428/ (VictoriaMetrics), o servicios internos por hostname Docker (http://cache:6379/, http://db:5432/). batch.py ni siquiera tenía el guard parcial. follow_redirects=True permitía además SSRF vía 302 a destino interno.

Modelo de amenaza confirmado: los probes server-side son para targets públicos — los dispositivos privados del cliente se monitorizan vía el Local Agent, no desde el servidor (de ahí que ping/HTTP/SNMP-poll ya saltaran is_private_ip). Por tanto un probe server-side hacia RFC1918/loopback/link-local es SSRF contra la propia infra, no monitoreo legítimo.

Fix — nuevo guard SSRF compartido monitoring/services/net_guard.py:

El proyecto ya tenía un guard equivalente para webhooks ITSM (notification_service.validate_webhook_url); net_guard lo generaliza para los probes (unificar ambos queda como carve-out de sub-área 4).

Resto de ALTA

  1. Endpoints SNMP sin gate — snmp/test, snmp/interfaces, snmp/poll (monitoring/api/snmp.py) no aplicaban require_perm → cualquier autenticado (incl. readonly) disparaba SNMP. Añadido require_perm(request, "observatory", "edit") a los 3. (Misma raíz Broken Access Control que sa1/blueprints; helper de s105.)
  2. Escaneo SNMP de red interna — snmp/test y snmp/interfaces no tenían el guard is_private_ip que sí tiene snmp/poll → permitían sondear IPs internas arbitrarias. Añadido (mismo criterio: privados vía Agent).
  3. Inyección PromQL en grupos — group_service.query_group_metric interpolaba metric en el nombre de métrica (snmp_extras_<metric>) y tenant_id/target_ids en los selectores de la query VM sin sanear → lectura cross-tenant (misma clase que el fix de sa1 en metrics_reader, en otro fichero). Validados contra allowlist _VALID_METRIC_NAME + numéricos; entrada inválida → {"data": []} + log.

Fixes correctness / fuga de info

Tests

15 nuevos en tests/api/test_monitoring.py: gate de permisos en los 3 probes SNMP (readonly→403, admin→skip private sin red), guard SSRF (net_guard + http_service.check bloquea metadata/loopback/RFC1918/esquema y permite IP pública), inyección PromQL en query_group_metric. 253 verde en tests/api/ (1 skip preexistente). Sin migraciones. ruff limpio.

Backlog Etapa 3 (carve-outs Regla 22)

Relacionado

Véase también

Subir