Cómo corregir una vulnerabilidad de ejecución remota de código en EJS
Tim Kadlec
30 de noviembre de 2016
0 minutos de lecturaEsta semana agregamos a nuestra base de datos de vulnerabilidades una vulnerabilidad de ejecución remota de código en el paquete EJS.
EJS (Embedded JavaScript Templates) es un motor de plantillas de JavaScript rápido, sencillo y muy popular. EJS ofrece varias opciones para renderizar una plantilla. Dos de ellas, render y renderFile, son bastante similares; la única diferencia es que render espera una cadena de texto como plantilla, mientras que renderFile espera la ruta a un archivo de plantilla. Ambos métodos también aceptan argumentos para los datos y un conjunto opcional de opciones de configuración. El método renderFile también acepta una función de devolución de llamada.
Ambos métodos también permiten combinar los datos y las opciones en un solo objeto.
La vulnerabilidad
El método abreviado puede parecer más sencillo, pero combinar los datos y las opciones puede propiciar errores con el tiempo. Si eso no basta para convencerte de evitarlo, aquí tienes una razón de peso: el método abreviado puede exponer tu aplicación a una vulnerabilidad de ejecución remota de código.
Las plantillas de EJS que compilas pueden incluir otros archivos mediante una directiva include.
De forma predeterminada, estas inclusiones se resuelven en relación con la plantilla. Si la plantilla está en la carpeta templates, EJS buscará el archivo que debe incluir en templates/path/to/include.
Una de las opciones de configuración disponibles es root, que te permite cambiar la ubicación predeterminada desde la que se obtienen esas inclusiones.
Esto no representa un problema cuando las opciones se pasan como un argumento independiente, pero sí cuando se combinan con los datos en un solo objeto. Si el método transmite una lista de datos proporcionados por el usuario, un atacante también podría interceptar e inyectar una opción root .
Al pasar la directiva root en la línea anterior, todas las inclusiones se obtendrían de /bad/root en lugar de la ruta prevista, lo que permitiría ejecutar código de forma remota.
Poder configurar la raíz puede ser útil para quienes desarrollan con el motor EJS, pero permitir que se configure en un objeto junto con datos del usuario representa un grave riesgo de seguridad. El desarrollador podría tomar algunas medidas para sanitizar la entrada, pero el motor sería inseguro de forma predeterminada.
Nuestro equipo de seguridad encontró el problema y lo divulgó el 27 de noviembre. El responsable del proyecto, Matthew Eernisse, preparó una solución sencilla que bloquea la opción root para impedir que se incluya junto con los datos del usuario.
A menudo, las vulnerabilidades siguen sin corregirse mucho tiempo después de su divulgación inicial. De hecho, quizá recuerdes la vulnerabilidad XSS en Marked, que tardó más de un año en corregirse. Por suerte, esta vez no fue así. Gracias a la rapidez excepcional de Matthew, la vulnerabilidad pasó de divulgarse a corregirse en solo un día. La versión 2.5.3 de EJS, publicada el 28 de noviembre, incluye la corrección.
Cómo corregirla
Si le pediste a Snyk que monitoreara tu proyecto y este usa EJS, es probable que ya hayas recibido una alerta sobre el problema. Puedes resolver la vulnerabilidad usando la integración de GitHub para generar una solicitud de cambios desde tu panel o ejecutando snyk wizard desde la interfaz de línea de comandos. En ambos casos, Snyk identificará el problema y te indicará que actualices el paquete EJS a la versión más reciente.
Si no usas Snyk —está bien, igual te queremos—, puedes resolver el problema actualizando manualmente a la versión más reciente de EJS. Asegúrate también de revisar todas tus dependencias. Si alguna incluye el paquete EJS, no aparecerá en tu archivo package.json y actualizarlo puede ser un proceso mucho más complejo.
Empieza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.