Node.js corrige una grave vulnerabilidad que permitía bloquear aplicaciones
Node.js ha publicado actualizaciones para una vulnerabilidad de alta gravedad que los atacantes podrían aprovechar para corromper el proceso y provocar comportamientos inesperados. Por ejemplo, bloqueos de aplicaciones y ejecución de código potencialmente remoto (RCE).
La vulnerabilidad use-after-free, identificada como CVE-2021-22930, tiene que ver con la forma en que se administran las transmisiones HTTP2 en el lenguaje.
Node.js ofreció soluciones inmediatas para la vulnerabilidad
Esta semana, Node.js lanzó las correcciones para la vulnerabilidad de alta gravedad use-after-free, identificada como CVE-2021-22930.
Las vulnerabilidades deuse-after-free (uso después de la liberación) ocurren cuando un programa intenta acceder a un recurso en una dirección de memoria que se ha liberado previamente y ya no contiene el recurso.
Esto puede provocar daños en los datos o comportamientos inesperados como fallas de la aplicación o incluso ejecución remota de código (RCE) en algunos casos.
Las correcciones llegaron en la última versión 16.6.0 de Node.js y también se retroportaron a las versiones 12.22.4 (LTS) y 14.17.4 (LTS).
La corrección que se muestra a continuación se ha aplicado en varias ramas de Node.js para eliminar la vulnerabilidad de uso después de la liberación:
El mérito por reportar esta vulnerabilidad se le ha atribuido a Eran Levin.
El lanzamiento de la actualización abrupta para una vulnerabilidad de alta gravedad se explica por el hecho de que las discusiones sobre la vulnerabilidad ya eran públicas:
“Normalmente nos gusta avisar con anticipación y proporcionar versiones en las que los únicos cambios son correcciones de seguridad. Sin embargo, dado que esta vulnerabilidad ya era pública, sentimos que era más importante obtener esta corrección rápidamente en versiones que ya estaban planificadas”. Esto según lo anunció Red Hat a través de Daniel Bevenius, ingeniero de software principal y miembro del Comité Directivo Técnico (TSC) de NodeJS.
Vulnerabilidad activada al abortar conexiones HTTP
La vulnerabilidad se activó en los casos en que Node.js analizó las tramas entrantes RST_STREAM, sin código de error o un código de cancelación.
En aplicaciones basadas en el protocolo HTTP/2, la trama RST_STREAM es enviada por cualquiera de los hosts con la intención de terminar una conexión.
Por ejemplo, en una arquitectura cliente-servidor, si una aplicación cliente desea finalizar la conexión, enviaría una trama RST_STREAM al servidor.
Al recibir la trama, el servidor dejará de responder al cliente y eventualmente abortará la conexión. Cualquier trama de “DATA” que el servidor estuviera a punto de enviar al cliente, podría descartarse.
Pero en el caso de versiones vulnerables de Node.js, cuando el servidor recibía una trama RST_STREAM con un código de “cancelación” (nghttp2_cancel), el receptor intentaba “forzar la purga” de los datos recibidos.
Y, una vez hecho esto, una devolución de llamada automática ejecutaría adicionalmente la función “cerrar”, intentando liberar la memoria por segunda vez, que ya se había liberado en el último paso.
Bloqueo de la aplicación
Y esto daría como resultado un bloqueo de la aplicación o un comportamiento errático debido a un error de doble liberación (double-free error).
Esta falla, que antes se consideraba un “error” en lugar de una vulnerabilidad explotable, fue reportado el 8 de junio de 2021. El reporte lo realizó Matthew Douglass en un hilo público.
Douglass pudo reproducir el error el 100% del tiempo en su sistema, lo que provocó fallas en la aplicación.
La discusión se prolongó durante más de un mes entre los colaboradores de Douglass y Node.js:
“El problema parece deberse al manejo de la trama RST_STREAM recibida sin código de error y cancelando el código de error”.
“Node intenta forzar el proceso y purgar cualquier dato existente para la secuencia. Esto hace que nghttp2 cierre la secuencia ya destruida, lo que provoca el error sw doble liberación”, respondió el usuario de GitHub kumarak.
En cambio, la solución implementada agrega el flujo entrante de tramas RST_STREAM a una cola y procesa la cola una vez que es seguro hacerlo. Esto evitaría errores de doble liberación o de uso después de la liberación.
Los usuarios de Node.js deben actualizar a la última versión 16.6.0, o a una versión actualizada parcheada.