Envío de registros, alertas y datos de telemetría a través de un diodo de datos

Descubre cómo
Utilizamos inteligencia artificial para traducir el sitio web y, aunque nos esforzamos por garantizar la precisión, es posible que las traducciones no sean siempre 100 % exactas. Agradecemos tu comprensión.

Descubrimiento técnico de las vulnerabilidades CVE-2025-23061 y CVE-2024-53900 de Mongoose

Por OPSWAT
Comparte esta publicación

Mongoose es una biblioteca de modelado de datos orientada a objetos (ODM) para MongoDB que simplifica las interacciones con la base de datos en aplicaciones Node.js. Al ofrecer una solución basada en esquemas, Mongoose permite asignar objetos JavaScript a documentos de MongoDB, actuando como una capa de abstracción que ayuda a estructurar los datos para facilitar su gestión y validación. Con características como middleware para la ejecución de lógica personalizada y un sistema intuitivo de construcción de consultas, Mongoose mejora la eficiencia del trabajo con MongoDB. Mongoose, descrito como «un elegante modelado de objetos MongoDB para Node.js», ha obtenido 27 000 estrellas en GitHub, lo que refleja su uso generalizado y el reconocimiento entre los desarrolladores.

El programa OPSWAT y la detección de vulnerabilidades críticas

El Programa de Becas de Posgrado en Ciberseguridad de InfraestructurasOPSWAT , con sede en Vietnam, ofrece a los estudiantes de posgrado experiencia práctica en la protección de infraestructuras críticas. Como parte de este programa, los becarios tienen la oportunidad de analizar y resolver vulnerabilidades de ciberseguridad, colaborando con OPSWAT para hacer frente a retos reales en ámbitos como la detección de malware, la seguridad de archivos y la prevención de amenazas. 

Durante el programa OPSWAT , los participantes investigan y reproducen de forma sistemática vulnerabilidades CVE conocidas en diversos productos, bibliotecas y sistemas operativos. Como parte de esta iniciativa, Dat Phung —uno de nuestros distinguidos becarios— decidió examinar Mongoose debido a su amplia adopción en entornos de producción. En noviembre de 2024, descubrió una vulnerabilidad crítica en Mongoose mientras realizaba un análisis en profundidad de la biblioteca. La vulnerabilidad permitía a un atacante explotar el valor $where, lo que podía dar lugar a la ejecución remota de código (RCE) en el servidor de aplicaciones Node.js. Tras informar rápidamente del problema a Mongoose, se publicó un parche como parte de la versión 8.8.3, y el CVE-2024-53900 se dio a conocer en la Base de Datos Nacional de Vulnerabilidades (NVD).

Cronología de CVE-2024-53900 y CVE-2025-23061

  • 7 de noviembre de 2024: Dat Phung detectó una vulnerabilidad crítica en Mongoose y envió un informe de seguridad a Snyk. 
  • 26 de noviembre de 2024: Mongoose lanzó la versión 8.8.3 para abordar y corregir esta vulnerabilidad. 
  • 2 de diciembre de 2024: La Base de Datos Nacional de Vulnerabilidades (NVD) publicó el CVE-2024-53900 para esta vulnerabilidad. 
  • 17 de diciembre de 2024: Tras analizar el parche 8.8.3 de Mongoose, Dat Phung descubrió una vulnerabilidad que seguía permitiendo la ejecución remota de código (RCE). Se envió un informe de seguridad detallado a Tidelift. 
  • 13 de enero de 2025: Mongoose lanzó la versión 8.9.5, que incluía un parche mejorado que solucionaba de forma efectiva la vulnerabilidad. 
  • 15 de enero de 2025: La Base de Datos Nacional de Vulnerabilidades (NVD) dio a conocer oficialmente el CVE-2025-23061, haciendo hincapié en la gravedad de la vulnerabilidad recién identificada.

El método Populate() de Mongoose

Mongoose también ofrece una función muy útil llamada `populate()` que mejora la capacidad de trabajar con relaciones entre documentos. Aunque las versiones de MongoDB ≥ 3.2 cuentan con el operador de agregación `$lookup` para realizar uniones, la función `populate()` de Mongoose ofrece una alternativa más potente para sustituir automáticamente una referencia por los datos correspondientes de los documentos relacionados. Esto resulta especialmente útil para gestionar relaciones entre diferentes colecciones de MongoDB, como cuando un documento hace referencia a otro mediante su `_id`. [2] 

Código JavaScript que define un esquema de Mongoose para un autor con los campos «nombre», «edad» y «biografía»
Esquema de autores
Código JavaScript que define un esquema de Mongoose para libros, incluyendo el título, la descripción, el precio y las referencias del autor
Esquema de libros
Fragmento de código JavaScript para una ruta de Node.js que recupera los detalles de un libro y rellena los campos de autor o reseña
Aplicación Node.js

Al definir un esquema en Mongoose, se puede configurar un campo para que haga referencia a otro modelo utilizando la opción `ref`. A continuación, se utiliza el método populate() para sustituir el campo al que se hace referencia (un ObjectId) por el documento completo del modelo relacionado. Por ejemplo, en una aplicación de librería, el campo author del bookSchema hace referencia al documento Author, y el campo review hace referencia al documento Reviews. El método populate() permite a los desarrolladores sustituir el campo author (que es un ObjectId) por el documento completo Author al consultar el modelo book.

El método `populate()` permite a los desarrolladores sustituir el campo «author» (que es un ObjectId) por el documento «Author» completo al consultar el modelo «book »:

Representación JSON de un documento de MongoDB que almacena los detalles de un libro sin información detallada sobre el autor
No utilizar `populate()`
Representación JSON de un documento de MongoDB con los datos del autor ampliados mediante la función «populate»
Uso de populate()

Además, el método `populate()` de Mongoose admite consultas personalizadas para definir qué documentos relacionados se recuperan y cómo se obtienen. Propiedades como `match` y `options` permiten a los desarrolladores filtrar, ordenar, limitar y omitir documentos relacionados, lo que ofrece una gran flexibilidad a la hora de recuperar datos.

Código JavaScript que muestra una consulta personalizada que utiliza la función «populate» de Mongoose para filtrar autores por edad
Consulta personalizada en `populate()` en Mongoose

Análisis de CVE-2024-53900

En el marco del programa de becas de posgrado OPSWAT , mientras analizaba Mongoose para reproducir vulnerabilidades CVE conocidas, Dat Phung llevó a cabo un análisis exhaustivo del funcionamiento interno del método `populate()`, que desempeña un papel fundamental en la gestión de las relaciones entre los documentos de MongoDB. El método `populate()` admite tanto argumentos de tipo cadena como de tipo objeto, y los desarrolladores pueden utilizar la opción `match` para aplicar filtros específicos a los datos que se recuperan:

Código JavaScript que muestra el uso del operador $where para filtrar autores por edad en una consulta

En el ejemplo anterior, la opción «match» es un objeto de filtro que puede incluir operadores de consulta de MongoDB, tal y como se detalla en «Operadores de consulta y proyección» del Manual de MongoDB v8.0. Un operador destacado es «$where», que permite la ejecución de JavaScript directamente en el servidor de MongoDB. Sin embargo, esta ejecución en el servidor de MongoDB está limitada, ya que solo admite operaciones y funciones básicas.

Tabla con las funciones y propiedades de JavaScript disponibles para las operaciones map-reduce de MongoDB

Dat Phung llevó a cabo un análisis en profundidad del código fuente de Mongoose para comprender el flujo de trabajo del método `populate()`. Determinó que, una vez que la aplicación invoca el método `populate()` en el modelo, se activa la función `populate()`. Dentro de esta función, Mongoose llama a la función _execPopulateQuery() , que ejecuta la consulta con el operador $where en el servidor de MongoDB. Posteriormente, se recuperan todos los documentos de la colección externa para su población en los siguientes pasos.

Captura de pantalla de una sesión de depuración en VS Code en la que se analiza la ejecución de una consulta «populate» de Mongoose

Tras recuperar los datos de MongoDB, Mongoose ejecuta la función de llamada de retorno _done(), que a su vez llama a _assign() para preparar los datos antes de «unir» los dos modelos mediante la función assignVals().

Una sesión de depuración en VS Code en la que se muestra resaltado el código JavaScript relacionado con la consulta $where en Mongoose

La vulnerabilidad puede surgir cuando los datos recuperados se procesan mediante la función `assignVals()` de Mongoose. Esta función comprueba si la opción `match` es una matriz y, en caso afirmativo, pasa cada operador a la función `sift()`. La función `sift()` , que se importa desde una biblioteca externa del mismo nombre, procesa estas consultas de forma local en el servidor de la aplicación. Este procesamiento local supone un riesgo de seguridad, especialmente al gestionar entradas controladas por el usuario.

Una sesión de depuración de VS Code que muestra las asignaciones de variables dentro de una función de JavaScript

Para profundizar en el análisis, Dat Phung modificó los valores de la opción «match» con el fin de garantizar que se cumplieran las condiciones, lo que provocó la ejecución de la función «sift()» para realizar un análisis más detallado del flujo de datos.

Un fragmento de código JavaScript que muestra una consulta de Mongoose con una condición de filtro $where

Una vez establecida la condición, el operador $where se pasó a continuación a la función sift().

Una sesión de depuración de VS Code en la que se muestran los valores filtrados en una función de JavaScript

La biblioteca sift es una utilidad ligera de JavaScript diseñada para filtrar y consultar conjuntos de datos, como matrices u objetos JSON, utilizando una sintaxis similar a la de MongoDB. Según la documentación oficial, «Sift es una pequeña biblioteca que permite utilizar consultas de MongoDB en JavaScript». La función sift() evalúa operaciones de filtrado similares a las de MongoDB en el servidor de la aplicación en lugar de en el servidor de la base de datos, lo que puede exponer al sistema a importantes riesgos de seguridad al procesar entradas no fiables.

Un sencillo fragmento de código JavaScript que utiliza Sift.js para filtrar una matriz de objetos según criterios de edad
Un ejemplo de código Sift

Continuando con su análisis, nuestro becario detectó un problema en la función `createDefaultQueryTester() ` de la biblioteca `sift`. Esta función convierte cada operación del array `match` en funciones JavaScript ejecutables, que luego se utilizan para filtrar y procesar los datos de los documentos de MongoDB de forma local. Para ello, `createDefaultQueryTester()` invoca la función `createNamedOperation()`, pasando como argumentos operaciones como `$where` del array `match`. 

Una sesión de depuración en VS Code centrada en las operaciones de consulta y la ejecución de funciones

Para cada operación de la matriz de coincidencias, createNamedOperation comprueba si la operación es compatible y, a continuación, la pasa a la función correspondiente.

Una sesión de depuración de JavaScript en la que se muestran operadores de consulta como $where, $eq y $exists

Si la operación es $where, se genera una función JavaScript utilizando el valor sin procesar «params», que se deriva del operador $where en la matriz de coincidencias y puede ser controlado por el usuario.

Un fragmento de código JavaScript resaltado que muestra la ejecución de funciones cuando la Política de Seguridad de Contenidos (CSP) está activada

CVE-2024-53900: Detalles de la vulnerabilidad

Aunque MongoDB limita la ejecución de funciones JavaScript a través de la operación $where, tal y como se ha analizado anteriormente, la función sift() permite ejecutar estas funciones sin tales restricciones. Esta falta de validación y restricción de las entradas supone una importante vulnerabilidad de seguridad, ya que el valor «params» —controlado directamente por la entrada del usuario— puede ser objeto de abuso, lo que podría dar lugar a ataques de inyección de código. Para examinar este problema con mayor detalle, Dat Phung elaboró la siguiente consulta:

Fragmento de código JavaScript que muestra una consulta de Mongoose en la que se utiliza la condición $where con una ejecución de función potencialmente insegura

Al principio, la consulta no pudo ejecutar otro proceso, lo que provocó el siguiente error:

Un registro de errores de MongoDB que muestra un fallo en la ejecución del servidor debido a una referencia global no definida

Este error indica que Mongoose intenta ejecutar la operación $where en el servidor de MongoDB antes de pasar el control a la función sift(). Sin embargo, debido a las restricciones que se aplican a las funciones de JavaScript en la cláusula $where de MongoDB, se produce un error que impide que se ejecute la consulta. Como consecuencia, Mongoose detiene el proceso antes de que pueda llegar a la función sift() .

Para sortear esta limitación, nuestro compañero aprovechó la variable «global» presente en el servidor de aplicaciones, que no existe en el servidor de MongoDB. Este enfoque le permitió eludir la restricción del servidor de MongoDB y hacer que la consulta llegara a la función sift():

Una pantalla de ordenador en la que se lee el texto «el código no funciona», lo que pone de manifiesto un problema en el proceso de programación

Con este valor, cuando Mongoose ejecuta la operación $where en MongoDB, la ausencia de la variable «global» hace que el operador ternario (typeof global != "undefined" ?global.process.mainModule.constructor._load("child_process").exec("calc") : 1)devuelva 1, lo que evita que MongoDB genere un error. En consecuencia, la consulta se ejecuta en el servidor de MongoDB sin problemas.

Sin embargo, cuando ese mismo valor llega a la función `sift()`, que se ejecuta en el servidor de aplicaciones donde está disponible la variable «global», se activa la creación de la siguiente función:

Una pantalla monocromática en la que aparece la frase «hello world» en negrita

Prueba de concepto de ejecución remota de código (RCE)

En el ejemplo de aplicación que se ofrece al principio del blog, si un atacante enviara la siguiente solicitud, podría llevar a cabo con éxito un ataque de ejecución remota de código (RCE):

Pantalla en blanco y negro en la que aparece destacado el texto «The New York Times» en letra negrita
Diagrama que ilustra los detalles técnicos de las vulnerabilidades CVE de Mongoose, en el que se muestran el flujo de datos y los puntos de brecha de seguridad

El vídeo muestra la demostración de concepto de la vulnerabilidad CVE-2024-53900, que afecta a las versiones de Mongoose anteriores a la 8.8.3, las cuales carecen de una validación adecuada de las entradas para evitar el uso indebido del operador $where junto con la biblioteca sift.

Solución incompleta y CVE-2025-23061

A raíz del informe de seguridad de Dat Phung, Mongoose lanzó un parche destinado a resolver la vulnerabilidad identificada anteriormente (CVE-2024-53900) antes de que se hiciera pública. El parche en cuestión (Automattic/mongoose@33679bc) añadió una comprobación para impedir el uso de $where dentro de la propiedad match pasada a la función populate().

Este fragmento de código comprueba si la propiedad «match» pasada a la función «populate()» es una matriz. Si lo es, el código recorre cada objeto de la matriz para comprobar si contiene el operador «$where ». Si se detecta «$where», se genera un error, lo que impide que la carga maliciosa se propague a la función «sift()», que supone un riesgo.  

En consecuencia, la carga útil que aprovecha la vulnerabilidad CVE-2024-53900 no supera esta comprobación porque un objeto de la matriz «match» contiene «$where», lo que impide que llegue a la función «sift()».

Aunque esta actualización bloquea correctamente el uso directo de $where dentro de un único nivel de anidamiento, no detecta $where cuando se incluye dentro de un operador $or, una estructura que tanto MongoDB como la biblioteca sift admiten plenamente.

MongoDB admite el operador $or
La biblioteca Sift admite el operador $or

Como consecuencia, un atacante puede anidar $where dentro de $or para eludir la comprobación de un solo nivel del parche. Dado que Mongoose solo inspecciona las propiedades de primer nivel de cada objeto del array «match», la carga útil de elusión pasa desapercibida y acaba llegando a la biblioteca «sift», lo que permite la ejecución remota de código maliciosa.

Código malicioso utilizado para eludir la corrección en Mongoose 8.8.3

Demostración de concepto para CVE-2025-23061

Para ilustrar el carácter incompleto de la corrección, Dat Phung volvió a compilar la aplicación de ejemplo utilizando una versión de Mongoose 8.9.4 (posterior a la 8.8.3). Al anidar $wheredentro de una cláusula $or, un atacante puede eludir con éxito la comprobación y lograr la ejecución de código remoto (RCE).

El exploit de prueba de concepto muestra cómo se puede aprovechar la vulnerabilidad CVE-2025-23061 en versiones de Mongoose anteriores a la 8.9.5, lo que permite a un atacante ejecutar código arbitrario en el servidor:

Medidas de mitigación y orientación

Para mitigar las vulnerabilidades que hemos comentado anteriormente, asegúrese de que su sistema esté actualizado a la última versión de Mongoose.

MetaDefender Core su motor SBOM, puede detectar esta vulnerabilidad

OPSWAT MetaDefender Core, equipado con capacidades avanzadas de SBOM (Software de materialesSoftware ), permite a las organizaciones adoptar un enfoque proactivo a la hora de abordar los riesgos de seguridad. Al analizar las aplicaciones de software y sus dependencias, MetaDefender Core vulnerabilidades conocidas, como CVE-2024-53900 y CVE-2025-23061, dentro de los componentes enumerados. Esto permite a los equipos de desarrollo y seguridad priorizar las tareas de aplicación de parches, mitigando los posibles riesgos de seguridad antes de que puedan ser explotados por actores maliciosos. 

A continuación se muestra una captura de pantalla de CVE-2024-53900 y CVE-2025-23061, que fueron detectadas por MetaDefender Core SBOM:

Además, las vulnerabilidades CVE también pueden detectarse mediante MetaDefender Software Supply Chain, que aprovecha MetaDefender Core SBOM para identificar estas vulnerabilidades.

¡Mantente al día con OPSWAT!

Regístrate hoy mismo para recibir las últimas novedades de la empresa, historias, información sobre eventos y mucho más.