🔍 Auditoría de Red — AquilaScan WDTP-80 CONFIDENCIAL

EMERCOM SpA  ·  Proyecto Workmed  ·  2026-05-18 13:37:44  ·  Directorio: AUDIT_RED_20260518_115720
5
Hallazgos críticos
5
Hallazgos altos
41
Rutas activas en update server

Infraestructura identificada

Update Server — TSCOM
164.77.118.86
AS6471 ENTEL CHILE S.A.
Santiago, CL
Apache 2.4.43 · PHP 7.4.8
tscom.cl → 164.77.118.92 (mismo /24)
Backend GCF — SACMED para Workmed
southamerica-west1
Proyecto GCP: workmed-log
QA: /aquilascan
PROD: /aquilascan-prod
Protocolo: XML POST · sin auth verificada
Update server original (manual SACMED)
202.105.129.162:9090
Shenzhen, China (ChinaNet Backbone)
Fabricante original AquilaScan
⚠ Diferente al dispositivo actual

Mapa de infraestructura

generado automáticamente
Mapa infraestructura AquilaScan

Hallazgos de seguridad

12 total
SeveridadDescripciónQué significa / impacto
CRÍTICO Ruta sensible expuesta: /db → HTTP 200 sin autenticación Endpoint de base de datos accesible sin autenticación. Puede exponer registros de exámenes toxicológicos, datos de trabajadores, RUTs y resultados médicos — todos datos sensibles bajo Ley 21.719.
CRÍTICO Ruta sensible expuesta: /backup → HTTP 200 sin autenticación Archivos de backup accesibles sin autenticación. Típicamente contienen volcados completos de base de datos o archivos comprimidos del sistema. Equivale a entregar una copia completa del servidor.
CRÍTICO Ruta sensible expuesta: /data → HTTP 200 sin autenticación Revisar manualmente el archivo de auditoría correspondiente para evaluar el impacto específico en el contexto de Workmed.
CRÍTICO Ruta sensible expuesta: /logs → HTTP 200 sin autenticación Revisar manualmente el archivo de auditoría correspondiente para evaluar el impacto específico en el contexto de Workmed.
CRÍTICO Servidor acepta HTTP 200 a todas las credenciales probadas (40 combinaciones) — posible autenticación sin validación real o catch-all handler Revisar manualmente el archivo de auditoría correspondiente para evaluar el impacto específico en el contexto de Workmed.
ALTO Endpoint de autenticación sin protección: /api/login → HTTP 200 El endpoint de login responde HTTP 200 a cualquier credencial probada. Esto indica ausencia de validación real, un handler catch-all, o que el servidor no distingue entre login exitoso y fallido — lo que hace imposible confiar en la autenticación.
ALTO Endpoint de autenticación sin protección: /login → HTTP 200 El endpoint de login responde HTTP 200 a cualquier credencial probada. Esto indica ausencia de validación real, un handler catch-all, o que el servidor no distingue entre login exitoso y fallido — lo que hace imposible confiar en la autenticación.
ALTO Endpoint de autenticación sin protección: /auth → HTTP 200 El endpoint de login responde HTTP 200 a cualquier credencial probada. Esto indica ausencia de validación real, un handler catch-all, o que el servidor no distingue entre login exitoso y fallido — lo que hace imposible confiar en la autenticación.
ALTO Endpoint de autenticación sin protección: /api/auth → HTTP 200 El endpoint de login responde HTTP 200 a cualquier credencial probada. Esto indica ausencia de validación real, un handler catch-all, o que el servidor no distingue entre login exitoso y fallido — lo que hace imposible confiar en la autenticación.
ALTO Endpoint de autenticación sin protección: /api/token → HTTP 200 El endpoint de login responde HTTP 200 a cualquier credencial probada. Esto indica ausencia de validación real, un handler catch-all, o que el servidor no distingue entre login exitoso y fallido — lo que hace imposible confiar en la autenticación.
MEDIO Cloud Function /aquilascan activa (HTTP 400) — acepta XML sin autenticación verificada La Cloud Function existe y procesa requests. El HTTP 400 indica que rechaza el payload por formato incorrecto, pero no por falta de autenticación — cualquier actor que conozca el esquema XML correcto puede enviar datos o consultar información.
MEDIO Cloud Function /aquilascan-prod activa (HTTP 400) — acepta XML sin autenticación verificada La Cloud Function existe y procesa requests. El HTTP 400 indica que rechaza el payload por formato incorrecto, pero no por falta de autenticación — cualquier actor que conozca el esquema XML correcto puede enviar datos o consultar información.

Rutas activas — 164.77.118.86

41 encontradas
RutaHTTPRiesgoQué significa
/ 200 INFO Endpoint activo. Revisar contenido manualmente.
/index.php 200 ALTO Ruta sensible activa sin autenticación verificada.
/index.html 200 INFO Endpoint activo. Revisar contenido manualmente.
/api 301 INFO Redirección → revisar destino.
/api/ 403 INFO Endpoint responde con código no-404.
/api/v1 301 INFO Redirección → revisar destino.
/api/v1/ 200 INFO Endpoint activo. Revisar contenido manualmente.
/api/v2 200 MEDIO API versión 2 expuesta. Superficie adicional sin documentación verificada.
/api/v2/ 200 INFO Endpoint activo. Revisar contenido manualmente.
/api/login 200 ALTO Endpoint de autenticación expuesto sin protección verificada. Respondió HTTP 200 a todas las credenciales probadas.
/api/auth 200 ALTO Endpoint de autenticación alternativo expuesto. Mismo comportamiento que /api/login.
/api/token 200 ALTO Endpoint de generación de tokens expuesto. Podría permitir obtener tokens de acceso sin credenciales válidas.
/login 200 ALTO Login sin protección verificada. El servidor no distinguió entre credenciales válidas e inválidas.
/auth 200 ALTO Auth endpoint expuesto. Ver pruebas de credenciales en la sección siguiente.
/api/device 200 MEDIO Info de dispositivo individual. Puede exponer configuración y serial numbers.
/api/devices 200 MEDIO Lista de dispositivos registrados. Expone IDs y metadata de todos los WDTP-80 del sistema.
/api/wdtp 200 MEDIO Endpoint específico WDTP sin autenticación verificada.
/api/wdtp80 200 MEDIO Endpoint WDTP-80 expuesto. Posible acceso a configuración o datos del modelo específico.
/api/aquilascan 200 MEDIO API AquilaScan expuesta. Puede exponer funciones internas del sistema de gestión.
/device 200 MEDIO Info de dispositivo sin autenticación. Ver /api/device.
/devices 200 MEDIO Lista de dispositivos sin autenticación. Ver /api/devices.
/wdtp 200 MEDIO Endpoint WDTP expuesto. Ver /api/wdtp.
/aquilascan 200 MEDIO Endpoint AquilaScan expuesto directamente. Ver /api/aquilascan.
/api/results 200 ALTO API de resultados expuesta. Acceso sin autenticación a resultados de tests toxicológicos.
/api/tests 200 MEDIO Tests/exámenes accesibles vía API sin autenticación verificada.
/api/export 200 ALTO Endpoint de exportación de datos. Sin autenticación podría entregar volcados masivos de registros.
/api/sync 200 MEDIO Sincronización de datos sin autenticación verificada. Podría permitir inyectar o extraer registros.
/results 200 ALTO Resultados de exámenes potencialmente accesibles sin autenticación. Datos de salud sensibles bajo Ley 21.719.
/tests 200 MEDIO Tests/exámenes accesibles. Ver /api/tests.
/data 200 ALTO Endpoint /data sin autenticación. Posible acceso a datos de exámenes o archivos del sistema.
/db 200 CRÍTICO Endpoint de base de datos sin autenticación. Posible acceso a registros de exámenes y datos de trabajadores.
/logs 200 ALTO Logs del sistema accesibles. Pueden contener credenciales, tokens, errores con rutas internas y trazas de stack.
/log 200 ALTO Log endpoint expuesto. Ver /logs.
/backup 200 CRÍTICO Backup accesible sin autenticación. Puede contener volcado completo de la base de datos o archivos del sistema.
/update 200 MEDIO Actualizaciones del sistema sin autenticación. Ver /api/update.
/firmware 200 ALTO Firmware del dispositivo accesible sin autenticación. Vector de supply-chain attack sobre todos los WDTP-80 conectados.
/apk 200 ALTO APK de la app AquilaScan descargable sin autenticación. Vector de análisis de ingeniería inversa o distribución de versión maliciosa.
/app 200 INFO Endpoint de aplicación. Contenido no verificado.
/download 200 ALTO Directorio de descargas expuesto. Puede incluir APKs, firmwares, configuraciones o backups.
/sync 200 MEDIO Sincronización expuesta. Acceso sin autenticación verificada.
/upload 200 MEDIO Subida de archivos sin autenticación verificada. Vector de carga de código malicioso.
/check 200 INFO Endpoint de verificación. Puede incluir info de versión o estado.
/admin 200 MEDIO Panel de administración expuesto. Dependiendo del contenido puede ser crítico.
/panel 200 MEDIO Panel de control expuesto sin autenticación verificada.
/dashboard 301 INFO Redirección → revisar destino.

Evidencia — rutas sensibles (/db, /backup, /.env, /.git)

sensitive_paths.txt  ·  136 B  ·  12 líneas

Estas rutas respondieron HTTP 200 en el servidor de actualizaciones (164.77.118.86) sin requerir autenticación. HTTP 200 significa que el servidor procesó el request y devolvió contenido — no que el acceso fue bloqueado. En un servidor de producción con datos médicos, cualquiera de estas rutas accesible sin auth es una vulnerabilidad crítica.

=== GET /db → HTTP 200 ===
2

=== GET /backup → HTTP 200 ===
2

=== GET /data → HTTP 200 ===
2

=== GET /logs → HTTP 200 ===
2

Evidencia — pruebas de autenticación por defecto

auth_tests.txt  ·  3,287 B  ·  122 líneas

Se enviaron credenciales triviales (admin/admin, aquila/aquila, workmed/workmed, etc.) a todos los endpoints de login. HTTP 200 en respuesta a credenciales inválidas indica que el servidor no valida correctamente las credenciales — ya sea porque el endpoint no tiene autenticación implementada, usa un handler catch-all que devuelve 200 siempre, o las credenciales por defecto son realmente válidas. Un login legítimo rechaza credenciales incorrectas con HTTP 401 o 403 — nunca 200.

=== Pruebas de autenticación ===

POST /api/login | body={"user":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /login | body={"user":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"admin","password":"admin123"} | HTTP=200
Resp: 2

POST /login | body={"user":"admin","password":"admin123"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"admin","password":"admin123"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"admin","password":"admin123"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"admin","password":"123456"} | HTTP=200
Resp: 2

POST /login | body={"user":"admin","password":"123456"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"admin","password":"123456"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"admin","password":"123456"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"aquila","password":"aquila"} | HTTP=200
Resp: 2

POST /login | body={"user":"aquila","password":"aquila"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"aquila","password":"aquila"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"aquila","password":"aquila"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"aquilascan","password":"aquilascan"} | HTTP=200
Resp: 2

POST /login | body={"user":"aquilascan","password":"aquilascan"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"aquilascan","password":"aquilascan"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"aquilascan","password":"aquilascan"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"workmed","password":"workmed"} | HTTP=200
Resp: 2

POST /login | body={"user":"workmed","password":"workmed"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"workmed","password":"workmed"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"workmed","password":"workmed"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"wdtp","password":"wdtp80"} | HTTP=200
Resp: 2

POST /login | body={"user":"wdtp","password":"wdtp80"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"wdtp","password":"wdtp80"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"wdtp","password":"wdtp80"} | HTTP=200
Resp: 2

POST /api/login | body={"user":"device","password":"device"} | HTTP=200
Resp: 2

POST /login | body={"user":"device","password":"device"} | HTTP=200
Resp: 2

POST /api/auth | body={"user":"device","password":"device"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"user":"device","password":"device"} | HTTP=200
Resp: 2

POST /api/login | body={"username":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /login | body={"username":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/auth | body={"username":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/v2/login | body={"username":"admin","password":"admin"} | HTTP=200
Resp: 2

POST /api/login | body={"device_id":"WDTP80-001","token":""} | HTTP=200
Resp: 2

POST /login | body={"device_id":"WDTP80-001","token":""} | HTTP=200
Resp: 2

POST /api/auth | body={"device_id":"WDTP80-001","token":""} | HTTP=200
Resp: 2

POST /api/v2/login | body={"device_id":"WDTP80-001","token":""} | HTTP=200
Resp: 2

Evidencia — Cloud Functions, pruebas de payload XML

gcf_xml_probes.txt  ·  52 B  ·  3 líneas

Las Cloud Functions de Workmed (workmed-log/aquilascan y workmed-log/aquilascan-prod) esperan recibir el XML con resultados del examen toxicológico enviado por el WDTP-80. Se probaron distintos payloads XML. HTTP 400 significa que la función existe, recibe el request y lo procesa, pero rechaza el payload por formato incorrecto — no por falta de autenticación. Cualquier actor que conozca el esquema XML correcto (documentado por TSCOM) puede enviar resultados falsos sin ningún token de acceso. HTTP 200 en cualquiera de estas pruebas sería un hallazgo crítico.

=== Pruebas de payload XML ===

--- /aquilascan ---

Pruebas de autenticación por defecto

HTTP 200 = CRITICO

Se enviaron credenciales triviales a todos los endpoints de login sin autenticación previa. HTTP 200 es el resultado de un servidor que no valida credenciales — un sistema seguro devuelve 401 (no autorizado) o 403 (prohibido) ante credenciales inválidas, nunca 200. HTTP 200 a admin/admin puede significar: (a) autenticación no implementada, (b) handler catch-all, o (c) credenciales por defecto realmente activas en producción.

EndpointCredencial probadaHTTPEstadoInterpretación
/api/login {"user":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"admin","password":"123456"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"admin","password":"123456"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"admin","password":"123456"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"admin","password":"123456"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"aquila","password":"aquila"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"aquila","password":"aquila"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"aquila","password":"aquila"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"aquila","password":"aquila"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"aquilascan","password":"aquilascan"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"aquilascan","password":"aquilascan"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"aquilascan","password":"aquilascan"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"aquilascan","password":"aquilascan"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"workmed","password":"workmed"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"workmed","password":"workmed"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"workmed","password":"workmed"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"workmed","password":"workmed"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"wdtp","password":"wdtp80"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"wdtp","password":"wdtp80"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"wdtp","password":"wdtp80"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"wdtp","password":"wdtp80"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"user":"device","password":"device"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"user":"device","password":"device"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"user":"device","password":"device"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"user":"device","password":"device"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"username":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"username":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"username":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"username":"admin","password":"admin"} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/login {"device_id":"WDTP80-001","token":""} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/login {"device_id":"WDTP80-001","token":""} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/auth {"device_id":"WDTP80-001","token":""} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.
/api/v2/login {"device_id":"WDTP80-001","token":""} 200 CRITICO El servidor devolvió HTTP 200 — procesó el request exitosamente. Un sistema con autenticación real debería responder 401 (no autorizado) o 403 (prohibido). HTTP 200 con credenciales inválidas indica ausencia de validación o credenciales por defecto activas.

Cloud Functions — proyecto GCP workmed-log

HTTP 400 = sin auth verificada

Se probaron todas las funciones del proyecto GCP workmed-log en la región Santiago. HTTP 400 no significa "acceso denegado" — significa que la función existe, recibe el request y lo procesa, pero rechaza el body por formato incorrecto. La diferencia crítica: 401/403 = función protegida. 400 = función activa sin token requerido. El protocolo correcto es XML (documentado por TSCOM) — cualquier actor con ese esquema puede enviar resultados falsos de exámenes o consultar datos sin autenticación.

Función GCFHTTPEstadoQué significa
/aquilascan 400 ACTIVA La función existe y procesa el request pero rechaza el formato del body. NO significa que requiere autenticación — significa que el payload XML es incorrecto. Cualquier actor con el esquema XML de TSCOM puede enviar datos reales.
/aquilascan-prod 400 ACTIVA La función existe y procesa el request pero rechaza el formato del body. NO significa que requiere autenticación — significa que el payload XML es incorrecto. Cualquier actor con el esquema XML de TSCOM puede enviar datos reales.

Certificados TLS y versiones de protocolo

Los certificados TLS garantizan que el canal de comunicación está cifrado, pero no garantizan que quien recibe los datos esté autorizado para verlos. Verificar: (1) si el certificado es de una CA confiable y no ha expirado, (2) si el servidor acepta TLS 1.0 o 1.1 — versiones obsoletas vulnerables a POODLE y BEAST que permiten descifrar el XML con resultados toxicológicos en tránsito. TLS 1.2+ con cifrado moderno es el mínimo aceptable para datos de salud bajo Ley 21.719.

Sin datos TLS — re-ejecutar audit_red.sh

Archivos de evidencia

75 archivos
ArchivoContenidoTamaño
✓ update_server/rutas_activas.txt Rutas HTTP activas con status y body preview 6,718 B
✓ update_server/auth_tests.txt Pruebas de credenciales por defecto 3,287 B
✓ update_server/sensitive_paths.txt Respuestas de /db, /backup, /.env, /.git 136 B
✓ gcf/gcf_enumeration.txt Funciones GCF activas 134 B
✓ gcf/gcf_xml_probes.txt Pruebas de payload XML 52 B
✗ gcf/gcf_headers.txt Headers HTTP y CORS
✗ gcf/gcf_project_variants.txt Variaciones de proyecto GCP
✗ tls/tls_audit.txt Certificados TLS
✗ report/dns.txt Resolución DNS
✓ update_server/ipinfo.json Geolocalización IP 273 B

Protocolo XML — AquilaScan WDTP-80

Fuente: TSCOM / SACMED

El dispositivo envía un POST HTTP con el resultado de cada examen en formato XML. El servidor debe responder con el rec_id del registro para confirmar recepción. Sin esa confirmación el dispositivo considera el envío fallido y reintenta.

Ejemplo de payload XML real
<?xml version="1.0" encoding="UTF-8"?>
<record index_id="201" aborted="false" rec_id="3">
  <device lcid="en-us" id="WD2A000015"/>
  <operator rank="1" department="" operator_lastname="" operator_firstname="Supervisor"/>
  <testee signature="" photo="" license="" birthday="null" gender="NA" lastname="" firstname=""/>
  <location latitude="-33.45509" longitude="-70.62161" addr=""/>
  <remarks remark5="" remark4="" remark3="" remark2="" remark1=""/>
  <testinfo detectType="Prueba de saliva" testtype="Fiscalizacion"
            testtime="Wed Apr 22 13:41:00 GMT-03:00 2020" cassette="WELL07T"/>
  <data T2G="" T1G="" T2F="" T1F="" T2E="" T1E="" T2D="" T1D=""
        T3C="" T2C="negativo" T1C=""
        T3B="negativo" T2B="negativo" T1B="negativo"
        T3A="negativo" T2A="negativo" T1A="positivo"/>
  <pic pic="[BASE64_IMAGEN]"/>
</record>
Campos del XML — referencia completa
CampoAtributos claveSignificado
<record> index_id, rec_id, aborted Encabezado del registro. rec_id es el número que el servidor debe devolver para confirmar recepción. aborted indica si el test fue interrumpido antes de completarse.
<device> id, lcid Identificador único del equipo físico (ej. WD2A000015). Es el único mecanismo de trazabilidad del dispositivo — no hay token de autenticación adicional. lcid es el idioma configurado.
<operator> rank, firstname, lastname, department Datos del profesional que tomó la muestra. En Workmed corresponde al técnico o paramédico que opera el WDTP-80. rank indica el nivel de acceso en el dispositivo.
<testee> firstname, lastname, license, birthday, gender, signature, photo Datos personales del trabajador examinado. Puede incluir nombre completo, RUT (campo license), fecha de nacimiento, género y firma digitalizada. Son datos de salud sensibles bajo Ley 21.719. La foto es base64 en el campo photo.
<location> latitude, longitude, addr Coordenadas GPS del punto exacto donde se realizó el examen. Permite verificar que el test ocurrió en el lugar declarado (faena, empresa). Se transmite en cada registro.
<testinfo> detectType, testtype, testtime, cassette detectType: tipo de muestra (saliva, orina, pelo, superficie). testtype: motivo del examen (Fiscalización, Accidente, Pre-ocupacional). cassette: código del cartucho usado (ej. WELL07T) — define qué drogas se detectan y en qué posición del elemento <data>. testtime: timestamp exacto del examen.
<data> T1A–T3G (21 posiciones) Resultados de cada droga. Cada atributo (T1A, T2A, T1B...) corresponde a una posición en el cassette. El valor es "positivo", "negativo" o vacío. La droga en cada posición depende del tipo de cassette — debe estar preconfigurado en el sistema receptor. El dispositivo permite renombrar "negativo" a "No se detecta droga" y "positivo" a "Requiere prueba de laboratorio".
<pic> pic (BASE64) Fotografía del cassette con el resultado físico, codificada en Base64. Sirve como evidencia visual del test y puede incluir la imagen del trabajador según configuración. Puede ser varios KB de datos por examen.
<remarks> / <testentry> remark1-5 / entry1-15 Campos libres de texto configurables por la empresa. Workmed puede usarlos para código de empresa, número de contrato, nombre de faena u otros campos personalizados del proceso de fiscalización.
Estructura de posiciones en <data> — cassette WELL07T
Posición XMLDroga típicaValor posibleImplicancia clínica
T1ATHC (Cannabis/Marihuana)positivo / negativoDetecta cannabinoides. Positivo no implica consumo reciente — puede persistir semanas en pelo.
T2ACOC (Cocaína)positivo / negativoDetecta benzoilecgonina (metabolito). Ventana de detección 2-4 días en orina.
T3AOPI (Opiáceos)positivo / negativoMorfina, codeína, heroína. Puede dar falso positivo con algunos medicamentos.
T1BAMP (Anfetaminas)positivo / negativoAnfetamina y metanfetamina. Medicamentos como Ritalín pueden generar falsos positivos.
T2BBZO (Benzodiacepinas)positivo / negativoClonazepam, diazepam, lorazepam. Muy común en trabajadores con prescripción médica — requiere validación posterior.
T3BMTD (Metadona)positivo / negativoTratamiento de adicciones. Un positivo no implica consumo ilícito.
T2CBAR (Barbitúricos)positivo / negativoFenobarbital y similares. Uso médico frecuente como anticonvulsivante.
T1C–T3GVariable según cassettepositivo / negativo / vacíoPosiciones adicionales configurables: MDMA, PCP, Ketamina, Tramadol, K2/Spice u otras sustancias según el tipo de cassette seleccionado por Workmed.
Implicancia de seguridad: Dado que las Cloud Functions no verifican autenticación por dispositivo, un atacante con acceso al esquema XML podría enviar registros falsos con T1A="negativo" para trabajadores que debieran dar positivo, o inyectar resultados arbitrarios con cualquier device_id. El único mecanismo de trazabilidad es el campo id del tag <device>, que no está validado criptográficamente.