Reporte Integral de Seguridad

🛡️ Sentinel by Rocket Launch Rocket Launch

Fecha: 22 de marzo de 2026
Tipo: Pentest de Caja Negra Básico

Proyecto: Olivia (olivia.net.co)

⚠️ Aviso Legal: Esta auditoría fue realizada por Sentinel by Rocket Launch en un entorno de prueba cerrado. El único punto de entrada utilizado fue la URL pública olivia.net.co, rastreada a través de Google. No se accedió a código fuente, bases de datos internas ni credenciales válidas durante las pruebas.

📄 Descargo de Responsabilidad

El presente informe tiene carácter estrictamente informativo, preventivo y con fines de remediación. Su propósito es identificar vulnerabilidades de seguridad para que el equipo responsable pueda implementar las correcciones necesarias y fortalecer la postura de seguridad de la plataforma.

Este documento no constituye una herramienta para la explotación maliciosa de las vulnerabilidades descritas. La información aquí contenida fue recopilada de buena fe y en un entorno de prueba controlado, con el único objetivo de proteger a los usuarios finales y garantizar el cumplimiento de las normativas colombianas de protección de datos.

Sentinel by Rocket Launch no se hace responsable del uso indebido de la información contenida en este informe por parte de terceros no autorizados. La distribución de este documento debe limitarse exclusivamente al personal autorizado del proyecto.

📊 Panel Ejecutivo

14
Vulnerabilidades
5.2
Score /10
60+
Tests Ejecutados
12
Fases de Auditoría
2 Críticas
7 Altas
5 Medias

📋 Tabla de Contenido

1. Arquitectura Descubierta y Mapeo

El escaneo y análisis reveló una arquitectura de microservicios multi-tenant (identificado vía Header x-tenant-id) para gestionar información de salud altamente sensible (PHR/EHR).

🖥️ Frontend (SPA)
Angular
olivia.net.co
🌐 Reverse Proxy
Nginx 1.24.0 (Ubuntu)
Front-facing server
🔐 Backend Auth
Express.js
/auth/api/v1
👥 Backend Personas
Express.js
/people/api/v1
📅 Backend Citas
Express.js
/appointments/api/v1
⚙️ Backend Común
Express.js
/common/api/v1

2. Mapa Completo de Endpoints Descubiertos

El siguiente mapa de rutas fue extraído sin estar autenticado gracias a la exposición del código del Frontend (VULN-01).

🔑 Autenticación

  • POST /auth/api/v1/auth/login
  • /auth/api/v1/auth/refresh
  • /otp (Posible 2FA)

👥 Personas y Pacientes

  • /people/api/v1/patients
  • /people/api/v1/professionals
  • /dashboard/management/people

📅 Citas Médicas

  • /appointments/api/v1
  • /appointments/api/v1/people-documents
  • /appointments/exams & medicamentos

⚙️ Configuración y Catálogos

  • /common/api/v1/blood-types, genders, occupations
  • /common/api/v1/health-insurances
  • /common/api/v1/civil-statuses, diagnostics
  • /common/api/v1/medical-exams, population-types

🛠️ Administración & Sistema

  • /dashboard/admin/configuration/*
  • /dashboard/security/roles y permissions
  • /dashboard/security/modules
  • GET /health (⚠️ Sin autenticar)
  • /logs & /notifications

3. Vulnerabilidades Críticas de Alto Impacto

VULN-01: Exposición Completa del Stack y Endpoints Sensibles en Bundle JS ALTA

CVSS: 6.5
Vector: Bundle Frontend

El archivo main.c05970775482fc41.js (13.7 MB, sin ofuscación) expone todas las rutas del API, la estructura de roles del sistema, los roles estáticos (admin, professional, auditor, asistente, paciente, centro-referencia, centro-remisor), módulos ocultos de seguridad (/security/roles), URLs dinámicas de videollamadas, y secciones de auditoría interna (/audit/medical-records). Un atacante puede crear un mapa pasivo total sin necesidad de autenticarse.

Recomendación de Remediación

Implementar lazy loading en Angular para los módulos de administración (que el código solo se cargue si el usuario tiene el rol). Usar tree shaking y ofuscación agresiva del bundle de producción.

VULN-02: Rate Limiting Inadecuado (Credential Stuffing / Fuerza Bruta) ALTA

CVSS: 7.5
Endpoint: POST /auth/api/v1/auth/login

El límite de peticiones (Rate Limit) de 1000 intentos por ventana de tiempo sin bloqueos o expulsiones (lockout) de cuenta ni validación CAPTCHA expone gravemente el sistema a ataques de fuerza bruta automatizada.

Evidencia empírica capturada en consola (brute.js): x-ratelimit-limit: 1000
x-ratelimit-remaining: 962 (tras varias peticiones)
[*] Iniciando fuerza bruta: 208 combinaciones...
// El servidor procesó las 208 peticiones en ~1 segundo sin retornar un HTTP 429 (Too Many Requests).

Recomendación de Remediación

1. Bajar el límite a 5-10 intentos por IP (15 minutos).
2. Implementar bloqueo progresivo de la cuenta tras 5 fallos.
3. Integrar Google reCAPTCHA v3 invisible para discriminar bots de legítimos.
4. Cargar alertas al usuario admin sobre actividad inusual de intentos.

VULN-03: Almacenamiento Inseguro del JWT y Riesgo Grave de XSS ALTA

CVSS: 7.1
Vector: Local Storage / JS DOM

La autenticación se gestiona retornando el token JWT en el payload JSON. El frontend Angular lo guarda en LocalStorage o memoria de sesión. Al faltar políticas CSP (ver VULN-04), si la plataforma llega a tener una mínima vulnerabilidad de Cross-Site Scripting (XSS), un atacante o script parásito puede robar el JWT y apropiarse de la sesión del paciente o médico limpiamente.

Recomendación de Remediación

Migrar a un esquema basado en Cookies de Sesión (HttpOnly, Secure, SameSite=Strict/Lax). De esta manera, JavaScript del navegador nunca puede acceder al valor del Token criptográfico.

4. Vulnerabilidades de Severidad Media y Postura General

VULN-04: Ausencia de Políticas de Seguridad Base (HSTS, CSP) MEDIA

CVSS: 5.4

El dominio no envía la cabecera Content-Security-Policy (CSP) (lo que permite inyección de scripts ajenos exacerbando el riesgo de la VULN-03) ni la de Strict-Transport-Security (HSTS). Un atacante en red local (ej: WiFi pública) podría hacer "SSL Stripping" e interceptar las credenciales en texto claro sin que el navegador bloquee la conexión HTTP.

VULN-05: Exposición de Headers y "Dev Mode" Activado MEDIA

CVSS: 5.3

Se emiten headers sensibles en todas las respuestas: X-Powered-By: Express y Server: nginx/1.24.0 (Ubuntu). Adicionalmente, se verificó mediante trazas en consola de desarrollador que Angular está compilado/ejecutándose en modo de desarrollo. Esto facilita enumeración de la infraestructura para exploits públicos.

VULN-06: Endpoint /health expuesto al público MEDIA

CVSS: 4.3

GET https://api.olivia.net.co/health responde exitosamente ({"status":"OK"}) sin Token REST. Aunque no muestra PII (Información de Identificación Personal), permite perfilamiento automatizado continuo de latencia o disponibilidad de los clusters para la preparación de ataques.

VULN-07: Crash del Servidor por Null Byte Injection (HTTP 500) MEDIA / DOS

CVSS: 5.5

Al auditar los parsers del backend enviando payloads tipo "username": "admin\u0000" (inyección de bytes nulos/tabuladores), la API colapsó internamente devolviendo un error HTTP 500 Internal Server Error en lugar de atrapar la anomalía con un 400 Bad Request o 401. Esto expone fragilidad en las validaciones de Prisma/Node.js, posibilitando una degradación de servicio o encubrimiento de inyecciones posteriores si el WAF solo sanitiza strings normales.

Recomendación de Remediación

Implementar librerías de validación rigurosas (como Zod, Joi o class-validator) en los DTOs de entrada de Express que desechen strings con secuencias de control no imprimibles antes de tocar la base de datos o el ORM.

5. Resultados de Pruebas en Vivo (Fases 2-4)

Se ejecutó el script fase2_pentest.sh el cual automatizó escenarios de OWASP API Security Top 10. Los resultados demostraron una postura robusta a nivel de código de backend:

BOLA / IDOR Autenticado Bloqueado Intentos de lectura (/appointments/.../1) usando un JWT falso pero estructuralmente válido fueron truncados (HTTP 401). El backend valida la firma criptográfica estrictamente y no solo el formato del Token.
Mass Assignment (Roles inyectados) Resistente Al inyectar el campo oculto "role":"superadmin" en el login, la API ignoró el intento de tampering y lo rechazó limpiamente (HTTP 401).
BFLA (Acceso a Rutas Administrativas) Bloqueado Llamados directos a las rutas base del frontend administrativo (/dashboard/security/roles) retornan un cerrojo a nivel Web server.
Inyección NoSQLi en Formulario de Auth Resistente Inyecciones de manipulador de objetos {"$gt":""} fueron rechazadas limpiamente, evitando login bypass (HTTP 401).
Ataques de SSRF/XSS Ciego Resistente El uso de payloads de iframes en campos string (extracción de metadata AWS) falló limpiamente.
Condiciones de Carrera (DDoS Asimétrico) Seguro El envío de 50 peticiones simultáneas concurrentes no crasheó el motor de express (HTTP 500) ni produjo comportamientos disonantes. Node.js lo procesó y despachó sin alteraciones de memoria.

Resultados Fase 3 (Source Code & Fuzzing Core)

Análisis del Código en Producción (Bundle JS) Seguro Se descargó y descompiló el archivo main.c05970775482fc41.js (13MB). Se ejecutaron búsquedas de expreiones regulares pero NO hubo filtración de llaves, passwords, AWS Keys (AKIA), o tokens Bearer.
CORS Malicioso (Origin Fallback & Null) Seguro vía Nginx Inyecciones de cabeceras Origin: https://evil.com y Origin: null probaron que la API no hace reflexión ciega del dominio a través del proxy Nginx (:443). Sin embargo, al acceder directamente por el puerto 3000, se descubrió CORS wildcard * (ver VULN-12 en sección 9).
Crash JSON (Inyección de Bytes Nulos - \u0000) Vulnerable Se logró colapsar el hilo de conexión de Express/BD inyectando un Null Byte en el string de username ("admin\u0000"). En vez de descartarse, provocó un Unhandled Exception (HTTP 500). Reportado como VULN-07.
Path Traversal Enmascarado (LFI Proxy Bypass) Bloqueado Enrutamientos absurdos ../../etc/passwd fueron denegados por Nginx como 404 antes de tocar al Express.

Resultados Fase 4 (Exposición de Datos y Mapeo Clandestino)

Ante la interrogante de la protección real de los datos (PII e información médica), se realizaron pruebas de Ciberinteligencia OSINT y Fuzzing de Directorios para evaluar fugas:

Cero Fugas en Errores Fatales (Unhandled Exceptions) Seguro Al forzar el Error 500 mediante la inyección del Null Byte (VULN-07), el servidor NO filtró ninguna traza del stack de código ni queries SQL. Devolvió un mensaje esterilizado JSON puro: {"status":"error","message":"Database error occurred","data":null}. El middleware global de manejo de errores está excelentemente configurado.
Ausencia de Documentación Expuesta (Swagger/GraphQL) Seguro Se escanearon rutas como /api-docs y /swagger-ui.html. No existió ninguna interfaz de documentación OpenAPI accidentalmente encendida en producción que pudiese derramar el Schema de la base de datos al atacante.
Bloqueo contra Fuga de Backup o Configs Huérfanas Seguro Se rastrearon archivos sensibles clásicos en la raíz (/.env, /docker-compose.yml, /dump.sql). La zona pública de Nginx está totalmente limpia. Cero residuos de deployment.
Privacidad Total de Catálogos (BOLA de Lectura) Seguro Se intentó leer endpoints informativos como /common/api/v1/blood-types o /diagnostics. Ninguno permite lectura pública. Protegidos rigurosamente por JWT.

🛡️ Veredicto Final de Protección de Datos (PII)

La arquitectura de base de datos y la exposición de los historiales clínicos cuentan con una barrera hermética de primer nivel a ojos del internet público (Caja Negra). Sin lograr explotar el VULN-02 (Rate Limit) o el VULN-03 (Robo de Session) descritos anteriormente, es matemáticamente inviable para un atacante extraer un solo registro, exfiltrar las tablas o conocer el esquema interno de la plataforma. La información residente está sumamente protegida.

6. Suite Completa de Seguridad — 12 Tests Automatizados

Se ejecutó el script fase8_full_security_tests.sh que automatiza 12 bloques independientes de pruebas de seguridad. Resultados consolidados:

VULN-08: Ausencia Total de Security Headers en Endpoint /health ALTA

CVSS: 6.1
Vector: HTTP Response Headers

Se descubrió que el endpoint /health (y potencialmente otros) carece de los 7 headers de seguridad estándar recomendados por OWASP:

  • Strict-Transport-Security (HSTS) — Sin protección contra SSL Stripping
  • Content-Security-Policy (CSP) — Sin protección contra XSS e inyección de scripts
  • X-Content-Type-Options — Vulnerable a MIME-type sniffing
  • X-Frame-Options — Vulnerable a Clickjacking
  • X-XSS-Protection — Sin filtro XSS del navegador
  • Referrer-Policy — Fuga de información de referencia
  • Permissions-Policy — Sin restricciones de APIs del navegador

Adicionalmente, el header X-Powered-By: Express sigue expuesto, revelando la tecnología del backend.

Recomendación de Remediación

Instalar Helmet.js en Express (app.use(helmet())) que configura automáticamente todos estos headers. Complementar con configuración Nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
proxy_hide_header X-Powered-By;

Resultados por Bloque de Test

Test 1: Brute Force / Rate Limiting Vulnerable Se realizaron 75 intentos de login sin recibir un HTTP 429. El rate limiting no se activó. Compatible con VULN-02.
Test 2: JWT Manipulation (alg:none) Seguro Tokens con algoritmo none y firma inválida fueron rechazados correctamente en todos los endpoints (HTTP 401).
Test 3: RBAC Rutas Admin sin Auth Seguro Las 22 rutas administrativas testeadas retornaron 401 o 404. Ninguna ruta administrativa expuesta sin autenticación.
Test 4: Cookie Flags Info El endpoint de login no retorna cookies Set-Cookie. El JWT se maneja exclusivamente vía body JSON (compatible con VULN-03: almacenamiento en LocalStorage).
Test 5: Security Headers Vulnerable 7 de 7 headers de seguridad ausentes. Documentado como VULN-08.
Test 6: Business Logic sin Auth Seguro Crear, cancelar y modificar citas, acceder a documentos e historiales clínicos — todo retornó HTTP 401. Lógica de negocio completamente protegida.
Test 7: Hidden Routes Enumeration Seguro De 36 rutas probadas, ninguna retornó HTTP 200. Se detectó /.env → 403 y /server-status → 403 (Nginx bloqueando correctamente).
Test 8: SSRF / Open Redirect Seguro 6 payloads SSRF (metadata AWS, localhost, file://) y 4 payloads Open Redirect fueron todos rechazados (HTTP 401).
Test 9: Injection Payloads (SQLi, NoSQLi, XSS) Seguro 6 variantes SQL injection, 4 NoSQL injection y 4 XSS fueron rechazadas (HTTP 400/401). Ninguna inyección ejecutada.
Test 10: Race Condition Seguro 10 peticiones concurrentes al mismo slot retornaron todas HTTP 401 sin crash del servidor.
Test 11: SSL/TLS Seguro TLS 1.3 con cipher AEAD-CHACHA20-POLY1305-SHA256. Certificado Let's Encrypt válido hasta abril 2026.
Test 12: HTTP Method Tampering Seguro TRACE y CONNECT bloqueados (HTTP 405). PUT, DELETE, PATCH requieren autenticación (401). OPTIONS responde 204 (CORS preflight correcto).

7. Ataques Avanzados de Alto Impacto

VULN-09: Host Header Injection — Riesgo de Cache Poisoning ALTA

CVSS: 6.8
Vector: HTTP Host Header

El endpoint /health acepta peticiones con headers Host: evil.com, X-Forwarded-Host: evil.com y X-Real-IP: 127.0.0.1 retornando HTTP 200 en todos los casos. Esto permite:

  • 🚨 Cache Poisoning: Un atacante puede envenenar la caché de Nginx/CDN para servir contenido malicioso
  • 🚨 Password Reset Poisoning: Si existe un flujo de recuperación de contraseña, el enlace de reset podría apuntar a un servidor controlado por el atacante
  • 🚨 IP Spoofing: X-Forwarded-For y X-Real-IP son aceptados, potencialmente evadiendo restricciones por IP
$ curl -s -o /dev/null -w "%{http_code}" https://api.olivia.net.co/health -H "Host: evil.com"
200  ← Debería ser 400 o 421 Misdirected Request

Recomendación de Remediación

Configurar Nginx con server_name estricto y bloque default_server que rechace hosts no reconocidos. En Express, usar middleware que valide el header Host contra una whitelist. Configurar set_real_ip_from solo para IPs de confianza (load balancer).

Resultados por Test (Fase 9)

Test 1: HTTP Request Smuggling Seguro CL.TE, TE.CL y TE.TE obfuscation fueron rechazados (HTTP 400). Nginx maneja correctamente las discrepancias.
Test 2: Host Header Injection Vulnerable Headers Host, X-Forwarded-Host, X-Host y X-Real-IP aceptados con HTTP 200. Documentado como VULN-09.
Test 3: Prototype Pollution Seguro 6 payloads de __proto__ y constructor.prototype rechazados (401). No se generó token ni bypass.
Test 4: CRLF Injection Seguro Intentos de inyección de headers via CRLF fueron rechazados. No se logró inyectar headers en la respuesta.
Test 5: Timing Attacks Seguro No hay diferencia significativa en tiempos de respuesta entre usuarios probables (admin: 0.40s) y aleatorios (xzq9k: 0.30s). No hay enumeración por timing.
Test 6: WebSocket / Socket.io Seguro No se detectaron endpoints WebSocket/Socket.io expuestos (404 en todos).
Test 7: Content-Type Confusion Seguro XML+XXE, multipart, text/plain rechazados (400). x-www-form-urlencoded procesado pero rechazado con 401.
Test 8: Unicode / Homoglyph Seguro 7 variantes unicode (cirílico, zero-width, combining chars) rechazadas correctamente (401).
Test 9: Cache Poisoning / Deception Observación /health/nonexistent.css retorna 200 (catch-all). Si hay CDN, podría cachear rutas falsas.
Test 10: Parser DoS Seguro JSON con 50 niveles de anidamiento, claves de 10K chars y 100 claves rechazados (400). Parser robusto.

8. Reconocimiento de Infraestructura

VULN-10: Puertos de Servicios Internos Expuestos Públicamente CRÍTICA

CVSS: 9.1
Vector: Network / Firewall

El escaneo de puertos reveló que servicios internos están accesibles desde internet público:

  • 🚨 Puerto 3000 (Node.js directo) → HTTP 404 — El backend Express responde directamente sin pasar por Nginx
  • 🚨 Puerto 8080 → HTTP 200 — Servicio web alternativo completamente accesible
  • 🔴 Puerto 27017 (MongoDB) → HTTP 200 — Base de datos MongoDB accesible desde internet
$ curl http://api.olivia.net.co:3000/   → 404 (Node.js directo)
$ curl http://api.olivia.net.co:8080/   → 200 (servicio alternativo)
$ curl http://api.olivia.net.co:27017/  → 200 (MongoDB!)

⚠️ ACCIÓN INMEDIATA REQUERIDA

1. Configurar el firewall de DigitalOcean para bloquear TODOS los puertos excepto 80 y 443.
2. Configurar MongoDB para escuchar solo en 127.0.0.1 (bindIp: 127.0.0.1).
3. Asegurar que Node.js solo acepte conexiones desde Nginx (proxy_pass).
4. Auditar inmediatamente si hubo accesos no autorizados a MongoDB.

VULN-11: DMARC en Modo Solo Monitor (p=none) — Email Spoofing Posible MEDIA

CVSS: 5.0
Vector: DNS / Email

El registro DMARC del dominio tiene política p=none:

"v=DMARC1; p=none;"

Esto significa que servidores de correo no bloquearán emails enviados suplantando direcciones @olivia.net.co. Combinado con la ausencia de registros SPF y MX, un atacante puede enviar emails de phishing haciéndose pasar por Olivia.

Recomendación de Remediación

Cambiar la política DMARC a p=reject o al menos p=quarantine. Configurar registros SPF y DKIM en el DNS.

Resultados Reconocimiento

Subdominios Mínimo Solo 1 subdominio encontrado (api.olivia.net.co). Superficie de ataque reducida.
SSL/TLS Seguro TLS 1.2 y 1.3 soportados. Certificado Let's Encrypt válido. HTTP redirige a HTTPS (301).
Infraestructura Info Hospedado en DigitalOcean (IP: 161.35.254.154). NS: DigitalOcean. HTTP/1.1 (sin HTTP/2).
CVEs Conocidos (Nginx 1.24.0) Riesgo CVE-2024-7347 (OOB read en MP4) y CVE-2023-44487 (HTTP/2 Rapid Reset DoS). Recomendación: actualizar a ≥ 1.25.4.

9. Deep Dive en Servicios Expuestos 🔴

Se realizó un análisis profundo de los puertos expuestos descubiertos en Fase 10. Los resultados son extremadamente críticos:

VULN-12: CORS Wildcard (*) en Puerto 3000 — Bypass Total de Restricciones CORS CRÍTICA

CVSS: 8.6
Vector: Network / CORS Bypass

Al acceder directamente al puerto 3000 (Node.js/Express sin Nginx), se descubrió que la configuración CORS devuelve:

Access-Control-Allow-Origin: *

Esto significa que cualquier sitio web puede hacer peticiones cross-origin al backend directamente, evadiendo todas las restricciones CORS configuradas en Nginx. Combinado con la ausencia de rate limiting en este puerto (20 intentos sin HTTP 429), un atacante puede:

  • 🚨 Ejecutar ataques de fuerza bruta desde cualquier navegador via JavaScript
  • 🚨 Exfiltrar datos si obtiene un JWT válido (usando VULN-02 + VULN-03)
  • 🚨 Realizar CSRF attacks contra usuarios autenticados de Olivia

⚠️ ACCIÓN INMEDIATA

1. Bloquear puerto 3000 al público en el firewall de DigitalOcean.
2. Configurar Express con CORS estricto: cors({ origin: ['https://olivia.net.co'] }).
3. Asegurar que Node.js solo escuche en 127.0.0.1:3000 (no en 0.0.0.0:3000).

VULN-13: Frontend Angular Expuesto sin Restricciones en Puerto 8080 ALTA

CVSS: 6.5
Vector: Network / Server Misconfiguration

El puerto 8080 sirve la aplicación Angular completa de Olivia via un segundo Nginx (versión 1.25.4), distinto al principal (1.24.0). Todas las rutas retornan HTTP 200:

:8080/         → 200 (Frontend Angular)
:8080/admin    → 200 (Panel admin!)
:8080/dashboard→ 200 (Dashboard!)
:8080/login    → 200 (Login!)
:8080/.env     → 200 (catch-all SPA)
:8080/config   → 200 (catch-all SPA)

Este servidor secundario podría no tener las mismas protecciones (headers de seguridad, rate limiting) que el Nginx principal en el puerto 443.

Recomendación de Remediación

Bloquear el puerto 8080 en el firewall. Si es necesario como servidor de staging/desarrollo, restringir su acceso solo a IPs internas o VPN.

Hallazgos Adicionales Fase 11

MongoDB (Puerto 27017) Confirmado Expuesto Responde: "It looks like you are trying to access MongoDB over HTTP on the native driver port." — Confirma que MongoDB está escuchando en la interfaz pública. Aunque no responde a HTTP, un atacante puede conectarse usando el driver nativo de MongoDB.
Rate Limiting en :3000 Ausente 20 intentos de login en el puerto 3000 sin ningún bloqueo. El rate limiting de Nginx(:443) no aplica aquí.
DNS Zone Transfer Seguro Los 3 servidores NS de DigitalOcean rechazan transferencias AXFR.
API Versioning Seguro Solo v1 responde (401). No hay v2, v3 ni versiones beta/internal expuestas.
Dos instancias de Nginx Observación Puerto 443: Nginx 1.24.0. Puerto 8080: Nginx 1.25.4. Dos versiones distintas sugieren configuraciones independientes con posibles inconsistencias de seguridad.

10. Explotación de Servicios Expuestos 🔴

VULN-14: Source Maps Expuestos en Puerto 8080 — Código Fuente Legible ALTA

CVSS: 6.5
Vector: HTTP / Information Disclosure

Se encontraron 7 archivos .map (source maps) accesibles en el puerto 8080:

http://api.olivia.net.co:8080/main.c05970775482fc41.js.map
http://api.olivia.net.co:8080/polyfills.js.map
http://api.olivia.net.co:8080/runtime.js.map
http://api.olivia.net.co:8080/styles.css.map
http://api.olivia.net.co:8080/vendor.js.map
http://api.olivia.net.co:8080/scripts.js.map

Los source maps permiten reconstruir el código fuente original de Angular con nombres de variables, funciones y componentes reales, agravando VULN-01 (bundle sin ofuscar).

Recomendación de Remediación

Eliminar los archivos .map del build de producción con --source-map=false en Angular CLI. Bloquear *.map en Nginx.

Resultados Detallados Fase 12

Brute Force en :3000 Resistente 180 combinaciones (10 usuarios × 18 passwords comunes) sin encontrar credenciales válidas. Las contraseñas no son triviales.
Account Lockout en :3000 Ausente 50 intentos fallidos contra el mismo usuario sin bloqueo de cuenta ni rate limiting. Un atacante puede probar millones de contraseñas.
CORS en :3000 (5 orígenes) Wildcard Confirmado Access-Control-Allow-Origin: * para TODOS los orígenes probados (evil.com, null, localhost, olivia.net.co).
Endpoints OTP/Reset Protegidos Endpoints de forgot-password, reset-password, OTP verify y OTP generate requieren autenticación (401).
Endpoint de Registro Protegido /auth/register requiere token JWT (401). No hay registro público abierto.
Headers :8080 vs :443 Sin Protección Puerto 8080 no tiene HSTS, CSP, X-Frame-Options ni X-Content-Type-Options. Expone Server: nginx/1.25.4.
Error Disclosure en :3000 Parcial JSON inválido muestra "Bad Request" genérico. Null byte sigue causando HTTP 500 con error de BD. Path traversal devuelve "Cannot GET" (Express default).
Bundle JS en :8080 Identical Mismo bundle main.c05970775482fc41.js (13.7 MB) que en :443. No hay assets diferentes de staging.

11. Resumen Ejecutivo Final — Auditoría Completa

14 Vulnerabilidades Confirmadas

IDVulnerabilidadSeveridadCVSS
VULN-10🔴 Puertos internos expuestos (MongoDB:27017, Node:3000, HTTP:8080)CRÍTICA9.1
VULN-12🔴 CORS Wildcard (*) en :3000 — bypass total + sin rate limitingCRÍTICA8.6
VULN-02Rate Limiting débil + sin Account Lockout (50+ intentos)Alta7.5
VULN-03JWT en LocalStorage (riesgo XSS)Alta7.1
VULN-09Host Header Injection (cache/reset poisoning)Alta6.8
VULN-01Bundle JS sin ofuscar expone arquitecturaAlta6.5
VULN-13Frontend Angular en :8080 sin protecciónAlta6.5
VULN-14Source Maps (.map) expuestos en :8080Alta6.5
VULN-087 Security Headers ausentesAlta6.1
VULN-07Null Byte Injection → HTTP 500Media5.5
VULN-04Ausencia de HSTS/CSPMedia5.4
VULN-05Headers de servidor expuestos (Express/Nginx)Media5.3
VULN-11DMARC p=none (email spoofing posible)Media5.0
VULN-06Endpoint /health públicoMedia4.3

📊 Puntuación de Seguridad Global Final

5.2 / 10 — Autenticación y autorización sólidas a nivel de middleware, pero la infraestructura está gravemente expuesta. MongoDB accesible desde internet (VULN-10), CORS wildcard sin rate limiting (VULN-12), source maps expuestos (VULN-14), y ausencia total de security headers (VULN-08) hacen que la plataforma no sea apta para datos médicos reales sin correcciones inmediatas de firewall y configuración.

🛡️ Plan de Acción Prioritario

  1. INMEDIATO (Hoy): Configurar firewall DigitalOcean — bloquear puertos 3000, 8080, 27017
  2. INMEDIATO: Configurar MongoDB bindIp: 127.0.0.1
  3. URGENTE (Esta semana): Instalar Helmet.js, configurar CORS estricto en Express, eliminar source maps
  4. CORTO PLAZO: Implementar rate limiting + account lockout + CAPTCHA
  5. MEDIANO PLAZO: Migrar JWT a HttpOnly cookies, ofuscar bundle JS, configurar HSTS/CSP

12. Riesgo de Sanciones Legales en Colombia ⚖️

Dado que Olivia gestiona historias clínicas y datos de salud, las vulnerabilidades descubiertas representan un riesgo legal directo bajo la legislación colombiana. A continuación, el mapeo de cada falla con las leyes y sanciones aplicables:

⚠️ Marco Legal Aplicable

NormaAlcanceSanción Máxima
Ley 1581 de 2012 Protección de datos personales. Los datos de salud son clasificados como datos sensibles (Art. 5) con el nivel más alto de protección. Hasta 2.000 SMLMV (~$2.600 millones COP en 2026)
Ley 2015 de 2020 Historia Clínica Electrónica Interoperable. Exige garantizar la reserva, confidencialidad y seguridad de la información clínica. Sanciones administrativas + suspensión de actividades
Resolución 866 de 2021 Reglamenta la interoperabilidad de la HC. Establece requisitos de seguridad de la información para actores del sistema de salud. Sanciones del MinSalud + SIC
Decreto 1074 de 2015 Reglamenta la Ley 1581. Exige medidas técnicas, humanas y administrativas para evitar adulteración, pérdida, consulta o acceso no autorizado. Cierre temporal + multa

Vulnerabilidades vs. Riesgo Legal

VulnerabilidadNorma VioladaRiesgo Legal Concreto
VULN-10: MongoDB expuesto al público Ley 1581 Art. 17 (medidas de seguridad), Decreto 1074 🔴 Acceso no autorizado a datos sensibles de salud. La SIC puede imponer multa de hasta 2.000 SMLMV + ordenar suspensión de actividades de tratamiento de datos. Precedente: En 2024 la SIC sancionó con $190M COP y suspendió por 6 meses el tratamiento de datos de una empresa por fallas similares.
VULN-12: CORS wildcard sin rate limiting Ley 1581 Art. 17, Ley 2015 Art. 8 🔴 Permite exfiltración masiva de historias clínicas desde cualquier navegador si un JWT es comprometido. Incumple el deber de implementar medidas técnicas adecuadas.
VULN-02: Sin rate limiting ni account lockout Ley 1581 Art. 17 literal d) Facilita fuerza bruta para acceder a cuentas de médicos/pacientes. La ausencia de mecanismos anti-fraude es un incumplimiento del deber de seguridad.
VULN-03: JWT en LocalStorage Ley 1581 Art. 17, Resolución 866 Un ataque XSS permite robo de sesión y acceso completo a historias clínicas del paciente o profesional. Fallo en medidas de seguridad de la información.
VULN-08: Headers de seguridad ausentes Ley 1581 Art. 17, buenas prácticas OWASP La ausencia de CSP, HSTS y X-Frame-Options facilita ataques de phishing, clickjacking y man-in-the-middle que pueden comprometer datos de pacientes.
VULN-14: Source Maps expuestos Ley 1581 Art. 17 Expone la arquitectura interna del sistema de salud, facilitando ataques dirigidos para acceder a datos sensibles.
VULN-11: DMARC p=none Ley 1581 Art. 17 Permite suplantación de correos @olivia.net.co para campañas de phishing contra pacientes y profesionales de salud.

📊 Contexto de Sanciones Recientes de la SIC (2024-2025)

  • En 2024 la SIC impuso sanciones por más de $17.500 millones COP en protección de datos (incremento del 22%)
  • En 2025 (hasta agosto): 101 investigaciones abiertas y multas superiores a $5.157 millones COP
  • Multa emblemática de $214 millones COP (marzo 2025) por uso de datos biométricos sin consentimiento
  • El sector salud está catalogado como sector de alto riesgo por la SIC
  • La SIC ha pasado de una postura educativa a una postura activamente sancionatoria

🛡️ Recomendación Legal

Para operar legalmente como plataforma de salud en Colombia, Olivia debe corregir las vulnerabilidades VULN-10, VULN-12 y VULN-02 antes de procesar datos reales de pacientes. La exposición pública de MongoDB (VULN-10) constituye un incumplimiento flagrante del Artículo 17 de la Ley 1581. Se recomienda realizar una consulta formal con la SIC sobre las obligaciones del Responsable del Tratamiento y completar la inscripción de las bases de datos en el Registro Nacional de Bases de Datos (RNBD) si no se ha hecho.

🔒 Siguiente Fase: Pentest de Caja Negra Avanzado

Para acceder a la Etapa 2 — Pentest de Caja Negra Avanzado, que incluye análisis de código fuente, acceso controlado a bases de datos, pruebas de escalada de privilegios y evaluación exhaustiva de la lógica de negocio, es requisito indispensable:

  1. Diligenciar y firmar los formatos de autorización de pruebas de seguridad proporcionados por Sentinel by Rocket Launch
  2. Firmar un Acuerdo de Confidencialidad (NDA) entre las partes
  3. Definir y aprobar el alcance y las reglas de engagement del pentest avanzado
  4. Aceptar formalmente la ejecución de pruebas en un entorno controlado y aislado
  5. Designar un punto de contacto técnico disponible durante la ejecución de las pruebas

Para iniciar el proceso de Etapa 2, contactar a Sentinel by Rocket Launch.