🛡️ Sentinel by Rocket Launch
Proyecto: Olivia (olivia.net.co)
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.
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.
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).
El siguiente mapa de rutas fue extraído sin estar autenticado gracias a la exposición del código del Frontend (VULN-01).
POST /auth/api/v1/auth/login/auth/api/v1/auth/refresh/otp (Posible 2FA)/people/api/v1/patients/people/api/v1/professionals/dashboard/management/people/appointments/api/v1/appointments/api/v1/people-documents/appointments/exams & medicamentos/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/dashboard/admin/configuration/*/dashboard/security/roles y permissions/dashboard/security/modulesGET /health (⚠️ Sin autenticar)/logs & /notificationsEl 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.
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.
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.
x-ratelimit-limit: 1000x-ratelimit-remaining: 962 (tras varias peticiones)[*] Iniciando fuerza bruta: 208 combinaciones...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.
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.
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.
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.
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.
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.
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.
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.
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. |
| 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. |
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. |
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.
Se ejecutó el script fase8_full_security_tests.sh que automatiza 12 bloques independientes de pruebas de seguridad. Resultados consolidados:
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 StrippingContent-Security-Policy (CSP) — Sin protección contra XSS e inyección de scriptsX-Content-Type-Options — Vulnerable a MIME-type sniffingX-Frame-Options — Vulnerable a ClickjackingX-XSS-Protection — Sin filtro XSS del navegadorReferrer-Policy — Fuga de información de referenciaPermissions-Policy — Sin restricciones de APIs del navegadorAdicionalmente, el header X-Powered-By: Express sigue expuesto, revelando la tecnología del backend.
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;
| 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). |
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:
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
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).
| 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. |
El escaneo de puertos reveló que servicios internos están accesibles desde internet público:
$ 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!)
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.
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.
Cambiar la política DMARC a p=reject o al menos p=quarantine. Configurar registros SPF y DKIM en el DNS.
| 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. |
Se realizó un análisis profundo de los puertos expuestos descubiertos en Fase 10. Los resultados son extremadamente críticos:
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:
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).
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.
Bloquear el puerto 8080 en el firewall. Si es necesario como servidor de staging/desarrollo, restringir su acceso solo a IPs internas o VPN.
| 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. |
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).
Eliminar los archivos .map del build de producción con --source-map=false en Angular CLI. Bloquear *.map en Nginx.
| 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. |
| ID | Vulnerabilidad | Severidad | CVSS |
|---|---|---|---|
| VULN-10 | 🔴 Puertos internos expuestos (MongoDB:27017, Node:3000, HTTP:8080) | CRÍTICA | 9.1 |
| VULN-12 | 🔴 CORS Wildcard (*) en :3000 — bypass total + sin rate limiting | CRÍTICA | 8.6 |
| VULN-02 | Rate Limiting débil + sin Account Lockout (50+ intentos) | Alta | 7.5 |
| VULN-03 | JWT en LocalStorage (riesgo XSS) | Alta | 7.1 |
| VULN-09 | Host Header Injection (cache/reset poisoning) | Alta | 6.8 |
| VULN-01 | Bundle JS sin ofuscar expone arquitectura | Alta | 6.5 |
| VULN-13 | Frontend Angular en :8080 sin protección | Alta | 6.5 |
| VULN-14 | Source Maps (.map) expuestos en :8080 | Alta | 6.5 |
| VULN-08 | 7 Security Headers ausentes | Alta | 6.1 |
| VULN-07 | Null Byte Injection → HTTP 500 | Media | 5.5 |
| VULN-04 | Ausencia de HSTS/CSP | Media | 5.4 |
| VULN-05 | Headers de servidor expuestos (Express/Nginx) | Media | 5.3 |
| VULN-11 | DMARC p=none (email spoofing posible) | Media | 5.0 |
| VULN-06 | Endpoint /health público | Media | 4.3 |
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.
bindIp: 127.0.0.1Dado 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:
| Norma | Alcance | Sanció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 |
| Vulnerabilidad | Norma Violada | Riesgo 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. |
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.
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:
Para iniciar el proceso de Etapa 2, contactar a Sentinel by Rocket Launch.