
Blog sobre CVE-2026-59827, deserialización insegura de salida de consultas H2
GHSA-w95f-x9v9-wv36 | CVSS 9.9 Crítico | CWE-502: Deserialización de datos no confiables
CVE-2026-59827 es una vulnerabilidad crítica de ejecución remota de código en Metabase, la popular plataforma de inteligencia empresarial y análisis de datos de código abierto. El fallo surge de cómo Metabase maneja los resultados de consultas devueltos por una conexión a la base de datos H2. Cuando una consulta SQL nativa contra una fuente H2 devuelve una columna tipificada como OTHER, Metabase deserializa los bytes brutos de esa columna en un objeto Java sin realizar ninguna validación. Por lo tanto, un usuario autenticado que pueda ejecutar consultas nativas puede introducir una carga útil serializada maliciosa en el conjunto de resultados y desencadenar la ejecución de código arbitrario en el servidor que aloja Metabase.
A la vulnerabilidad se le asignó una puntuación CVSS de 9.9, lo que refleja las condiciones previas mínimas requeridas y la ejecución completa de código en el lado del servidor que resulta de una explotación exitosa.
Metabase distribuye dos ediciones paralelas a partir del mismo ciclo de lanzamiento. La edición de código abierto utiliza números de versión con el prefijo 0, por ejemplo, v0.61.1. La edición empresarial (comercial) utiliza números de versión con el prefijo 1, por ejemplo, v1.61.1. Ambas ediciones comparten el mismo código base subyacente y se lanzan juntas, por lo que una vulnerabilidad que afecta a v1.61.0 afecta igualmente a v0.61.0. A lo largo de este informe, los números de versión se escriben usando el prefijo empresarial 1.xx, pero cada versión afectada se corresponde directamente con su contraparte de código abierto 0.xx reemplazando el 1 inicial por 0.
Tanto CVE-2026-59826 como CVE-2026-59827 se divulgaron juntos en julio de 2026. Comparten rangos de versiones superpuestos pero tienen diferentes puntos de parche.
Las versiones empresariales vulnerables son 1.58.0 a 1.58.14, 1.59.0 a 1.59.11, 1.60.0 a 1.60.6.2 y 1.61.0 a 1.61.1.3. Las versiones de código abierto correspondientes son 0.58.0 a 0.58.14, 0.59.0 a 0.59.11, 0.60.0 a 0.60.6.2 y 0.61.0 a 0.61.1.3.
Se emitió un parche interno por primera vez como 1.61.1.4 (empresarial) y 0.61.1.4 (código abierto). La primera versión corregida disponible públicamente en la línea 1.61 es 1.61.2 (v1.61.2.x / v0.61.2.x). Las instancias de Metabase Cloud fueron parcheadas automáticamente por el proveedor.
Las versiones empresariales vulnerables son 1.55.0 a 1.58.15.0, 1.59.0 a 1.59.11, 1.60.0 a 1.60.6.2 y 1.61.0 hasta toda la línea 1.61.1.x. La primera versión pública completamente parcheada es 1.61.2 (v1.61.2.x / v0.61.2.x). El alcance de CVE-2026-59826 es más amplio, llegando hasta la línea de versiones 1.55, lo que refleja la presencia más prolongada de la ruta de código de creación de base de datos insuficientemente validada que explota.
El mecanismo de serialización de Java permite que un objeto en memoria se convierta en un flujo plano de bytes, se almacene o transmita, y luego se reconstruya llamando a ObjectInputStream.readObject(). La propiedad crítica de este mecanismo es que la reconstrucción ejecuta código. Los constructores de clase, las sobrescrituras de readObject y los finalizadores se ejecutan durante la deserialización. Si los bytes que se leen provienen de una fuente no confiable, un atacante puede manipularlos para desencadenar llamadas a métodos arbitrarios a través de una secuencia de clases legítimas existentes ya cargadas en la JVM. Estas secuencias se conocen como cadenas de gadgets.
Las cadenas de gadgets no requieren introducir ningún código nuevo en la aplicación. Explotan el cableado de clases de bibliotecas existentes cuyos métodos normales, cuando se llaman en el orden correcto durante la deserialización, eventualmente alcanzan un sumidero como Runtime.exec(). Herramientas como ysoserial existen específicamente para generar estas cargas útiles para bibliotecas ampliamente implementadas como Apache Commons Collections, Spring Framework y otras.
H2 es una base de datos relacional integrada puramente en Java. Define un tipo de columna SQL especial llamado OTHER que actúa como un paso directo para objetos Java arbitrarios. Cuando H2 almacena un valor en una columna OTHER, escribe los bytes producidos por ObjectOutputStream de Java. Cuando lee el valor de vuelta, llama a ObjectInputStream.readObject() para reconstruir el objeto. Los bytes serializados brutos también se pueden proporcionar directamente en una consulta usando la sintaxis hexadecimal literal de H2:
SELECT CAST(X'ACED0005...' AS OTHER);
-- or
SELECT X'ACED0005...'::OTHER;
El prefijo ACED seguido de 0005 es el número mágico de flujo de serialización de Java y la versión del protocolo. Cualquier cadena hexadecimal que comience con ACED0005 es un flujo de objetos serializados de Java.
Cuando H2 procesa esta consulta, deserializa los bytes hexadecimales en el lado de la base de datos. El objeto resultante se pasa luego a la aplicación llamante a través del ResultSet JDBC. Si la aplicación inspecciona el valor de la columna — por ejemplo, para formatearlo para mostrarlo — puede desencadenar procesamiento adicional. Esto es exactamente lo que hace Metabase en la ruta de código vulnerable.
Metabase recibe el ResultSet JDBC del controlador H2 e inspecciona los metadatos de las columnas para decidir cómo representar cada valor para el usuario. Cuando encuentra una columna con el tipo JDBC Types.OTHER (también reportado como JAVA_OBJECT), las versiones vulnerables de Metabase intentan deserializar los bytes brutos para producir una representación visualizable. Esta llamada de deserialización, ObjectInputStream.readObject(), se ejecuta sin ningún filtro de lista blanca ni validación de clase.
La secuencia de eventos es:
OTHER que contiene una carga útil serializada manipulada.JAVA_OBJECT en el ResultSet.OTHER y llama a readObject() en los bytes.Runtime.exec() y ejecutando el comando del atacante como el usuario del sistema operativo que ejecuta el proceso de Metabase.Las versiones parcheadas resuelven el problema inspeccionando los metadatos de los resultados JDBC antes de intentar cualquier deserialización. Si una columna está tipificada como JAVA_OBJECT, Metabase ahora la rechaza directamente en lugar de intentar analizarla.