FlawOpen

flawopen.com/SSRF/SSRF con fetch() en Node.js

¿Node.js fetch() evita la SSRF?

CWE-918: Server-Side Request ForgeryReferencia de seguridad de Node.js
En lenguaje sencillo

No. El fetch() del servidor realiza solicitudes desde el servidor. Si quien llama elige el destino, puede dirigir la solicitud a sistemas accesibles para el servidor pero no para esa persona. Es como pedirle a un mensajero de confianza que entregue un paquete sin comprobar la dirección. La exposición depende de la red, identidad, política de URL y redirecciones.

SSRF (CWE-918)El servidor solicita un destino elegido o influido por un usuario no confiable, cruzando el límite de confianza de red.
Lista de destinos permitidosMapa fijo desde una opción del usuario, como providerId, hasta un origen configurado por la aplicación. Evita aceptar URLs arbitrarias.
Validación de redireccionesUna respuesta puede señalar otro destino. Seguir redirecciones automáticamente puede eludir una validación aplicada solo a la URL inicial.
DNS rebindingUn nombre puede resolver a direcciones distintas. Validar DNS una vez y dejar que el cliente vuelva a resolverlo crea una condición TOCTOU.

Causa raíz: el servidor confía en el destino elegido por el usuario

El fetch() de Node.js es un cliente HTTP general, no una política contra SSRF. No decide a qué redes puede conectarse la aplicación; CORS del navegador no establece ese límite en el servidor. Analizar la URL tampoco basta: un host permitido puede resolver a una dirección prohibida y una respuesta puede redirigir a otro host. Funciones que descargan avatares, webhooks, documentos o vistas previas proporcionados por usuarios pueden exponer este riesgo.

Cómo cruza la solicitud el límite de confianza

Step 1

El usuario influye en una URL

Un endpoint acepta una URL completa o datos suficientes para construirla, por ejemplo, para mostrar una vista previa de imagen.

Step 2

El servidor envía la solicitud

El cliente HTTP utiliza la ruta de red, DNS, proxy e identidad disponibles al proceso del servidor.

Step 3

Una redirección puede cambiar el destino

Fetch sigue redirecciones por defecto. Un destino validado al inicio puede responder con Location hacia un host que la aplicación debía bloquear.

Step 4

La respuesta puede exponer datos accesibles

Si la política y la red lo permiten, pueden alcanzarse servicios internos o metadatos de nube. Depende del entorno; no ocurre en toda llamada fetch.

Patrones Node.js vulnerable y más seguro

Vulnerable
// No solicites una URL arbitraria proporcionada por quien llama.
const response = await fetch(userProvidedUrl);
Más seguro
// El usuario elige una clave, nunca un destino de red.
const destinations = new Map([
  ["status", new URL("https://status.example/")],
  ["docs", new URL("https://docs.example/")],
]);

const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");

const response = await fetch(target, {
  redirect: "error",
  signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");

Si los usuarios deben enviar URLs

Prefiere aceptar un identificador de proveedor y construir la solicitud desde un mapa fijo de destinos. Si son imprescindibles URLs públicas arbitrarias, permite solo esquemas y puertos necesarios; rechaza user-info, loopback, IP privadas, link-local y otros destinos IPv4/IPv6 prohibidos; valida todas las direcciones resueltas y asegura que la conexión use una dirección validada sin otra resolución no comprobada. Desactiva redirecciones automáticas o valida cada salto. Aplica reglas de salida de red independientes, incluidos los endpoints de metadatos como 169.254.169.254 y la dirección IPv6 habilitada. Limita tiempo, tamaño de respuesta y concurrencia; no reenvíes credenciales al host consultado.

Lista de prevención de SSRF

Preguntas frecuentes

¿Basta con bloquear localhost e IP privadas?

No. Redirecciones, variantes IPv4/IPv6, DNS rebinding, proxies y carreras entre resolución y conexión pueden eludir comprobaciones simples. Prefiere una lista permitida de destinos. Si aceptas destinos arbitrarios, valida cada dirección y haz que la conexión use ese resultado; aplica la misma política en la salida de red.

¿Exigir IMDSv2 elimina la SSRF?

No. IMDSv2 requiere un flujo con token y reduce algunas exposiciones, pero la SSRF puede alcanzar otros servicios internos o endpoints de metadatos según la configuración. Mantén los controles de destino y salida.

Fuentes primarias

Explora temas de seguridad y análisis de incidentes relacionados:Directorio completo de seguridad →
Véase también Falsificación de peticiones del lado del servidor (SSRF, CWE-918): cómo funciona y cómo evitarla en cada lenguaje — flawopen.com SSRF y metadatos cloud: riesgos y defensa Bots de PR con IA: prevenir SSRF — flawopen.com