Hay una vulnerabilidad y no la vamos a arreglar: en Node.js descubren cómo hackear casi todo, pero los desarrolladores lo llaman 'una característica de la arquitectura'.

Hay una vulnerabilidad y no la vamos a arreglar: en Node.js descubren cómo hackear casi todo, pero los desarrolladores lo llaman 'una característica de la arquitectura'.

Aún es difícil imaginar la magnitud de los problemas que se avecinan

image

En el ecosistema de Node.js se detectó una vulnerabilidad relacionada con la lógica básica del cliente HTTP, que permite eludir la protección previa contra la separación de peticiones. Martino Spagnolo, conocido como r3verii, publicó un análisis después de que el equipo de Node.js se negara a considerar el problema una violación de su modelo de amenazas. Se trata de un mecanismo que abre la posibilidad de inyección de cabeceras y de formar una segunda petición dentro de la misma conexión.

El problema se remonta a 2018, cuando la vulnerabilidad CVE-2018-12116 permitía inyectar caracteres de control mediante particularidades de la codificación latin1. Entonces los desarrolladores añadieron una comprobación del camino de la petición en http.request, prohibiendo caracteres fuera del rango \u0021—\u00ff. La protección se aplicaba solo en el momento de crear el objeto ClientRequest. Tras eso la propiedad path permaneció como un campo mutable normal sin validación adicional.

La investigación mostró que si se modifica clientRequest.path después de crear la petición, la comprobación ya no se ejecuta. Al formar la cadena HTTP, el método _implicitHeader usa el valor actual de path sin volver a filtrarlo. Como resultado, las secuencias de control \r\n pueden llegar directamente al flujo TCP.

Dependiendo de la carga útil, las consecuencias varían. En el caso más sencillo el atacante inyecta cabeceras HTTP adicionales y suplanta Host o Authorization. Un escenario más serio permite cerrar las cabeceras y añadir un cuerpo de petición, cambiando la semántica de la solicitud original. El caso más peligroso conduce a una división completa de la petición, cuando el servidor recibe dos peticiones HTTP independientes en lugar de una.

El autor comprobó bibliotecas populares y halló siete proyectos con una ventana TOCTOU abierta. Entre ellos node-http-proxy, http-proxy-middleware, superagent, request y @hapi/wreck. La audiencia combinada supera los 160 millones de descargas por semana. El patrón común es el mismo — la biblioteca crea un ClientRequest, luego pasa el objeto a manejadores externos antes de enviar las cabeceras. Si el manejador modifica path en base a datos del usuario, la filtración se evita.

Algunas herramientas evitaron el problema gracias a una arquitectura distinta. axios se apoya en follow-redirects y no expone el ClientRequest interno, got envía las cabeceras antes de exponer el objeto, y undici y el fetch integrado usan su propia implementación de la pila HTTP sin un path mutable.

El equipo de Node.js declaró a través del programa HackerOne que el comportamiento se corresponde con el diseño actual y no se considera una vulnerabilidad. Según su postura, la responsabilidad recae en las bibliotecas que permiten cambiar path después de crear la petición. El autor de la investigación no estuvo de acuerdo con esa evaluación y señaló la escala del ecosistema y la existencia de ejemplos de explotación funcionales.

Como corrección mínima se propone volver a verificar el camino justo antes de formar la cadena de la petición o proteger la propiedad path mediante un setter con validación. Por ahora no se planean cambios en el núcleo; se aconseja a los desarrolladores buscar en el código asignaciones a clientRequest.path y comprobar si los valores provienen de la entrada del usuario.