Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/squeeze440/inference-gateway-poc
Análisis de VulnerabilidadesExplotaciónSeguridad WebPruebas de PenetraciónAutenticaciónSeguridad de APIs
GitHubsqueeze440/inference-gateway-poc

inference-gateway-PoC

PoC — las solicitudes de origen cruzado reutilizan la clave API del proveedor configurada en inference-gateway (GHSA-5293-fcm6-fh8v, CVE-2026-87009, CVSS 5.4).

Ver Repositorio
hace 14h 24mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

inference-gateway: aviso de seguridad

InvestigadorDostxodjayev Abdullox (@squeeze440)
AvisoGHSA-5293-fcm6-fh8v
CVECVE-2026-87009
CVSS 3.15.4 (Medio) — CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L
DebilidadCWE-352, CWE-306, CWE-346
EstadoCorregido en v0.46.0

Resumen: inference-gateway se enlaza a 0.0.0.0 y distribuye la autenticación deshabilitada (AUTH_ENABLED=false) por defecto, y su ruta de paso directo ANY /proxy/:provider/*path elimina incondicionalmente cualquier cabecera Authorization proporcionada por el llamador y la reemplaza con la propia clave de API del proveedor configurada en el servidor por el operador del gateway antes de reenviarla al upstream, sin política CORS y sin protección CSRF de ningún tipo, lo que permite que cualquier página web que visite el navegador de una víctima impulse silenciosamente solicitudes facturadas a LLM a través de la propia cuenta de OpenAI/Anthropic/etc. de la víctima.

Producto: inference-gateway/inference-gateway — gateway LLM autoalojado y nativo de la nube (Go, Gin).

Versión probada: commit 6677da6afd0a606899f833c2351635edeef386f5 (main, 2026-08-04). Afectadas: <= 0.45.0.

Detalles

Tres hechos independientes se combinan en el fallo.

1. La autenticación está desactivada y el enlace es público por defecto. config/config.go:77 — AuthConfig.Enabled es false por defecto. config/config.go:94 — ServerConfig.Host es 0.0.0.0 por defecto. Con la autenticación deshabilitada, NewOIDCAuthenticatorMiddleware (api/middlewares/auth.go:27-30) devuelve OIDCAuthenticatorNoop, cuyo Middleware() (api/middlewares/auth.go:48-52) es un paso directo puro. No hay ninguna comprobación de identidad por solicitud en ninguna ruta en este modo. El quickstart examples/docker-compose/basic/docker-compose.yml publica 8080:8080 sin establecer AUTH_ENABLED, por lo que la ruta de inicio documentada produce exactamente esta configuración.

2. /proxy/:provider/*path siempre inyecta la propia clave del proveedor del operador. api/routes.go:102-131 (ProxyHandler) llama a applyProviderAuth, api/routes.go:287-312:

root@kitploit:~
func applyProviderAuth(req *http.Request, provider core.IProvider) error {
	req.Header.Del("Authorization")          // caller's own Authorization header is discarded
	token := provider.GetToken()             // the operator's configured key (env var, e.g. OPENAI_API_KEY)
	switch provider.GetAuthType() {
	case constants.AuthTypeBearer:
		req.Header.Set("Authorization", "Bearer "+token)
	...

No existe ninguna ruta de código en la que se utilice la propia credencial del llamador; el diseño siempre sustituye la clave configurada del gateway. Combinado con el hecho 1, un llamador no autenticado obtiene la clave real del operador adjunta de forma gratuita.

3. No existe ninguna política CORS ni protección CSRF en ningún lugar de la cadena de middleware. cmd/gateway/main.go:271 construye el router con gin.New() (sin middleware por defecto); la cadena (:273-290) es otel → logger → telemetry → OIDC auth → guardrails → MCP. go.mod/go.sum no contienen ningún paquete CORS. Nunca se envía la cabecera Access-Control-Allow-Origin. El manejador del proxy no necesita ninguna cabecera personalizada ni un Content-Type no seguro para CORS para funcionar (reenvía el cuerpo sin procesar y luego sobrescribe el Content-Type de salida a application/json en api/routes.go:254), por lo que un fetch() cross-origin "simple" (Content-Type: text/plain, sin cabeceras personalizadas) es enviado por el navegador sin preflight. La solicitud facturada del lado del servidor se completa independientemente de la aplicación de CORS del lado de lectura del navegador.

Efecto neto: cualquier origen que visite el navegador de una víctima, mientras el gateway sea accesible desde ese navegador (loopback, LAN o público si el operador siguió el patrón de publicación documentado 8080:8080), puede impulsar finalizaciones de chat arbitrarias elegidas por el atacante a través de la cuenta real del proveedor del operador, con cero autenticación y sin ninguna indicación visible para el usuario.

Prueba de concepto

Confirmado dinámicamente de extremo a extremo con un navegador Chrome real realizando una solicitud cross-origin genuina entre dos orígenes de loopback distintos (gateway en 127.0.0.1, página del atacante en 127.0.0.2). Véase poc/:

  • poc/attacker_site/attack.html — la página exacta servida desde el origen del atacante; su única acción al cargar es un fetch() a /proxy/openai/chat/completions.
  • poc/mock_upstream.py — sustituye a api.openai.com, registra la cabecera Authorization, el Origin y el cuerpo que recibe.
  • poc/README.md — pasos completos de ejecución.

Observado: la solicitud cross-origin del navegador (Origin: http://127.0.0.2:8000) llegó al upstream simulado portando Authorization: Bearer sk-proj-VICTIM-REAL-BILLED-KEY-... y el cuerpo elegido por el atacante {"messages":[{"role":"user","content":"CSRF-DRIVEBY-MARKER-8271"}]} — la página del atacante nunca poseyó, vio ni le fue solicitada ninguna credencial. La inspección de red del navegador confirmó que POST http://127.0.0.1:8081/proxy/openai/chat/completions [200] se disparó desde la página 127.0.0.2:8000. La evidencia completa impulsada por el navegador (registro de red, captura de pantalla) está adjunta a GHSA-5293-fcm6-fh8v.

Impacto

Cualquier operador que ejecute inference-gateway con su configuración predeterminada documentada tiene su(s) clave(s) de API del proveedor configurada(s) utilizables por cualquier página web accesible a un navegador que pueda alcanzar el puerto del gateway, sin credencial, cookie ni posición de red especial más allá de "poder enviar una solicitud HTTP a la dirección del gateway". Concretamente: consumo no autorizado de facturación/cuota en la propia cuenta del proveedor del operador, impulsado ciegamente por cualquier sitio web de terceros, anuncio o página comprometida que el operador (o cualquier persona en la misma LAN) tenga abierta mientras el gateway esté en ejecución. El navegador bloquea que el atacante lea la salida del modelo (sin cabeceras CORS), por lo que se trata de una transacción forzada ciega, no de una primitiva de lectura.

Debilidades

  • CWE-352 Cross-Site Request Forgery — una acción costosa que cambia el estado realizada mediante una solicitud cross-origin emitida por el navegador sin token anti-CSRF, sin comprobación de Origin/Sec-Fetch-Site y sin restricción CORS.
  • CWE-306 Falta de autenticación para función crítica — todas las rutas excepto /health tienen cero comprobación de identidad por solicitud cuando AUTH_ENABLED=false, el valor predeterminado documentado.
  • CWE-346 Error de validación de origen — sin política CORS ni lista de orígenes permitidos en ningún lugar de la cadena de middleware.

Remediación

Corregido en v0.46.0 (el mantenedor reforzó los valores predeterminados). Medidas recomendadas:

  1. Requerir una cabecera personalizada no incluida en la lista segura en /proxy/:provider/*path (y otras rutas que cambian el estado), lo que fuerza un preflight CORS para los llamadores cross-origin y da al gateway un lugar donde aplicar una lista de orígenes permitidos. Esto cierra el bypass de "solicitud simple" sin requerir que la autenticación esté habilitada.
  2. Cambiar el valor predeterminado de SERVER_HOST de 0.0.0.0 a 127.0.0.1, requiriendo una adhesión explícita a una interfaz más amplia (como hizo Ollama para la misma clase de fallo).
  3. Emitir una advertencia de inicio, o negarse a iniciar, cuando AUTH_ENABLED=false y SERVER_HOST no sea loopback.
  4. Documentar el riesgo en README.md / Configurations.md.

Crédito

Dostxodjayev Abdullox (@squeeze440)

Descargar herramienta