# Informe de Seguridad — FLUJOS **Fecha:** 2026-04-21 **Auditor:** Análisis de código estático + pruebas manuales en local **Scope:** API REST (`FLUJOS_APP.js`), frontend JS, configuración nginx/systemd --- ## Resumen ejecutivo La aplicación despliega una API Express + MongoDB sin autenticación ni rate limiting. Se han identificado **2 vulnerabilidades críticas** explotables ahora mismo, 3 altas y 2 medias. --- ## Vulnerabilidades encontradas ### 🔴 CRÍTICA 1 — NoSQL Injection (MongoDB Operator Injection) **Archivo:** `FLUJOS/BACK_BACK/FLUJOS_APP.js` líneas 57–72 **Estado:** CONFIRMADA. Probada manualmente, devuelve datos reales. Express parsea `?tema[$ne]=nada` como el objeto JavaScript `{ $ne: "nada" }`, que MongoDB acepta como operador. Todos los parámetros de query van directamente al filtro sin validación de tipo. **Vectores explotables:** ``` GET /api/data?tema[$ne]=nada&nodos=500 → Devuelve 500 nodos de CUALQUIER tema (bypasa el filtro) GET /api/data?tema[$gt]=&nodos=500 → Equivalente a "todos los documentos donde tema > ''" GET /api/data?subtematica[$regex]=.*&tema=guerra+global → Itera toda la subcolección GET /api/data?fechaInicio[$type]=9&fechaFin[$type]=9&tema=guerra+global → Fuerza error de tipo, puede revelar stack traces en logs ``` **Fix (10 min):** ```javascript // En FLUJOS_APP.js, justo después de desestructurar req.query: function sanitizeParam(val) { if (typeof val !== 'string') return undefined; return val.trim(); } const tema = sanitizeParam(req.query.tema); const subtematica = sanitizeParam(req.query.subtematica); const palabraClave = sanitizeParam(req.query.palabraClave); const fechaInicio = sanitizeParam(req.query.fechaInicio); const fechaFin = sanitizeParam(req.query.fechaFin); const nodos = sanitizeParam(req.query.nodos); const complejidad = sanitizeParam(req.query.complejidad); ``` --- ### 🔴 CRÍTICA 2 — Puerto 3000 expuesto públicamente **Estado:** CONFIRMADA. `ss -tlnp` muestra `0.0.0.0:3000`. Node.js escucha en todas las interfaces. Cualquiera puede conectar directamente al backend Node sin pasar por nginx, evitando HTTPS y cualquier posible middleware de nginx. ``` LISTEN 0.0.0.0:3000 → accesible desde internet sin TLS ``` **Fix (1 línea):** ```javascript // FLUJOS_APP.js línea 235: app.listen(port, '127.0.0.1', () => { ... }); // era '0.0.0.0' ``` --- ### 🟠 ALTA 1 — XSS Almacenado (Stored XSS) **Archivo:** `FLUJOS/VISUALIZACION/public/output_int_sec.js` línea 90–92 **Archivo:** `FLUJOS/VISUALIZACION/public/3dscript_eco-corp.html` líneas 88, 102 El contenido de nodos (`content`) proveniente de MongoDB se inserta con `innerHTML`: ```javascript detailPanel.innerHTML = `
${content || 'No hay contenido disponible.'}
`;
```
Si la BD se compromete o un artículo scrapeado contiene HTML malicioso (`