Volver a la wiki

Auditoría Suprema 2 · Tanda 9: SSRF por IPv6 mapeada, XSS almacenado en stencils y borde anónimo de signage

Cuándo

01-09-2026 · commit 024052ce (PR #488, v1.100.0). Novena tanda de la Auditoría Suprema 2: no nace de un dominio nuevo del plan de arreglos, sino del triage de la cola de hallazgos (sesión 298), que destapó 2 ALTA que ningún agrupamiento temático de las Tandas 1-8 había recogido — quedaron huérfanos entre “core”, “racks” y “monitoring” hasta que alguien revisó la cola entera.

Síntomas visibles

Cinco hallazgos distintos en el mismo commit:

  1. SSRF por IPv6 mapeada (monitoring/services/net_guard.py): las direcciones ::ffff:127.0.0.1 y ::ffff:169.254.169.254 — la forma IPv6 “mapeada” de un loopback o de la IP de metadata de la nube — conectan exactamente al mismo destino que sus equivalentes IPv4, que sí estaban bloqueados. Pero _ip_blocked comparaba el objeto ipaddress contra una lista de redes por versión, y una IPv6 nunca cae dentro de una red IPv4: el filtro las dejaba pasar sin más.
  2. XSS almacenado por la librería de stencils (racks/api/library.py, core/views.py): create_from_image y create_custom_stencil guardaban cualquier fichero subido sin exigir ningún permiso (un usuario de solo lectura podía subir), sin validar el tipo ni sanear el contenido, y el resultado se servía same-origin por /media/. Un .svg o .html con <script> se ejecutaba en el origen de la app en cuanto alguien navegaba a esa URL.
  3. Borde anónimo del portal de signage (signage/views.py): el PIN de un proyecto de cliente solo protegía la vista de lectura (client_portal_view); los tres POST de acción (client_upload, client_create_playlist, client_publish) aceptaban solo el token —que viaja en la URL y por tanto en proxies, historial y cabecera Referer— sin comprobar el PIN. client_publish, además, no exigía el permiso schedule que sí calculaba la vista de lectura.
  4. Gates de core incompletos: /api/search enumeraba racks, equipos y blueprints sin comprobar el scope de lectura de quien preguntaba; la suspensión de una organización se comprobaba DESPUÉS de la lista de exenciones de ModuleGatingMiddleware (que incluye /api/users, /api/credentials, /api/export, /api/admin, /api/agent), así que un tenant suspendido conservaba gestión de usuarios, credenciales y export; /api/help/article servía cualquier ruta del workspace validando solo .., filtrando por whitelist únicamente en el LISTADO, no en la lectura directa — un autenticado podía leer doc técnica/interna (ADRs, concept--/decision--/incident--) vía el proxy de ayuda; y help_ask/help_ask_stream (Gemma de pago) no tenían ningún tope de coste por organización.
  5. Dos XSS de frontend menores (import Visio, walk SNMP) sin escapar en el editor.

Causa raíz

Ningún patrón único explica las cinco — es la cola de una auditoría grande, con hallazgos de forma distinta:

Fix aplicado

Commit 024052ce7db543e6ff35eb6b1a3e7659061a1c2e (PR #488):

Lecciones

Preventivos futuros

Véase también

Subir